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

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

Added new api enhancement option and win32k ini filename.

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