source: trunk/src/win32k/dev32/d32init.c@ 5224

Last change on this file since 5224 was 5224, checked in by bird, 25 years ago

CallGate changes.

File size: 62.4 KB
Line 
1/* $Id: d32init.c,v 1.37 2001-02-21 07:44:57 bird Exp $
2 *
3 * d32init.c - 32-bits init routines.
4 *
5 * Copyright (c) 1998-1999 knut st. osmundsen
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants *
13*******************************************************************************/
14/*
15 * Calltab entry sizes.
16 */
17#define OVERLOAD16_ENTRY 0x18
18#define OVERLOAD32_ENTRY 0x14
19#define IMPORT16_ENTRY 0x08
20#define IMPORT32_ENTRY 0x08
21#define VARIMPORT_ENTRY 0x10
22
23#if 0
24 #define kprintf2(a) kprintf
25#else
26 #define kprintf2(a) {}//
27#endif
28
29#define INCL_DOSERRORS
30#define INCL_NOPMAPI
31#define LDR_INCL_INITONLY
32#define INCL_OS2KRNL_ALL
33#define INCL_OS2KRNL_LDR
34
35/*******************************************************************************
36* Header Files *
37*******************************************************************************/
38#include <os2.h>
39
40#include <string.h>
41
42#include "devSegDf.h"
43#include "OS2Krnl.h"
44#include "options.h"
45#include "dev1632.h"
46#include "dev32.h"
47#include "dev32hlp.h"
48#include "probkrnl.h"
49#include "log.h"
50#include "asmutils.h"
51#include "malloc.h"
52#include "ldr.h"
53#include "macros.h"
54#include "errors.h"
55
56#ifdef R3TST
57 #include "test.h"
58#endif
59
60
61/*******************************************************************************
62* Global Variables *
63*******************************************************************************/
64#ifdef DEBUG
65static char * apszPE[] = {"FLAGS_PE_NOT", "FLAGS_PE_PE2LX", "FLAGS_PE_PE", "FLAGS_PE_MIXED", "!invalid!"};
66static char * apszPEOneObject[] = {"FLAGS_PEOO_DISABLED", "FLAGS_PEOO_ENABLED", "FLAGS_PEOO_FORCED", "!invalid!"};
67static char * apszInfoLevel[] = {"INFOLEVEL_QUIET", "INFOLEVEL_ERROR", "INFOLEVEL_WARNING", "INFOLEVEL_INFO", "INFOLEVEL_INFOALL", "!invalid!"};
68#endif
69PMTE pKrnlMTE = NULL;
70PSMTE pKrnlSMTE = NULL;
71POTE pKrnlOTE = NULL;
72
73
74/*******************************************************************************
75* Internal Functions *
76*******************************************************************************/
77 ULONG readnum(const char *pszNum);
78_Inline int ModR_M_32bit(char bModRM);
79_Inline int ModR_M_16bit(char bModRM);
80int interpretFunctionProlog32(char *pach, BOOL fOverload);
81int interpretFunctionProlog16(char *pach, BOOL fOverload);
82int importTabInit(void);
83#ifdef R3TST
84PMTE GetOS2KrnlMTETst(void);
85void R3TstFixImportTab(void);
86#endif
87PSZ SECCALL nopSecPathFromSFN(SFN hFile);
88
89
90
91/* externs located in 16-bit data segement in ProbKrnl.c */
92extern ULONG _TKSSBase16;
93extern USHORT _R0FlatCS16;
94extern USHORT _R0FlatDS16;
95
96/* extern(s) located in calltab.asm */
97extern char callTab[1];
98extern unsigned auFuncs[NBR_OF_KRNLIMPORTS];
99
100
101/**
102 * Ring-0, 32-bit, init function.
103 * @returns Status word.
104 * @param pRpInit Pointer init request packet.
105 * @sketch Set TKSSBase32.
106 * Set default parameters.
107 * Parse command line options.
108 * Show (kprint) configuration.
109 * Init heap.
110 * Init ldr.
111 * Init procs. (overloaded ldr procedures)
112 * @status completely implemented.
113 * @author knut st. osmundsen
114 */
115USHORT _loadds _Far32 _Pascal R0Init32(RP32INIT *pRpInit)
116{
117 char * pszTmp2;
118 char * pszTmp;
119 ULONG ul;
120 APIRET rc;
121 LOCKHANDLE lockhandle;
122
123 pulTKSSBase32 = (PULONG)_TKSSBase16;
124
125 /*---------------------*/
126 /* commandline options */
127 /*---------------------*/
128 kprintf(("Options start\n"));
129 pszTmp = strpbrk(pRpInit->InitArgs, "-/");
130 while (pszTmp != NULL)
131 {
132 int cch;
133 pszTmp++; //skip [-/]
134 cch = strlen(pszTmp);
135 switch (*pszTmp)
136 {
137 case '1': /* All-In-One-Object fix - temporary...- -1<-|+|*> */
138 if (pszTmp[1] == '-')
139 options.fPEOneObject = FLAGS_PEOO_DISABLED;
140 else if (pszTmp[1] == '+')
141 options.fPEOneObject = FLAGS_PEOO_ENABLED;
142 else
143 options.fPEOneObject = FLAGS_PEOO_FORCED;
144 break;
145
146 case 'c':
147 case 'C': /* -C[1|2|3|4] or -Com:[1|2|3|4] - com-port no, def:-C2 */
148 pszTmp2 = strpbrk(pszTmp, ":=/- ");
149 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
150 pszTmp2++;
151 else
152 pszTmp2 = pszTmp + 1;
153 ul = readnum(pszTmp2);
154 switch (ul)
155 {
156 case 1: options.usCom = OUTPUT_COM1; break;
157 case 2: options.usCom = OUTPUT_COM2; break;
158 case 3: options.usCom = OUTPUT_COM3; break;
159 case 4: options.usCom = OUTPUT_COM4; break;
160 }
161 break;
162
163 case 'd':
164 case 'D':
165 pszTmp2 = strpbrk(pszTmp, ":=/- ");
166 if (pszTmp2 != NULL
167 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
168 )
169 options.fDllFixes = FALSE;
170 else
171 options.fDllFixes = TRUE;
172 break;
173
174 case 'e':
175 case 'E':/* Elf or EXe */
176 pszTmp2 = strpbrk(pszTmp, ":=/- ");
177 if (pszTmp[1] != 'x' && pszTmp[1] != 'X')
178 {
179 options.fElf = !(pszTmp2 != NULL
180 && ( pszTmp2[1] == 'N' || pszTmp2[1] == 'n'
181 || pszTmp2[1] == 'D' || pszTmp2[1] == 'd'));
182 }
183 else
184 {
185 options.fExeFixes = !(pszTmp2 != NULL
186 && ( pszTmp2[1] == 'N' || pszTmp2[1] == 'n'
187 || pszTmp2[1] == 'D' || pszTmp2[1] == 'd'));
188 }
189 break;
190
191 case 'f':
192 case 'F': /* -F[..]<:|=| >[<Y..|E..| > | <N..|D..>] - force preload */
193 pszTmp2 = strpbrk(pszTmp, ":=/- ");
194 if (pszTmp2 == NULL
195 || (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y' || pszTmp2[1] == 'E' || pszTmp2[1] == 'e')
196 )
197 options.fForcePreload = TRUE;
198 else
199 options.fForcePreload = FALSE;
200 break;
201
202 case 'h':
203 case 'H': /* Heap options */
204 pszTmp2 = strpbrk(pszTmp, ":=/- ");
205 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
206 {
207 ul = readnum(pszTmp2 + 1);
208 if (ul > 0x1000UL && ul < 0x2000000UL) /* 4KB < ul < 32MB */
209 {
210 if (strnicmp(pszTmp, "heapm", 5) == 0)
211 options.cbSwpHeapMax = ul;
212 else
213 options.cbSwpHeapInit = ul;
214 }
215 }
216 break;
217
218 case 'j':
219 case 'J': /* -Java:<Yes|No> */
220 pszTmp2 = strpbrk(pszTmp, ":=/- ");
221 options.fJava =
222 pszTmp2 != NULL
223 && (int)(pszTmp2-pszTmp) < cch-1
224 && (*pszTmp2 == ':' || *pszTmp2 == '=')
225 && (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y');
226 break;
227
228 case 'l':
229 case 'L': /* -L[..]<:|=| >[<Y..|E..| > | <N..|D..>] */
230 pszTmp2 = strpbrk(pszTmp, ":=/- ");
231 if (pszTmp2 != NULL
232 && (pszTmp2[1] == 'Y' ||pszTmp2[1] == 'y' || pszTmp2[1] == 'E' || pszTmp2[1] == 'e')
233 )
234 options.fLogging = TRUE;
235 else
236 options.fLogging = FALSE;
237 break;
238
239 case 'n':
240 case 'N': /* NoLoader */
241 options.fNoLoader = TRUE;
242 break;
243
244 case 'p':
245 case 'P': /* PE */
246 pszTmp2 = strpbrk(pszTmp, ":=/- ");
247 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
248 {
249 pszTmp2++;
250 if (strnicmp(pszTmp2, "pe2lx", 5) == 0)
251 options.fPE = FLAGS_PE_PE2LX;
252 else if (strnicmp(pszTmp2, "pe", 2) == 0)
253 options.fPE = FLAGS_PE_PE;
254 else if (strnicmp(pszTmp2, "mixed", 2) == 0)
255 options.fPE = FLAGS_PE_MIXED;
256 else if (strnicmp(pszTmp2, "not", 2) == 0)
257 options.fPE = FLAGS_PE_NOT;
258 else
259 kprintf(("R0Init32: invalid parameter -PE:...\n"));
260 }
261 else
262 kprintf(("R0Init32: invalid parameter -PE...\n"));
263 break;
264
265 case 'q':
266 case 'Q': /* quiet initialization */
267 options.fQuiet = TRUE;
268 break;
269
270 case 'r':
271 case 'R': /* ResHeap options or REXX option */
272 pszTmp2 = strpbrk(pszTmp, ":=/- ");
273 if ( (pszTmp[1] == 'E' || pszTmp[1] == 'e')
274 && (pszTmp[2] == 'X' || pszTmp[2] == 'x'))
275 { /* REXX */
276 options.fREXXScript =
277 pszTmp2 != NULL
278 && (int)(pszTmp2-pszTmp) < cch-1
279 && (*pszTmp2 == ':' || *pszTmp2 == '=')
280 && (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y');
281 }
282 else
283 { /* ResHeap options */
284 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
285 {
286 ul = readnum(pszTmp2 + 1);
287 if (ul > 0x1000UL && ul < 0x700000UL) /* 4KB < ul < 7MB */
288 {
289 if (strnicmp(pszTmp, "resheapm", 8) == 0)
290 options.cbResHeapMax = ul;
291 else
292 options.cbResHeapInit = ul;
293 }
294 }
295 }
296 break;
297
298 case 's':
299 case 'S': /* Sym:<filename> or Script:<Yes|No> or Smp */
300 /* SMP kernel */
301 pszTmp2 = strpbrk(pszTmp, ":=/- ");
302 if (pszTmp[1] == 'c' || pszTmp[1] == 'C')
303 {
304 options.fUNIXScript =
305 pszTmp2 != NULL
306 && (int)(pszTmp2-pszTmp) < cch-1
307 && (*pszTmp2 == ':' || *pszTmp2 == '=')
308 && (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y');
309 }
310 break;
311
312 case 'v':
313 case 'V': /* verbose initialization */
314 options.fQuiet = FALSE;
315 break;
316
317 case 'w':
318 case 'W': /* ModuleBase info level; -W<n> or -Warning:<n> */
319 if (pszTmp[1] >= '0' && pszTmp[1] <= '4')
320 options.ulInfoLevel = pszTmp[1] - '0';
321 else
322 {
323 pszTmp2 = strpbrk(pszTmp, ":=/- ");
324 if (pszTmp2 != NULL && (*pszTmp2 == ':' || *pszTmp2 == '='))
325 pszTmp2++;
326 else
327 pszTmp2 = pszTmp + 1;
328
329 if (*pszTmp2 >= '0' && *pszTmp2 <= '4')
330 options.ulInfoLevel = *pszTmp2 - '0';
331 }
332 break;
333
334 }
335 pszTmp = strpbrk(pszTmp, "-/");
336 }
337
338 /* heap min/max corrections */
339 if (options.cbSwpHeapInit > options.cbSwpHeapMax)
340 options.cbSwpHeapMax = options.cbSwpHeapInit;
341 if (options.cbResHeapInit > options.cbResHeapMax)
342 options.cbResHeapMax = options.cbResHeapInit;
343
344 /* Log option summary */
345 #ifdef DEBUG
346 kprintf(("Options - Summary - Start\n"));
347 if (options.fQuiet)
348 kprintf(("\tQuiet init\n"));
349 else
350 kprintf(("\tVerbose init\n"));
351
352 if (options.fLogging)
353 kprintf(("\tlogging enabled\n"));
354 else
355 kprintf(("\tlogging disabled\n"));
356 kprintf(("\tCom port no.%03xh\n", options.usCom));
357
358 kprintf(("\tKernel: v%d.%d build %d%c type ",
359 options.usVerMajor,
360 options.usVerMinor,
361 options.ulBuild,
362 (options.fKernel & KF_REV_MASK)
363 ? ((options.fKernel & KF_REV_MASK) >> KF_REV_SHIFT) + 'a'-1
364 : ' '
365 ));
366 if (options.fKernel & KF_SMP)
367 kprintf(("SMP "));
368 else if (options.fKernel & KF_W4)
369 kprintf(("W4 "));
370 else
371 kprintf(("UNI "));
372 if (options.fKernel & KF_DEBUG)
373 kprintf(("DEBUG\n"));
374 else
375 kprintf(("\n"));
376
377 kprintf(("\tfPE=%d (%s)\n", options.fPE, apszPE[MIN(options.fPE, 5)]));
378 kprintf(("\tfPEOneObject=%d (%s)\n", options.fPEOneObject, apszPEOneObject[MIN(options.fPEOneObject, 3)]));
379 kprintf(("\tulInfoLevel=%d (%s)\n", options.ulInfoLevel, apszInfoLevel[MIN(options.ulInfoLevel, 5)]));
380 kprintf(("\tfElf=%d\n", options.fElf));
381 kprintf(("\tfUNIXScript=%d\n", options.fUNIXScript));
382 kprintf(("\tfREXXScript=%d\n", options.fREXXScript));
383 kprintf(("\tfJAVA=%d\n", options.fJava));
384 kprintf(("\tfNoLoader=%d\n", options.fNoLoader));
385 kprintf(("\tcbSwpHeapInit=0x%08x cbSwpHeapMax=0x%08x\n",
386 options.cbSwpHeapInit, options.cbSwpHeapMax));
387 kprintf(("\tcbResHeapInit=0x%08x cbResHeapMax=0x%08x\n",
388 options.cbResHeapInit, options.cbResHeapMax));
389 kprintf(("Options - Summary - End\n"));
390 #endif /* debug */
391 /* end option summary */
392
393
394 /*
395 * init sub-parts
396 */
397 /* heap */
398 if (heapInit(options.cbResHeapInit, options.cbResHeapMax,
399 options.cbSwpHeapInit, options.cbSwpHeapMax) != NO_ERROR)
400 return ERROR_D32_HEAPINIT_FAILED;
401
402 /* loader */
403 if (ldrInit() != NO_ERROR)
404 return ERROR_D32_LDR_INIT_FAILED;
405
406 /* functionoverrides */
407 if ((rc = importTabInit()) != NO_ERROR)
408 return (USHORT)rc;
409
410 /* apis */
411 #if 0
412 if ((rc = APIInit()) != NO_ERROR)
413 return (USHORT)rc;
414 #endif
415
416 /* callgate */
417 if ((rc = InitCallGate()) != NO_ERROR)
418 {
419 kprintf(("R0Init32: InitCallGate failed with rc=%d\n", rc));
420 return (USHORT)rc;
421 }
422
423
424 /*
425 * Lock the 32-bit objects/segments and 16-bit datasegment in memory
426 */
427 /* 32-bit code segment */
428 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
429 rc = D32Hlp_VMLock2(&CODE32START,
430 ((unsigned)&CODE32END & ~0xFFF) - (unsigned)&CODE32START, /* Round down so we don't overlap with the next request. */
431 VMDHL_LONG,
432 SSToDS(&lockhandle));
433 if (rc != NO_ERROR)
434 kprintf(("code segment lock failed with with rc=%d\n", rc));
435
436 /* 32-bit data segment */
437 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
438 rc = D32Hlp_VMLock2(callTab,
439 &CONST32_ROEND - (char*)callTab,
440 VMDHL_LONG | VMDHL_WRITE,
441 SSToDS(&lockhandle));
442 if (rc != NO_ERROR)
443 kprintf(("data segment lock failed with with rc=%d\n", rc));
444
445 /* 16-bit data segment - is this really necessary? - no!!! */
446 #if 0 /* This should not be necessary!!! it's allocated from the kernel resident heap if I am not much mistaken. */
447 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
448 rc = D32Hlp_VMLock2(&DATA16START,
449 &DATA16END - &DATA16START,
450 VMDHL_LONG | VMDHL_WRITE,
451 SSToDS(&lockhandle));
452 if (rc != NO_ERROR)
453 kprintf(("16-bit data segment lock failed with with rc=%d\n", rc));
454 #endif
455
456 return NO_ERROR;
457}
458
459
460/**
461 * Reads a number (unsigned long integer) for a string.
462 * @returns number read, ~0UL on error / no number read.
463 * @param pszNum Pointer to the string containing the number.
464 * @status competely implemented.
465 * @author knut st. osmundsen
466 */
467ULONG readnum(const char *pszNum)
468{
469 ULONG ulRet = 0;
470 ULONG ulBase = 10;
471 int i = 0;
472
473 /* determin ulBase */
474 if (*pszNum == '0')
475 if (pszNum[1] == 'x' || pszNum[1] == 'X')
476 {
477 ulBase = 16;
478 pszNum += 2;
479 }
480 else
481 {
482 ulBase = 8;
483 i = 1;
484 }
485
486 /* read digits */
487 while (ulBase == 16 ? (pszNum[i] >= '0' && pszNum[i] <= '9') || (pszNum[i] >= 'a' && pszNum[i] <= 'f') || (pszNum[i] >= 'A' && pszNum[i] <= 'F')
488 : (pszNum[i] >= '0' && pszNum[i] <= (ulBase == 10 ? '9' : '7'))
489 )
490 {
491 ulRet *= ulBase;
492 if (ulBase <= 10)
493 ulRet += pszNum[i] - '0';
494 else
495 ulRet += pszNum[i] - (pszNum[i] >= 'A' ? 'A' - 10 : (pszNum[i] >= 'a' ? 'a' + 9 : '0'));
496
497 i++;
498 }
499
500 return i > 0 ? ulRet : ~0UL;
501}
502
503
504/**
505 * Get kernel OTEs
506 * This function set pKrnlMTE, pKrnlSMTE and pKrnlOTE.
507 * @returns Strategy return code:
508 * STATUS_DONE on success.
509 * STATUS_DONE | STERR | errorcode on failure.
510 * @param pKrnlInfo Pointer to output buffer.
511 * If NULL only the three global variables are set.
512 * @status completely implemented and tested.
513 * @author knut st. osmundsen
514 * @remark Called from IOCtl.
515 * WARNING! This function is called before the initroutine (R0INIT)!
516 */
517USHORT _loadds _Far32 _Pascal GetKernelInfo32(PKRNLINFO pKrnlInfo)
518{
519 int i;
520 USHORT usRc;
521
522 /* VerifyImporTab32 is called before the initroutine! */
523 pulTKSSBase32 = (PULONG)_TKSSBase16;
524
525 /* Find the kernel OTE table */
526#ifndef R3TST
527 pKrnlMTE = GetOS2KrnlMTE();
528#else
529 pKrnlMTE = GetOS2KrnlMTETst();
530#endif
531 if (pKrnlMTE != NULL)
532 {
533 pKrnlSMTE = pKrnlMTE->mte_swapmte;
534 if (pKrnlSMTE != NULL)
535 {
536 if (pKrnlSMTE->smte_objcnt <= MAXKRNLOBJECTS)
537 {
538 pKrnlOTE = pKrnlSMTE->smte_objtab;
539 if (pKrnlOTE != NULL)
540 {
541 /*
542 * Thats all?
543 */
544 if (pKrnlInfo == NULL)
545 return NO_ERROR;
546
547 pKrnlInfo->cObjects = (unsigned char)pKrnlSMTE->smte_objcnt;
548
549 /*
550 * Copy OTEs
551 */
552 for (i = 0; i < pKrnlInfo->cObjects; i++)
553 {
554 memcpy((void*)&pKrnlInfo->aObjects[i], &pKrnlOTE[i], sizeof(OTE));
555 kprintf2(("GetKernelInfo32: %d base=0x%08x size=0x%08x flags=0x%08x\n",
556 i, pKrnlOTE[i].ote_base, pKrnlOTE[i].ote_size, pKrnlOTE[i].ote_flags));
557 }
558 usRc = 0;
559
560 /*
561 * Search for internal revision stuff in the two first objects.
562 */
563 pKrnlInfo->ulBuild = 0;
564 for (i = 0; i < 2 && pKrnlInfo->ulBuild == 0; i++)
565 {
566 const char *psz = (const char*)pKrnlOTE[i].ote_base;
567 const char *pszEnd = psz + pKrnlOTE[i].ote_size - 50; /* Last possible search position. */
568
569 while (psz < pszEnd)
570 {
571 if (strncmp(psz, "Internal revision ", 18) == 0 && (psz[18] >= '0' && psz[18] <= '9'))
572 {
573 int j;
574 kprintf2(("GetKernelInfo32: found internal revision: '%s'\n", psz));
575
576 /* skip to end of "Internal revision " string. */
577 psz += 18;
578
579 /* Read number*/
580 while ((*psz >= '0' && *psz <= '9') || *psz == '.')
581 {
582 if (*psz != '.')
583 pKrnlInfo->ulBuild = (unsigned short)(pKrnlInfo->ulBuild * 10 + (*psz - '0'));
584 psz++;
585 }
586
587 /* Check if build number seems valid. */
588 if ( !(pKrnlInfo->ulBuild >= 8254 && pKrnlInfo->ulBuild < 8383) /* Warp 3 fp 32 -> fp 60 */
589 && !(pKrnlInfo->ulBuild >= 9023 && pKrnlInfo->ulBuild <= 9036) /* Warp 4 GA -> fp 12 */
590 && !(pKrnlInfo->ulBuild >= 14039 && pKrnlInfo->ulBuild < 14100) /* Warp 4.5 GA -> fp 40 */
591 && !(pKrnlInfo->ulBuild >= 6600 && pKrnlInfo->ulBuild <= 6678) /* Warp 2.1x fix?? (just for fun!) */
592 )
593 {
594 kprintf(("GetKernelInfo32: info summary: Build %d is invalid - invalid fixpack?\n", pKrnlInfo->ulBuild));
595 usRc = ERROR_D32_INVALID_BUILD;
596 break;
597 }
598
599 /* Check for any revision flag */
600 pKrnlInfo->fKernel = 0;
601 if ((*psz >= 'A' && *psz <= 'E') || (*psz >= 'a' && *psz <= 'e'))
602 {
603 pKrnlInfo->fKernel = (USHORT)((*psz - (*psz >= 'a' ? 'a'-1 : 'A'-1)) << KF_REV_SHIFT);
604 psz++;
605 }
606 if (*psz == 'F' || *psz == 'f' || *psz == ',') /* These are ignored! */
607 *psz++;
608
609 /* If this is an Aurora/Warp 4.5 or Warp 3 kernel there is more info! */
610 if (psz[0] == '_' && (psz[1] == 'S' || psz[1] == 's')) /* _SMP */
611 pKrnlInfo->fKernel |= KF_SMP;
612 else
613 if (*psz != ','
614 && ( (psz[0] == '_' && psz[1] == 'W' && psz[2] == '4') /* _W4 */
615 || (psz[0] == '_' && psz[1] == 'U' && psz[2] == 'N' && psz[3] == 'I' && psz[4] == '4') /* _UNI4 */
616 )
617 )
618 pKrnlInfo->fKernel |= KF_W4 | KF_UNI;
619 else
620 pKrnlInfo->fKernel |= KF_UNI;
621
622
623 /* Check if its a debug kernel (look for DEBUG at start of object 3-5) */
624 j = 3;
625 while (j < 5)
626 {
627 /* There should be no iopl object preceding the debugger data object. */
628 if ((pKrnlOTE[j].ote_flags & OBJIOPL) != 0)
629 break;
630 /* Is this is? */
631 if ((pKrnlOTE[j].ote_flags & OBJINVALID) == 0
632 && (pKrnlOTE[j].ote_flags & (OBJREAD | OBJWRITE)) == (OBJREAD | OBJWRITE)
633 && strncmp((char*)pKrnlOTE[j].ote_base, "DEBUG", 5) == 0)
634 {
635 pKrnlInfo->fKernel |= KF_DEBUG;
636 break;
637 }
638 j++;
639 }
640
641 /* Display info */
642 kprintf(("GetKernelInfo32: info summary: Build %d, fKernel=0x%x\n",
643 pKrnlInfo->ulBuild, pKrnlInfo->fKernel));
644
645 /* Break out */
646 break;
647 }
648
649 /* next */
650 psz++;
651 } /* while loop searching for "Internal revision " */
652 } /* for loop on objects 0-1. */
653
654 /* Set error code if not found */
655 if (pKrnlInfo->ulBuild == 0)
656 {
657 usRc = ERROR_D32_BUILD_INFO_NOT_FOUND;
658 kprintf(("GetKernelInfo32: Internal revision was not found!\n"));
659 }
660 }
661 else
662 usRc = ERROR_D32_NO_OBJECT_TABLE;
663 }
664 else
665 usRc = ERROR_D32_TOO_MANY_OBJECTS;
666 }
667 else
668 usRc = ERROR_D32_NO_SWAPMTE;
669 }
670 else
671 usRc = ERROR_D32_GETOS2KRNL_FAILED;
672
673 if (usRc != NO_ERROR)
674 kprintf(("GetKernelInfo32: failed. usRc = %d\n", usRc));
675
676 return (USHORT)(usRc | (usRc != NO_ERROR ? STATUS_DONE | STERR : STATUS_DONE));
677}
678
679
680
681/**
682 * Functions which cacluates the instructionsize given a ModR/M byte.
683 * @returns Number of bytes to add to cb and pach.
684 * @param bModRM ModR/M byte.
685 * @status completely implemented.
686 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
687 */
688int ModR_M_32bit(char bModRM)
689{
690 if ((bModRM & 0xc0) == 0x80 /* ex. mov ax,[ebp+11145543h] */
691 || ((bModRM & 0xc0) == 0 && (bModRM & 0x07) == 5)) /* ex. mov ebp,[0ff231234h] */
692 { /* 32-bit displacement */
693 return 5 + ((bModRM & 0x7) == 0x4); // + SIB
694 }
695 else if ((bModRM & 0xc0) == 0x40) /* ex. mov ecx,[esi]+4fh */
696 { /* 8-bit displacement */
697 return 2 + ((bModRM & 0x7) == 0x4); // + SIB
698 }
699 /* no displacement (only /r byte) */
700 return 1;
701}
702
703
704/**
705 * Functions which cacluates the instructionsize given a ModR/M byte.
706 * @returns Number of bytes to add to cb and pach.
707 * @param bModRM ModR/M byte.
708 * @status completely implemented.
709 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
710 */
711int ModR_M_16bit(char bModRM)
712{
713 if ((bModRM & 0xc0) == 0x80 /* ex. mov ax,[ebp+11145543h] */
714 || ((bModRM & 0xc0) == 0 && (bModRM & 0x07) == 5)) /* ex. mov ebp,[0ff231234h] */
715 { /* 16-bit displacement */
716 return 4;
717 }
718 else if ((bModRM & 0xc0) == 0x40) /* ex. mov ecx,[esi]+4fh */
719 { /* 8-bit displacement */
720 return 2;
721 }
722 /* no displacement (only /r byte) */
723 return 1;
724}
725
726
727
728
729
730/**
731 * 32-bit! Interpret function prolog to find where to jmp back.
732 * @returns Length of prolog need to be copied - which is also the offset of
733 * where the jmp instr should be placed.
734 * On error it returns 0.
735 * @param pach Pointer to prolog.
736 * @param fOverload TRUE: Function is to be overloaded.
737 * FALSE: Function is to be imported.
738 */
739int interpretFunctionProlog32(char *pach, BOOL fOverload)
740{
741 int cb = -3;
742 kprintf2(("interpretFunctionProlog32(0x%08x, %d):\n"
743 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
744 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
745 pach, fOverload,
746 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
747 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
748
749 /*
750 * check for the well known prolog (the only that is supported now)
751 * which is:
752 * push ebp
753 * mov ebp,esp
754 * or
755 * push ebp
756 * mov eax, dword ptr [xxxxxxxx]
757 * or
758 * sub esp, imm8
759 * push ebx
760 * push edi
761 *
762 * These are allowed when not overloading:
763 * mov eax, imm32
764 * jmp short
765 * or
766 * mov eax, imm32
767 * push ebp
768 * or
769 * mov ecx, r/m32
770 * or
771 * jmp dword
772 * or
773 * sub esp, imm8
774 * or
775 * call ptr16:32
776 * or
777 * enter imm16, imm8 (2.1x)
778 * or
779 * mov eax, imm32 (2.1x)
780 * <anything>
781 * or
782 * xor r32, r/m32
783 * or
784 * mov eax, msoff32
785 * or
786 * push edi
787 * mov eax, dword ptr [xxxxxxxx]
788 * or
789 * movzx esp, sp
790 * or
791 * call rel32
792 * popf
793 */
794 if ((pach[0] == 0x55 && (pach[1] == 0x8b || pach[1] == 0xa1)) /* the two first prologs */
795 ||
796 (pach[0] == 0x83 && pach[3] == 0x53 && pach[4] == 0x57) /* the third prolog */
797 ||
798 (pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55) && !fOverload) /* the two next prologs */
799 ||
800 (pach[0] == 0x8B && !fOverload) /* the next prolog */
801 ||
802 (pach[0] == 0xFF && !fOverload) /* the next prolog */
803 ||
804 (pach[0] == 0x83 && !fOverload) /* the next prolog */
805 ||
806 (pach[0] == 0x9a && !fOverload) /* the next prolog */
807 ||
808 (pach[0] == 0xc8) /* the next prolog */
809 ||
810 (pach[0] == 0xB8 && !fOverload) /* the next prolog */
811 ||
812 (pach[0] == 0x33 && !fOverload) /* the next prolog */
813 ||
814 (pach[0] == 0xa1 && !fOverload) /* the next prolog */
815 ||
816 (pach[0] == 0x57 && pach[1] == 0x8b && !fOverload) /* the next prolog */
817 ||
818 (pach[0] == 0x0f && pach[1] == 0xb7 && pach[2] == 0xe4 && !fOverload) /* the next prolog */
819 ||
820 (pach[0] == 0xe8 && pach[5] == 0x9d && !fOverload) /* the last prolog */
821 )
822 {
823 BOOL fForce = FALSE;
824 int cbWord = 4;
825 cb = 0;
826 while (cb < 5 || fForce) /* 5 is the size of a jump instruction. */
827 {
828 int cb2;
829 if (!fForce && cbWord != 4)
830 cbWord = 4;
831 fForce = FALSE;
832 switch (*pach)
833 {
834 case 0x0f:
835 if (pach[1] != 0xb7 && pach[2] != 0xe4) /* movzx esp, sp */
836 {
837 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
838 return -11;
839 }
840 pach += 2;
841 cb += 2;
842 break;
843
844
845 /* simple one byte prefixes */
846 case 0x2e: /* cs segment override */
847 case 0x36: /* ss segment override */
848 case 0x3e: /* ds segment override */
849 case 0x26: /* es segment override */
850 case 0x64: /* fs segment override */
851 case 0x65: /* gs segment override */
852 fForce = TRUE;
853 break;
854
855 case 0x66: /* 16 bit */
856 fForce = TRUE;
857 cbWord = 2;
858 break;
859
860 /* simple one byte instructions */
861 case 0x50: /* push ax */
862 case 0x51: /* push cx */
863 case 0x52: /* push dx */
864 case 0x53: /* push bx */
865 case 0x54: /* push sp */
866 case 0x55: /* push bp */
867 case 0x56: /* push si */
868 case 0x57: /* push di */
869 case 0x06: /* push es */
870 case 0x0e: /* push cs */
871 case 0x1e: /* push ds */
872 case 0x16: /* push ss */
873 break;
874
875 /* simple two byte instructions */
876 case 0xb0: /* mov al, imm8 */
877 case 0xb1: /* mov cl, imm8 */
878 case 0xb2: /* mov dl, imm8 */
879 case 0xb3: /* mov bl, imm8 */
880 case 0xb4: /* mov ah, imm8 */
881 case 0xb5: /* mov ch, imm8 */
882 case 0xb6: /* mov dh, imm8 */
883 case 0xb7: /* mov bh, imm8 */
884 case 0x2c: /* sub al, imm8 */
885 case 0x34: /* xor al, imm8 */
886 case 0x3c: /* cmp al, imm8 */
887 case 0x6a: /* push <byte> */
888 case 0xa0: /* mov al, moffs8 */
889 case 0xa2: /* mov moffs8, al */
890 pach++;
891 cb++;
892 break;
893
894 /* simple five byte instructions */
895 case 0xb8: /* mov eax, imm32 */
896 case 0xb9: /* mov ecx, imm32 */
897 case 0xba: /* mov edx, imm32 */
898 case 0xbb: /* mov ebx, imm32 */
899 case 0xbc: /* mov esx, imm32 */
900 case 0xbd: /* mov ebx, imm32 */
901 case 0xbe: /* mov esi, imm32 */
902 case 0xbf: /* mov edi, imm32 */
903 case 0x2d: /* sub eax, imm32 */
904 case 0x35: /* xor eax, imm32 */
905 case 0x3d: /* cmp eax, imm32 */
906 case 0x68: /* push <dword> */
907 case 0xa1: /* mov eax, moffs16 */
908 case 0xa3: /* mov moffs16, eax */
909 pach += cbWord;
910 cb += cbWord;
911 break;
912
913 /* fixed five byte instructions */
914 case 0xe8: /* call imm32 */
915 pach += 4;
916 cb += 4;
917 break;
918
919 /* complex sized instructions - "/r" */
920 case 0x30: /* xor r/m8, r8 */
921 case 0x31: /* xor r/m32, r32 */
922 case 0x32: /* xor r8, r/m8 */
923 case 0x33: /* xor r32, r/m32 */
924 case 0x38: /* cmp r/m8, r8 */
925 case 0x39: /* cmp r/m32, r32 */
926 case 0x3a: /* cmp r8, r/m8 */
927 case 0x3b: /* cmp r32, r/m32 */
928 case 0x28: /* sub r/m8, r8 */
929 case 0x29: /* sub r/m32, r32 */
930 case 0x2a: /* sub r8, r/m8 */
931 case 0x2b: /* sub r32, r/m32 */
932 case 0x8b: /* mov /r */
933 case 0x8d: /* lea /r */
934 cb += cb2 = ModR_M_32bit(pach[1]);
935 pach += cb2;
936 break;
937
938 /* complex sized instruction - "/5 ib" */
939 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
940 case 0x83: /* 5: sub r/m32, imm8 7: cmp r/m32, imm8 */
941 if ((pach[1] & 0x38) == (5<<3)
942 || (pach[1] & 0x38) == (7<<3)
943 )
944 {
945 cb += cb2 = 1 + ModR_M_32bit(pach[1]); /* 1 is the size of the imm8 */
946 pach += cb2;
947 }
948 else
949 {
950 kprintf(("interpretFunctionProlog32: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
951 return -3;
952 }
953 break;
954
955 /* complex sized instruction - "/digit id" */
956 case 0x81: /* sub r/m32, imm32 + more instructions! */
957 if ((pach[1] & 0x38) == (5<<3) /* sub r/m32, imm32 */
958 || (pach[1] & 0x38) == (7<<3) /* cmp r/m32, imm32 */
959 )
960 {
961 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
962 pach += cb2;
963 }
964 else
965 {
966 kprintf(("interpretFunctionProlog32: unknown instruction (-2) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
967 return -2;
968 }
969 break;
970
971 case 0x9a: /* call ptr16:32 */
972 cb += cb2 = 6;
973 pach += cb2;
974 break;
975
976 case 0xc8: /* enter imm16, imm8 */
977 cb += cb = 3;
978 pach += cb2;
979 break;
980
981 /*
982 * jmp /digit
983 */
984 case 0xff:
985 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
986 pach += cb2;
987 break;
988
989 default:
990 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
991 return 0;
992 }
993 pach++;
994 cb++;
995 }
996 }
997 else
998 {
999 kprintf(("interpretFunctionProlog32: unknown prolog start. 0x%x 0x%x 0x%x 0x%x 0x%x\n",
1000 pach[0], pach[1], pach[2], pach[3], pach[4]));
1001 cb = 0;
1002 }
1003 return cb;
1004}
1005
1006
1007/**
1008 * 16-bit! Interpret function prolog to find where to jmp back.
1009 * @returns Length of prolog need to be copied - which is also the offset of
1010 * where the jmp instr should be placed.
1011 * On error it returns 0.
1012 * @param pach Pointer to prolog.
1013 * @param fOverload TRUE: Function is to be overloaded.
1014 * FALSE: Function is to be imported.
1015 */
1016int interpretFunctionProlog16(char *pach, BOOL fOverload)
1017{
1018 int cb = -7;
1019
1020 kprintf2(("interpretFunctionProlog16(0x%08x, %d):\n"
1021 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
1022 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
1023 pach, fOverload,
1024 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
1025 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
1026 /*
1027 * Check for the well known prolog (the only that is supported now)
1028 * which is:
1029 * push 2
1030 */
1031 if (*pach == 0x6A) /* push 2 (don't check for the 2) */
1032 {
1033 BOOL fForce;
1034 int cOpPrefix = 0;
1035 cb = 0;
1036 while (cb < 8 || fForce) /* 8 is the size of a 66h prefixed far jump instruction. */
1037 {
1038 int cb2;
1039 fForce = FALSE;
1040 switch (*pach)
1041 {
1042 case 0x06: /* push es */
1043 case 0x0e: /* push cs */
1044 case 0x1e: /* push ds */
1045 case 0x16: /* push ss */
1046 break;
1047
1048 case 0x0f: /* push gs and push fs */
1049 if (pach[1] != 0xA0 && pach[1] != 0xA8)
1050 {
1051 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1052 return -11;
1053 }
1054 pach++;
1055 cb++;
1056 break;
1057
1058 case 0x50: /* push ax */
1059 case 0x51: /* push cx */
1060 case 0x52: /* push dx */
1061 case 0x53: /* push bx */
1062 case 0x54: /* push sp */
1063 case 0x55: /* push bp */
1064 case 0x56: /* push si */
1065 case 0x57: /* push di */
1066 break;
1067
1068 case 0x2e: /* cs segment override */
1069 case 0x36: /* ss segment override */
1070 case 0x3e: /* ds segment override */
1071 case 0x26: /* es segment override */
1072 case 0x64: /* fs segment override */
1073 case 0x65: /* gs segment override */
1074 fForce = TRUE;
1075 if (cOpPrefix > 0)
1076 cOpPrefix++;
1077 break;
1078
1079 case 0x66:
1080 cOpPrefix = 2; /* it's decremented once before it's used. */
1081 fForce = TRUE;
1082 break;
1083
1084 case 0x6a: /* push <byte> */
1085 pach++;
1086 cb++;
1087 break;
1088
1089 case 0x68: /* push <word> */
1090 if (cOpPrefix > 0)
1091 {
1092 pach += 2;
1093 cb += 2;
1094 }
1095 pach += 2;
1096 cb += 2;
1097 break;
1098
1099 case 0x8b: /* mov /r */
1100 if ((pach[1] & 0xc0) == 0x80 /* ex. mov ax,bp+1114h */
1101 || ((pach[1] & 0xc0) == 0 && (pach[1] & 0x7) == 6)) /* ex. mov bp,0ff23h */
1102 { /* 16-bit displacement */
1103 if (cOpPrefix > 0)
1104 {
1105 pach += 2;
1106 cb += 2;
1107 }
1108 pach += 3;
1109 cb += 3;
1110 }
1111 else
1112 if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
1113 { /* 8-bit displacement */
1114 pach += 2;
1115 cb += 2;
1116 }
1117 else
1118 { /* no displacement (only /r byte) */
1119 pach++;
1120 cb++;
1121 }
1122 break;
1123
1124 /* complex sized instruction - "/5 ib" */
1125 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
1126 case 0x83: /* 5: sub r/m16, imm8 7: cmp r/m16, imm8 */
1127 if ((pach[1] & 0x38) == (5<<3)
1128 || (pach[1] & 0x38) == (7<<3)
1129 )
1130 {
1131 cb += cb2 = 1 + ModR_M_16bit(pach[1]); /* 1 is the size of the imm8 */
1132 pach += cb2;
1133 }
1134 else
1135 {
1136 kprintf(("interpretFunctionProlog16: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1137 return -3;
1138 }
1139 break;
1140
1141
1142 default:
1143 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1144 return 0;
1145 }
1146 pach++;
1147 cb++;
1148 if (cOpPrefix > 0)
1149 cOpPrefix--;
1150 }
1151 }
1152
1153 fOverload = fOverload;
1154 return cb;
1155}
1156
1157
1158/**
1159 * Verifies the aImportTab.
1160 * @returns 16-bit errorcode where the high byte is the procedure number which
1161 * the error occured on and the low byte the error code.
1162 * @remark Called from IOCtl.
1163 * WARNING! This function is called before the initroutine (R0INIT)!
1164 */
1165USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
1166{
1167 USHORT usRc;
1168 int i;
1169 int cb;
1170 int cbmax;
1171
1172 /* VerifyImporTab32 is called before the initroutine! */
1173 pulTKSSBase32 = (PULONG)_TKSSBase16;
1174
1175 /* Check that pKrnlOTE is set */
1176 usRc = GetKernelInfo32(NULL);
1177 if (usRc != NO_ERROR)
1178 return usRc;
1179
1180 /*
1181 * Verify aImportTab.
1182 */
1183 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1184 {
1185 /*
1186 * Debug info
1187 */
1188 kprintf2(("VerifyImportTab32: procedure no.%d is being checked: %s addr=0x%08x iObj=%d offObj=%d\n",
1189 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1190 aImportTab[i].iObject, aImportTab[i].offObject));
1191
1192 /* Verify that it is found */
1193 if (!aImportTab[i].fFound)
1194 {
1195 if (EPTNotReq(aImportTab[i]))
1196 continue;
1197 else
1198 {
1199 kprintf(("VerifyImportTab32: procedure no.%d was not fFound!\n", i));
1200 return (USHORT)(ERROR_D32_PROC_NOT_FOUND | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1201 }
1202 }
1203
1204 /* Verify read/writeable. */
1205 if ( aImportTab[i].iObject >= pKrnlSMTE->smte_objcnt /* object index valid? */
1206 || aImportTab[i].ulAddress < pKrnlOTE[aImportTab[i].iObject].ote_base /* address valid? */
1207 || aImportTab[i].ulAddress + 16 > (pKrnlOTE[aImportTab[i].iObject].ote_base +
1208 pKrnlOTE[aImportTab[i].iObject].ote_size) /* address valid? */
1209 || aImportTab[i].ulAddress - aImportTab[i].offObject
1210 != pKrnlOTE[aImportTab[i].iObject].ote_base /* offObject ok? */
1211 )
1212 {
1213 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address or object number.!\n"
1214 " %s addr=0x%08x iObj=%d offObj=%d\n",
1215 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1216 aImportTab[i].iObject, aImportTab[i].offObject));
1217 return (USHORT)(ERROR_D32_INVALID_OBJ_OR_ADDR | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1218 }
1219
1220
1221 #ifndef R3TST
1222 if (aImportTab[i].ulAddress < 0xff400000UL)
1223 {
1224 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address, %#08x!\n",
1225 i, aImportTab[i].ulAddress));
1226 return (USHORT)(ERROR_D32_INVALID_ADDRESS | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1227 }
1228 #endif
1229
1230 switch (aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ | EPT_WRAPPED))
1231 {
1232 case EPT_PROC:
1233 case EPT_PROCIMPORT:
1234 /*
1235 * Verify known function prolog.
1236 */
1237 if (EPT32BitEntry(aImportTab[i]))
1238 {
1239 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1240 cbmax = OVERLOAD32_ENTRY - 5; /* 5 = Size of the jump instruction */
1241 }
1242 else
1243 {
1244 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1245 cbmax = OVERLOAD16_ENTRY - 7; /* 7 = Size of the far jump instruction */
1246 }
1247
1248 /*
1249 * Check result of the function prolog interpretations.
1250 */
1251 if (cb <= 0 || cb > cbmax)
1252 { /* failed, too small or too large. */
1253 kprintf(("VerifyImportTab32: verify failed for procedure no.%d (cb=%d), %s\n", i, cb, aImportTab[i].achName));
1254 return (USHORT)(ERROR_D32_TOO_INVALID_PROLOG | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1255 }
1256 break;
1257
1258 case EPT_VARIMPORT:
1259 /* do nothing! */
1260 break;
1261
1262 default:
1263 kprintf(("VerifyImportTab32: invalid type/type not implemented. Proc no.%d, %s\n",i, aImportTab[i].achName));
1264 Int3(); /* temporary fix! */
1265 return (USHORT)(ERROR_D32_NOT_IMPLEMENTED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1266 }
1267 }
1268
1269 return NO_ERROR;
1270}
1271
1272
1273/**
1274 * Initiates the overrided functions.
1275 * @returns 16-bit errorcode where the high byte is the procedure number which
1276 * the error occured on and the low byte the error code.
1277 */
1278int importTabInit(void)
1279{
1280 int i;
1281 int cb;
1282 int cbmax;
1283 char * pchCTEntry; /* Pointer to current calltab entry. */
1284 ULONG flWP; /* CR0 WP flag restore value. */
1285
1286 /*
1287 * Apply build specific changes to the auFuncs table
1288 */
1289 if (options.ulBuild < 14053)
1290 {
1291 #ifdef DEBUG
1292 if (auFuncs[0] != (unsigned)myldrOpenPath)
1293 {
1294 kprintf(("importTabInit: ASSERTION FAILED auFuncs don't point at myldrOpenPath\n"));
1295 Int3();
1296 }
1297 #endif
1298 auFuncs[0] = (unsigned)myldrOpenPath_old;
1299 }
1300
1301#ifdef R3TST
1302 R3TstFixImportTab();
1303#endif
1304
1305 /*
1306 * verify proctable
1307 */
1308 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1309 {
1310 /* EPT_VARIMPORTs are skipped */
1311 if ((aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ)) == EPT_VARIMPORT)
1312 continue;
1313 /* EPT_NOT_REQ which is not found are set pointing to the nop function provided. */
1314 if (!aImportTab[i].fFound && EPTNotReq(aImportTab[i]))
1315 continue;
1316
1317 if (EPT32BitEntry(aImportTab[i]))
1318 {
1319 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1320
1321 cbmax = OVERLOAD16_ENTRY - 5; /* 5 = Size of the jump instruction */
1322 }
1323 else
1324 {
1325 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1326 cbmax = OVERLOAD16_ENTRY - 7; /* 7 = Size of the far jump instruction */
1327 }
1328 if (cb <= 0 || cb > cbmax)
1329 {
1330 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
1331 return ERROR_D32_VERIFY_FAILED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1332 }
1333 }
1334
1335 /*
1336 * rehook / import
1337 */
1338 pchCTEntry = &callTab[0];
1339 flWP = x86DisableWriteProtect();
1340 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1341 {
1342 switch (aImportTab[i].fType & ~EPT_WRAPPED)
1343 {
1344 /*
1345 * 32-bit procedure overload.
1346 * The overloading procedure is found in the auFuncs table (at the same index
1347 * as the overloaded procedure has in aImportTab).
1348 * The overloaded procedure is called by issuing a call to the callTab entry.
1349 */
1350 case EPT_PROC32:
1351 {
1352 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, TRUE);
1353 aImportTab[i].cbProlog = (char)cb;
1354 if (cb >= 5 && cb + 5 < OVERLOAD32_ENTRY) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
1355 { /* 5(2nd): size of jump instruction which jumps back to the original function after executing the prolog copied to the callTab entry for this function. */
1356 /*
1357 * Copy function prolog which will be overwritten by the jmp to calltabl.
1358 */
1359 memcpy(pchCTEntry, (void*)aImportTab[i].ulAddress, (size_t)cb);
1360
1361 /*
1362 * Make jump instruction which jumps from calltab to original function.
1363 * 0xE9 <four bytes displacement>
1364 * Note: the displacement is relative to the next instruction
1365 */
1366 pchCTEntry[cb] = 0xE9; /* jmp */
1367 *(unsigned long*)(void*)&pchCTEntry[cb+1] = aImportTab[i].ulAddress + cb - (unsigned long)&pchCTEntry[cb+5];
1368
1369 /*
1370 * Jump from original function to my function - an cli(?) could be needed here
1371 */
1372 *(char*)aImportTab[i].ulAddress = 0xE9; /* jmp */
1373 *(unsigned long*)(aImportTab[i].ulAddress + 1) = auFuncs[i] - (aImportTab[i].ulAddress + 5);
1374 }
1375 else
1376 { /* !fatal! - this could never happen really... */
1377 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1378 Int3(); /* ipe - later! */
1379 x86RestoreWriteProtect(flWP);
1380 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1381 }
1382 pchCTEntry += OVERLOAD32_ENTRY;
1383 break;
1384 }
1385
1386
1387 /*
1388 * 16-bit procedure overload.
1389 * Currently disabled due to expected problems when calltab is a 32-bit segment.
1390 */
1391 case EPT_PROC16:
1392 {
1393 kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
1394 Int3();
1395
1396 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, TRUE);
1397 aImportTab[i].cbProlog = (char)cb;
1398 if (cb >= 8 && cb + 7 < OVERLOAD16_ENTRY) /* 8: size of a 16:32 jump which jumps to my overloading function (prefixed with 66h in a 16-bit segment) */
1399 { /* 7: size of a 16:32 jump which is added to the call tab */
1400 /*
1401 * Copy function prolog which is to be overwritten.
1402 */
1403 memcpy(pchCTEntry, (void*)aImportTab[i].ulAddress, (size_t)cb);
1404
1405 /*
1406 * Create far jump from calltab to original function.
1407 * 0xEA <four byte target address> <two byte target selector>
1408 */
1409 pchCTEntry[cb] = 0xEA; /* jmp far ptr */
1410 *(unsigned long*)(void*)&pchCTEntry[cb+1] = aImportTab[i].offObject;
1411 *(unsigned short*)(void*)&pchCTEntry[cb+5] = aImportTab[i].usSel;
1412
1413 /*
1414 * jump from original function to my function - an cli(?) could be needed here
1415 * 0x66 0xEA <four byte target address> <two byte target selector>
1416 */
1417 *(char*)(aImportTab[i].ulAddress ) = 0x66; /* operandsize prefix */
1418 *(char*)(aImportTab[i].ulAddress + 1) = 0xEA; /* jmp far ptr */
1419 *(unsigned long*)(aImportTab[i].ulAddress + 2) = auFuncs[i]; /* FIXME? */
1420 *(unsigned short*)(aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
1421 }
1422 else
1423 { /* !fatal! - this could never happen really... */
1424 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1425 Int3(); /* ipe - later! */
1426 x86RestoreWriteProtect(flWP);
1427 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1428 }
1429 pchCTEntry += OVERLOAD16_ENTRY;
1430 break;
1431 }
1432
1433
1434 /*
1435 * 32-bit imported procedure.
1436 * This is called by issuing a near call to the callTab entry.
1437 */
1438 case EPT_PROCIMPORTNR32: /* Not required */
1439 if (!(pchCTEntry[6] = aImportTab[i].fFound))
1440 aImportTab[i].ulAddress = auFuncs[i];
1441 case EPT_PROCIMPORT32:
1442 {
1443 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, FALSE);
1444 aImportTab[i].cbProlog = (char)cb;
1445 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1446 {
1447 /*
1448 * Make jump instruction which jumps from calltab to original function.
1449 * 0xE9 <four bytes displacement>
1450 * Note: the displacement is relative to the next instruction
1451 */
1452 pchCTEntry[0] = 0xE9; /* jmp */
1453 *(unsigned*)(void*)&pchCTEntry[1] = aImportTab[i].ulAddress - (unsigned)&pchCTEntry[5];
1454 }
1455 else
1456 { /* !fatal! - this should never really happen... */
1457 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1458 Int3(); /* ipe - later! */
1459 x86RestoreWriteProtect(flWP);
1460 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1461 }
1462 pchCTEntry += IMPORT32_ENTRY;
1463 break;
1464 }
1465
1466
1467 /*
1468 * 16-bit imported procedure.
1469 * This is called by issuing a far call to the calltab entry.
1470 */
1471 case EPT_PROCIMPORTNR16: /* Not required */
1472 if (!(pchCTEntry[7] = aImportTab[i].fFound))
1473 {
1474 aImportTab[i].ulAddress = auFuncs[i];
1475 Int3();
1476 break;
1477 }
1478 case EPT_PROCIMPORT16:
1479 {
1480 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, FALSE);
1481 aImportTab[i].cbProlog = (char)cb;
1482 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1483 {
1484 /*
1485 * Create far jump from calltab to original function.
1486 * 0xEA <four byte target address> <two byte target selector>
1487 */
1488 pchCTEntry[0] = 0xEA; /* jmp far ptr */
1489 *(unsigned long*)(void*)&pchCTEntry[1] = aImportTab[i].offObject;
1490 *(unsigned short*)(void*)&pchCTEntry[5] = aImportTab[i].usSel;
1491 }
1492 else
1493 { /* !fatal! - this should never really happen... */
1494 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1495 Int3(); /* ipe - later! */
1496 x86RestoreWriteProtect(flWP);
1497 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1498 }
1499 pchCTEntry += IMPORT16_ENTRY;
1500 break;
1501 }
1502
1503
1504 /*
1505 * 16/32-bit importe variable.
1506 * This is used by accessing the 32-bit flat address in the callTab.
1507 * callTab-entry + 4 holds the offset of the variable into the object.
1508 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1509 * callTab-entry + a holds the 16-bit offset for the variable.
1510 * callTab-entry + c holds the selector for the object. (These two fields is the 16:16-bit pointer to the variable.)
1511 */
1512 case EPT_VARIMPORTNR32:
1513 case EPT_VARIMPORTNR16:
1514 if (!aImportTab[i].fFound)
1515 {
1516 memset(pchCTEntry, 0, VARIMPORT_ENTRY);
1517 pchCTEntry += VARIMPORT_ENTRY;
1518 break;
1519 }
1520 case EPT_VARIMPORT32:
1521 case EPT_VARIMPORT16:
1522 aImportTab[i].cbProlog = (char)0;
1523 *(unsigned long*)(void*)&pchCTEntry[0] = aImportTab[i].ulAddress;
1524 *(unsigned long*)(void*)&pchCTEntry[4] = aImportTab[i].offObject;
1525 *(unsigned short*)(void*)&pchCTEntry[8] = aImportTab[i].usSel;
1526 *(unsigned short*)(void*)&pchCTEntry[0xa] = (unsigned short)aImportTab[i].offObject;
1527 *(unsigned short*)(void*)&pchCTEntry[0xc] = aImportTab[i].usSel;
1528 pchCTEntry += VARIMPORT_ENTRY;
1529 break;
1530
1531 default:
1532 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1533 Int3(); /* ipe - later! */
1534 x86RestoreWriteProtect(flWP);
1535 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1536 } /* switch - type */
1537 } /* for */
1538
1539 x86RestoreWriteProtect(flWP);
1540
1541 return NO_ERROR;
1542}
1543
1544
1545#ifdef R3TST
1546/**
1547 * Creates a fake kernel MTE, SMTE and OTE for use while testing in Ring3.
1548 * @returns Pointer to the fake kernel MTE.
1549 * @status completely implemented.
1550 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1551 */
1552PMTE GetOS2KrnlMTETst(void)
1553{
1554 static MTE KrnlMTE;
1555 static SMTE KrnlSMTE;
1556
1557 KrnlMTE.mte_swapmte = &KrnlSMTE;
1558 KrnlSMTE.smte_objtab = &aKrnlOTE[0];
1559 KrnlSMTE.smte_objcnt = cObjectsFake;
1560
1561 return &KrnlMTE;
1562}
1563
1564/**
1565 * -Ring-3 testing-
1566 * Changes the entries in aImportTab to point to their fake equivalents.
1567 * @returns void
1568 * @param void
1569 * @status completely implemented.
1570 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1571 * @remark Called before the aImportTab array is used/verified.
1572 */
1573VOID R3TstFixImportTab(VOID)
1574{
1575 int i;
1576
1577 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1578 {
1579 switch (aImportTab[i].fType & ~EPT_NOT_REQ)
1580 {
1581 case EPT_PROC32:
1582 if (aTstFakers[i].fObj != 1)
1583 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROC32)\n", i));
1584 break;
1585 case EPT_PROCIMPORT32:
1586 if (aTstFakers[i].fObj != 1)
1587 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT32)\n", i));
1588 break;
1589 case EPT_PROCIMPORT16:
1590 if (aTstFakers[i].fObj != 2)
1591 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT16)\n", i));
1592 break;
1593 case EPT_VARIMPORT32:
1594 case EPT_VARIMPORT16:
1595 if (aTstFakers[i].fObj != 3 && aTstFakers[i].fObj != 4)
1596 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (VARIMPORT32/16)\n", i));
1597 break;
1598 } /* switch - type */
1599
1600 aImportTab[i].ulAddress = aTstFakers[i].uAddress;
1601 switch (aTstFakers[i].fObj)
1602 {
1603 case 1:
1604 aImportTab[i].usSel = GetSelectorCODE32();
1605 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE32START;
1606 break;
1607 case 2:
1608 aImportTab[i].usSel = GetSelectorCODE16();
1609 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE16START;
1610 break;
1611 case 3:
1612 aImportTab[i].usSel = GetSelectorDATA32();
1613 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA32START;
1614 break;
1615 case 4:
1616 aImportTab[i].usSel = GetSelectorDATA16();
1617 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA16START;
1618 break;
1619 default:
1620 kprintf(("R3TstFixImportTab: invalid segment config for entry %i.\n", i));
1621 }
1622 } /* for */
1623}
1624#endif
1625
1626/**
1627 * Dummy nop function if SecPathFromSFN isn't found.
1628 */
1629PSZ SECCALL nopSecPathFromSFN(SFN hFile)
1630{
1631 NOREF(hFile);
1632 return NULL;
1633}
Note: See TracBrowser for help on using the repository browser.