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

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

Added support for kernel revisions. (like 14062a)

File size: 59.0 KB
Line 
1/* $Id: d32init.c,v 1.29 2001-01-19 02:28:07 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 /*
389 * Lock the 32-bit objects/segments and 16-bit datasegment in memory
390 */
391 /* 32-bit code segment */
392 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
393 rc = D32Hlp_VMLock2(&CODE32START,
394 ((unsigned)&CODE32END & ~0xFFF) - (unsigned)&CODE32START, /* Round down so we don't overlap with the next request. */
395 VMDHL_LONG,
396 SSToDS(&lockhandle));
397 if (rc != NO_ERROR)
398 kprintf(("code segment lock failed with with rc=%d\n", rc));
399
400 /* 32-bit data segment */
401 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
402 rc = D32Hlp_VMLock2(callTab,
403 &CONST32_ROEND - (char*)callTab,
404 VMDHL_LONG | VMDHL_WRITE,
405 SSToDS(&lockhandle));
406 if (rc != NO_ERROR)
407 kprintf(("data segment lock failed with with rc=%d\n", rc));
408
409 /* 16-bit data segment - is this necessary? */
410 memset(SSToDS(&lockhandle), 0, sizeof(lockhandle));
411 rc = D32Hlp_VMLock2(&DATA16START,
412 &DATA16END - &DATA16START,
413 VMDHL_LONG | VMDHL_WRITE,
414 SSToDS(&lockhandle));
415 if (rc != NO_ERROR)
416 kprintf(("16-bit data segment lock failed with with rc=%d\n", rc));
417
418 return NO_ERROR;
419}
420
421
422/**
423 * Reads a number (unsigned long integer) for a string.
424 * @returns number read, ~0UL on error / no number read.
425 * @param pszNum Pointer to the string containing the number.
426 * @status competely implemented.
427 * @author knut st. osmundsen
428 */
429ULONG readnum(const char *pszNum)
430{
431 ULONG ulRet = 0;
432 ULONG ulBase = 10;
433 int i = 0;
434
435 /* determin ulBase */
436 if (*pszNum == '0')
437 if (pszNum[1] == 'x' || pszNum[1] == 'X')
438 {
439 ulBase = 16;
440 pszNum += 2;
441 }
442 else
443 {
444 ulBase = 8;
445 i = 1;
446 }
447
448 /* read digits */
449 while (ulBase == 16 ? (pszNum[i] >= '0' && pszNum[i] <= '9') || (pszNum[i] >= 'a' && pszNum[i] <= 'f') || (pszNum[i] >= 'A' && pszNum[i] <= 'F')
450 : (pszNum[i] >= '0' && pszNum[i] <= (ulBase == 10 ? '9' : '7'))
451 )
452 {
453 ulRet *= ulBase;
454 if (ulBase <= 10)
455 ulRet += pszNum[i] - '0';
456 else
457 ulRet += pszNum[i] - (pszNum[i] >= 'A' ? 'A' - 10 : (pszNum[i] >= 'a' ? 'a' + 9 : '0'));
458
459 i++;
460 }
461
462 return i > 0 ? ulRet : ~0UL;
463}
464
465
466/**
467 * Get kernel OTEs
468 * This function set pKrnlMTE, pKrnlSMTE and pKrnlOTE.
469 * @returns Strategy return code:
470 * STATUS_DONE on success.
471 * STATUS_DONE | STERR | errorcode on failure.
472 * @param pKrnlInfo Pointer to output buffer.
473 * If NULL only the three global variables are set.
474 * @status completely implemented and tested.
475 * @author knut st. osmundsen
476 * @remark Called from IOCtl.
477 * WARNING! This function is called before the initroutine (R0INIT)!
478 */
479USHORT _loadds _Far32 _Pascal GetKernelInfo32(PKRNLINFO pKrnlInfo)
480{
481 int i;
482 USHORT usRc;
483
484 /* VerifyImporTab32 is called before the initroutine! */
485 pulTKSSBase32 = (PULONG)_TKSSBase16;
486
487 /* Find the kernel OTE table */
488#ifndef R3TST
489 pKrnlMTE = GetOS2KrnlMTE();
490#else
491 pKrnlMTE = GetOS2KrnlMTETst();
492#endif
493 if (pKrnlMTE != NULL)
494 {
495 pKrnlSMTE = pKrnlMTE->mte_swapmte;
496 if (pKrnlSMTE != NULL)
497 {
498 if (pKrnlSMTE->smte_objcnt <= MAXKRNLOBJECTS)
499 {
500 pKrnlOTE = pKrnlSMTE->smte_objtab;
501 if (pKrnlOTE != NULL)
502 {
503 /*
504 * Thats all?
505 */
506 if (pKrnlInfo == NULL)
507 return NO_ERROR;
508
509 pKrnlInfo->cObjects = (unsigned char)pKrnlSMTE->smte_objcnt;
510
511 /*
512 * Copy OTEs
513 */
514 for (i = 0; i < pKrnlInfo->cObjects; i++)
515 {
516 memcpy((void*)&pKrnlInfo->aObjects[i], &pKrnlOTE[i], sizeof(OTE));
517 kprintf2(("GetKernelInfo32: %d base=0x%08x size=0x%08x flags=0x%08x\n",
518 i, pKrnlOTE[i].ote_base, pKrnlOTE[i].ote_size, pKrnlOTE[i].ote_flags));
519 }
520 usRc = 0;
521
522 /*
523 * Search for internal revision stuff in the two first objects.
524 */
525 pKrnlInfo->ulBuild = 0;
526 for (i = 0; i < 2 && pKrnlInfo->ulBuild == 0; i++)
527 {
528 const char *psz = (const char*)pKrnlOTE[i].ote_base;
529 const char *pszEnd = psz + pKrnlOTE[i].ote_size - 50; /* Last possible search position. */
530
531 while (psz < pszEnd)
532 {
533 if (strncmp(psz, "Internal revision ", 18) == 0 && (psz[18] >= '0' && psz[18] <= '9'))
534 {
535 int j;
536 kprintf2(("GetKernelInfo32: found internal revision: '%s'\n", psz));
537
538 /* skip to end of "Internal revision " string. */
539 psz += 18;
540
541 /* Read number*/
542 while ((*psz >= '0' && *psz <= '9') || *psz == '.')
543 {
544 if (*psz != '.')
545 pKrnlInfo->ulBuild = (unsigned short)(pKrnlInfo->ulBuild * 10 + (*psz - '0'));
546 psz++;
547 }
548
549 /* Check if build number seems valid. */
550 if ( !(pKrnlInfo->ulBuild >= 8254 && pKrnlInfo->ulBuild < 8383) /* Warp 3 fp 32 -> fp 60 */
551 && !(pKrnlInfo->ulBuild >= 9023 && pKrnlInfo->ulBuild <= 9036) /* Warp 4 GA -> fp 12 */
552 && !(pKrnlInfo->ulBuild >= 14039 && pKrnlInfo->ulBuild < 14100) /* Warp 4.5 GA -> fp 40 */
553 && !(pKrnlInfo->ulBuild >= 6600 && pKrnlInfo->ulBuild <= 6678) /* Warp 2.1x fix?? (just for fun!) */
554 )
555 {
556 kprintf(("GetKernelInfo32: info summary: Build %d is invalid - invalid fixpack?\n", pKrnlInfo->ulBuild));
557 usRc = ERROR_D32_INVALID_BUILD;
558 break;
559 }
560
561 /* Check for any revision flag */
562 pKrnlInfo->fKernel = 0;
563 if (*psz == 'A' || *psz == 'a')
564 {
565 pKrnlInfo->fKernel = (*psz - (*psz >= 'a' ? 'a'-1 : 'A'-1)) << KF_REV_SHIFT;
566 psz++;
567 }
568 if (*psz == 'F' || *psz == 'f' || *psz == ',') /* These are ignored! */
569 *psz++;
570
571 /* If this is an Aurora/Warp 4.5 or Warp 3 kernel there is more info! */
572 if (psz[0] == '_' && (psz[1] == 'S' || psz[1] == 's')) /* _SMP */
573 pKrnlInfo->fKernel |= KF_SMP;
574 else
575 if (*psz != ','
576 && ( (psz[0] == '_' && psz[1] == 'W' && psz[2] == '4') /* _W4 */
577 || (psz[0] == '_' && psz[1] == 'U' && psz[2] == 'N' && psz[3] == 'I' && psz[4] == '4') /* _UNI4 */
578 )
579 )
580 pKrnlInfo->fKernel |= KF_W4 | KF_UNI;
581 else
582 pKrnlInfo->fKernel |= KF_UNI;
583
584
585 /* Check if its a debug kernel (look for DEBUG at start of object 3-5) */
586 j = 3;
587 while (j < 5)
588 {
589 /* There should be no iopl object preceding the debugger data object. */
590 if ((pKrnlOTE[j].ote_flags & OBJIOPL) != 0)
591 break;
592 /* Is this is? */
593 if ((pKrnlOTE[j].ote_flags & OBJINVALID) == 0
594 && (pKrnlOTE[j].ote_flags & (OBJREAD | OBJWRITE)) == (OBJREAD | OBJWRITE)
595 && strncmp((char*)pKrnlOTE[j].ote_base, "DEBUG", 5) == 0)
596 {
597 pKrnlInfo->fKernel |= KF_DEBUG;
598 break;
599 }
600 j++;
601 }
602
603 /* Display info */
604 kprintf(("GetKernelInfo32: info summary: Build %d, fKernel=0x%x\n",
605 pKrnlInfo->ulBuild, pKrnlInfo->fKernel));
606
607 /* Break out */
608 break;
609 }
610
611 /* next */
612 psz++;
613 } /* while loop searching for "Internal revision " */
614 } /* for loop on objects 0-1. */
615
616 /* Set error code if not found */
617 if (pKrnlInfo->ulBuild == 0)
618 {
619 usRc = ERROR_D32_BUILD_INFO_NOT_FOUND;
620 kprintf(("GetKernelInfo32: Internal revision was not found!\n"));
621 }
622 }
623 else
624 usRc = ERROR_D32_NO_OBJECT_TABLE;
625 }
626 else
627 usRc = ERROR_D32_TOO_MANY_OBJECTS;
628 }
629 else
630 usRc = ERROR_D32_NO_SWAPMTE;
631 }
632 else
633 usRc = ERROR_D32_GETOS2KRNL_FAILED;
634
635 if (usRc != NO_ERROR)
636 kprintf(("GetKernelInfo32: failed. usRc = %d\n", usRc));
637
638 return (USHORT)(usRc | (usRc != NO_ERROR ? STATUS_DONE | STERR : STATUS_DONE));
639}
640
641
642
643/**
644 * Functions which cacluates the instructionsize given a ModR/M byte.
645 * @returns Number of bytes to add to cb and pach.
646 * @param bModRM ModR/M byte.
647 * @status completely implemented.
648 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
649 */
650int ModR_M_32bit(char bModRM)
651{
652 if ((bModRM & 0xc0) == 0x80 /* ex. mov ax,[ebp+11145543h] */
653 || ((bModRM & 0xc0) == 0 && (bModRM & 0x07) == 5)) /* ex. mov ebp,[0ff231234h] */
654 { /* 32-bit displacement */
655 return 5 + ((bModRM & 0x7) == 0x4); // + SIB
656 }
657 else if ((bModRM & 0xc0) == 0x40) /* ex. mov ecx,[esi]+4fh */
658 { /* 8-bit displacement */
659 return 2 + ((bModRM & 0x7) == 0x4); // + SIB
660 }
661 /* no displacement (only /r byte) */
662 return 1;
663}
664
665
666/**
667 * Functions which cacluates the instructionsize given a ModR/M byte.
668 * @returns Number of bytes to add to cb and pach.
669 * @param bModRM ModR/M byte.
670 * @status completely implemented.
671 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
672 */
673int ModR_M_16bit(char bModRM)
674{
675 if ((bModRM & 0xc0) == 0x80 /* ex. mov ax,[ebp+11145543h] */
676 || ((bModRM & 0xc0) == 0 && (bModRM & 0x07) == 5)) /* ex. mov ebp,[0ff231234h] */
677 { /* 16-bit displacement */
678 return 4;
679 }
680 else if ((bModRM & 0xc0) == 0x40) /* ex. mov ecx,[esi]+4fh */
681 { /* 8-bit displacement */
682 return 2;
683 }
684 /* no displacement (only /r byte) */
685 return 1;
686}
687
688
689
690
691
692/**
693 * 32-bit! Interpret function prolog to find where to jmp back.
694 * @returns Length of prolog need to be copied - which is also the offset of
695 * where the jmp instr should be placed.
696 * On error it returns 0.
697 * @param pach Pointer to prolog.
698 * @param fOverload TRUE: Function is to be overloaded.
699 * FALSE: Function is to be imported.
700 */
701int interpretFunctionProlog32(char *pach, BOOL fOverload)
702{
703 int cb = -3;
704 kprintf2(("interpretFunctionProlog32(0x%08x, %d):\n"
705 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
706 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
707 pach, fOverload,
708 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
709 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
710
711 /*
712 * check for the well known prolog (the only that is supported now)
713 * which is:
714 * push ebp
715 * mov ebp,esp
716 * or
717 * push ebp
718 * mov eax, dword ptr [xxxxxxxx]
719 * or
720 * sub esp, imm8
721 * push ebx
722 * push edi
723 *
724 * These are allowed when not overloading:
725 * mov eax, imm32
726 * jmp short
727 * or
728 * mov eax, imm32
729 * push ebp
730 * or
731 * mov ecx, r/m32
732 * or
733 * jmp dword
734 * or
735 * sub esp, imm8
736 * or
737 * call ptr16:32
738 * or
739 * enter imm16, imm8 (2.1x)
740 * or
741 * mov eax, imm32 (2.1x)
742 * <anything>
743 * or
744 * xor r32, r/m32
745 * or
746 * mov eax, msoff32
747 *
748 */
749 if ((pach[0] == 0x55 && (pach[1] == 0x8b || pach[1] == 0xa1)) /* the two first prologs */
750 ||
751 (pach[0] == 0x83 && pach[3] == 0x53 && pach[4] == 0x57) /* the third prolog */
752 ||
753 (pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55) && !fOverload) /* the two next prologs */
754 ||
755 (pach[0] == 0x8B && !fOverload) /* the next prolog */
756 ||
757 (pach[0] == 0xFF && !fOverload) /* the next prolog */
758 ||
759 (pach[0] == 0x83 && !fOverload) /* the next prolog */
760 ||
761 (pach[0] == 0x9a && !fOverload) /* the next prolog */
762 ||
763 (pach[0] == 0xc8) /* the next prolog */
764 ||
765 (pach[0] == 0xB8 && !fOverload) /* the next prolog */
766 ||
767 (pach[0] == 0x33 && !fOverload) /* the next prolog */
768 ||
769 (pach[0] == 0xa1 && !fOverload) /* last prolog */
770 )
771 {
772 BOOL fForce = FALSE;
773 int cbWord = 4;
774 cb = 0;
775 while (cb < 5 || fForce) /* 5 is the size of a jump instruction. */
776 {
777 int cb2;
778 if (!fForce && cbWord != 4)
779 cbWord = 4;
780 fForce = FALSE;
781 switch (*pach)
782 {
783 /* simple one byte prefixes */
784 case 0x2e: /* cs segment override */
785 case 0x36: /* ss segment override */
786 case 0x3e: /* ds segment override */
787 case 0x26: /* es segment override */
788 case 0x64: /* fs segment override */
789 case 0x65: /* gs segment override */
790 fForce = TRUE;
791 break;
792
793 case 0x66: /* 16 bit */
794 fForce = TRUE;
795 cbWord = 2;
796 break;
797
798 /* simple one byte instructions */
799 case 0x50: /* push ax */
800 case 0x51: /* push cx */
801 case 0x52: /* push dx */
802 case 0x53: /* push bx */
803 case 0x54: /* push sp */
804 case 0x55: /* push bp */
805 case 0x56: /* push si */
806 case 0x57: /* push di */
807 break;
808
809 /* simple two byte instructions */
810 case 0xb0: /* mov al, imm8 */
811 case 0xb1: /* mov cl, imm8 */
812 case 0xb2: /* mov dl, imm8 */
813 case 0xb3: /* mov bl, imm8 */
814 case 0xb4: /* mov ah, imm8 */
815 case 0xb5: /* mov ch, imm8 */
816 case 0xb6: /* mov dh, imm8 */
817 case 0xb7: /* mov bh, imm8 */
818 case 0x2c: /* sub al, imm8 */
819 case 0x34: /* xor al, imm8 */
820 case 0x3c: /* cmp al, imm8 */
821 case 0x6a: /* push <byte> */
822 case 0xa0: /* mov al, moffs8 */
823 case 0xa2: /* mov moffs8, al */
824 pach++;
825 cb++;
826 break;
827
828 /* simple five byte instructions */
829 case 0xb8: /* mov eax, imm32 */
830 case 0xb9: /* mov ecx, imm32 */
831 case 0xba: /* mov edx, imm32 */
832 case 0xbb: /* mov ebx, imm32 */
833 case 0xbc: /* mov esx, imm32 */
834 case 0xbd: /* mov ebx, imm32 */
835 case 0xbe: /* mov esi, imm32 */
836 case 0xbf: /* mov edi, imm32 */
837 case 0x2d: /* sub eax, imm32 */
838 case 0x35: /* xor eax, imm32 */
839 case 0x3d: /* cmp eax, imm32 */
840 case 0x68: /* push <dword> */
841 case 0xa1: /* mov eax, moffs16 */
842 case 0xa3: /* mov moffs16, eax */
843 pach += cbWord;
844 cb += cbWord;
845 break;
846
847 /* complex sized instructions - "/r" */
848 case 0x30: /* xor r/m8, r8 */
849 case 0x31: /* xor r/m32, r32 */
850 case 0x32: /* xor r8, r/m8 */
851 case 0x33: /* xor r32, r/m32 */
852 case 0x38: /* cmp r/m8, r8 */
853 case 0x39: /* cmp r/m32, r32 */
854 case 0x3a: /* cmp r8, r/m8 */
855 case 0x3b: /* cmp r32, r/m32 */
856 case 0x28: /* sub r/m8, r8 */
857 case 0x29: /* sub r/m32, r32 */
858 case 0x2a: /* sub r8, r/m8 */
859 case 0x2b: /* sub r32, r/m32 */
860 case 0x8b: /* mov /r */
861 case 0x8d: /* lea /r */
862 cb += cb2 = ModR_M_32bit(pach[1]);
863 pach += cb2;
864 break;
865
866 /* complex sized instruction - "/5 ib" */
867 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
868 case 0x83: /* 5: sub r/m32, imm8 7: cmp r/m32, imm8 */
869 if ((pach[1] & 0x38) == (5<<3)
870 || (pach[1] & 0x38) == (7<<3)
871 )
872 {
873 cb += cb2 = 1 + ModR_M_32bit(pach[1]); /* 1 is the size of the imm8 */
874 pach += cb2;
875 }
876 else
877 {
878 kprintf(("interpretFunctionProlog32: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
879 return -3;
880 }
881 break;
882
883 /* complex sized instruction - "/digit id" */
884 case 0x81: /* sub r/m32, imm32 + more instructions! */
885 if ((pach[1] & 0x38) == (5<<3) /* sub r/m32, imm32 */
886 || (pach[1] & 0x38) == (7<<3) /* cmp r/m32, imm32 */
887 )
888 {
889 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
890 pach += cb2;
891 }
892 else
893 {
894 kprintf(("interpretFunctionProlog32: unknown instruction (-2) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
895 return -2;
896 }
897 break;
898
899 case 0x9a: /* call ptr16:32 */
900 cb += cb2 = 6;
901 pach += cb2;
902 break;
903
904 case 0xc8: /* enter imm16, imm8 */
905 cb += cb = 3;
906 pach += cb2;
907 break;
908
909 /*
910 * jmp /digit
911 */
912 case 0xff:
913 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
914 pach += cb2;
915 break;
916
917 default:
918 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
919 return 0;
920 }
921 pach++;
922 cb++;
923 }
924 }
925 else
926 {
927 kprintf(("interpretFunctionProlog32: unknown prolog start. 0x%x 0x%x 0x%x 0x%x 0x%x\n",
928 pach[0], pach[1], pach[2], pach[3], pach[4]));
929 cb = 0;
930 }
931 return cb;
932}
933
934
935/**
936 * 16-bit! Interpret function prolog to find where to jmp back.
937 * @returns Length of prolog need to be copied - which is also the offset of
938 * where the jmp instr should be placed.
939 * On error it returns 0.
940 * @param pach Pointer to prolog.
941 * @param fOverload TRUE: Function is to be overloaded.
942 * FALSE: Function is to be imported.
943 */
944int interpretFunctionProlog16(char *pach, BOOL fOverload)
945{
946 int cb = -7;
947
948 kprintf2(("interpretFunctionProlog16(0x%08x, %d):\n"
949 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
950 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
951 pach, fOverload,
952 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
953 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
954 /*
955 * Check for the well known prolog (the only that is supported now)
956 * which is:
957 * push 2
958 */
959 if (*pach == 0x6A) /* push 2 (don't check for the 2) */
960 {
961 BOOL fForce;
962 int cOpPrefix = 0;
963 cb = 0;
964 while (cb < 8 || fForce) /* 8 is the size of a 66h prefixed far jump instruction. */
965 {
966 int cb2;
967 fForce = FALSE;
968 switch (*pach)
969 {
970 case 0x06: /* push es */
971 case 0x0e: /* push cs */
972 case 0x1e: /* push ds */
973 case 0x16: /* push ss */
974 break;
975
976 case 0x0f: /* push gs and push fs */
977 if (pach[1] != 0xA0 && pach[1] != 0xA8)
978 {
979 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
980 return -11;
981 }
982 pach++;
983 cb++;
984 break;
985
986 case 0x50: /* push ax */
987 case 0x51: /* push cx */
988 case 0x52: /* push dx */
989 case 0x53: /* push bx */
990 case 0x54: /* push sp */
991 case 0x55: /* push bp */
992 case 0x56: /* push si */
993 case 0x57: /* push di */
994 break;
995
996 case 0x2e: /* cs segment override */
997 case 0x36: /* ss segment override */
998 case 0x3e: /* ds segment override */
999 case 0x26: /* es segment override */
1000 case 0x64: /* fs segment override */
1001 case 0x65: /* gs segment override */
1002 fForce = TRUE;
1003 if (cOpPrefix > 0)
1004 cOpPrefix++;
1005 break;
1006
1007 case 0x66:
1008 cOpPrefix = 2; /* it's decremented once before it's used. */
1009 fForce = TRUE;
1010 break;
1011
1012 case 0x6a: /* push <byte> */
1013 pach++;
1014 cb++;
1015 break;
1016
1017 case 0x68: /* push <word> */
1018 if (cOpPrefix > 0)
1019 {
1020 pach += 2;
1021 cb += 2;
1022 }
1023 pach += 2;
1024 cb += 2;
1025 break;
1026
1027 case 0x8b: /* mov /r */
1028 if ((pach[1] & 0xc0) == 0x80 /* ex. mov ax,bp+1114h */
1029 || ((pach[1] & 0xc0) == 0 && (pach[1] & 0x7) == 6)) /* ex. mov bp,0ff23h */
1030 { /* 16-bit displacement */
1031 if (cOpPrefix > 0)
1032 {
1033 pach += 2;
1034 cb += 2;
1035 }
1036 pach += 3;
1037 cb += 3;
1038 }
1039 else
1040 if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
1041 { /* 8-bit displacement */
1042 pach += 2;
1043 cb += 2;
1044 }
1045 else
1046 { /* no displacement (only /r byte) */
1047 pach++;
1048 cb++;
1049 }
1050 break;
1051
1052 /* complex sized instruction - "/5 ib" */
1053 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
1054 case 0x83: /* 5: sub r/m16, imm8 7: cmp r/m16, imm8 */
1055 if ((pach[1] & 0x38) == (5<<3)
1056 || (pach[1] & 0x38) == (7<<3)
1057 )
1058 {
1059 cb += cb2 = 1 + ModR_M_16bit(pach[1]); /* 1 is the size of the imm8 */
1060 pach += cb2;
1061 }
1062 else
1063 {
1064 kprintf(("interpretFunctionProlog16: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1065 return -3;
1066 }
1067 break;
1068
1069
1070 default:
1071 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1072 return 0;
1073 }
1074 pach++;
1075 cb++;
1076 if (cOpPrefix > 0)
1077 cOpPrefix--;
1078 }
1079 }
1080
1081 fOverload = fOverload;
1082 return cb;
1083}
1084
1085
1086/**
1087 * Verifies the aImportTab.
1088 * @returns 16-bit errorcode where the high byte is the procedure number which
1089 * the error occured on and the low byte the error code.
1090 * @remark Called from IOCtl.
1091 * WARNING! This function is called before the initroutine (R0INIT)!
1092 */
1093USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
1094{
1095 USHORT usRc;
1096 int i;
1097 int cb;
1098 int cbmax;
1099
1100 /* VerifyImporTab32 is called before the initroutine! */
1101 pulTKSSBase32 = (PULONG)_TKSSBase16;
1102
1103 /* Check that pKrnlOTE is set */
1104 usRc = GetKernelInfo32(NULL);
1105 if (usRc != NO_ERROR)
1106 return usRc;
1107
1108 /*
1109 * Verify aImportTab.
1110 */
1111 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1112 {
1113 /*
1114 * Debug info
1115 */
1116 kprintf2(("VerifyImportTab32: procedure no.%d is being checked: %s addr=0x%08x iObj=%d offObj=%d\n",
1117 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1118 aImportTab[i].iObject, aImportTab[i].offObject));
1119
1120 /* Verify that it is found */
1121 if (!aImportTab[i].fFound)
1122 {
1123 if (EPTNotReq(aImportTab[i]))
1124 continue;
1125 else
1126 {
1127 kprintf(("VerifyImportTab32: procedure no.%d was not fFound!\n", i));
1128 return (USHORT)(ERROR_D32_PROC_NOT_FOUND | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1129 }
1130 }
1131
1132 /* Verify read/writeable. */
1133 if ( aImportTab[i].iObject >= pKrnlSMTE->smte_objcnt /* object index valid? */
1134 || aImportTab[i].ulAddress < pKrnlOTE[aImportTab[i].iObject].ote_base /* address valid? */
1135 || aImportTab[i].ulAddress + 16 > (pKrnlOTE[aImportTab[i].iObject].ote_base +
1136 pKrnlOTE[aImportTab[i].iObject].ote_size) /* address valid? */
1137 || aImportTab[i].ulAddress - aImportTab[i].offObject
1138 != pKrnlOTE[aImportTab[i].iObject].ote_base /* offObject ok? */
1139 )
1140 {
1141 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address or object number.!\n"
1142 " %s addr=0x%08x iObj=%d offObj=%d\n",
1143 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1144 aImportTab[i].iObject, aImportTab[i].offObject));
1145 return (USHORT)(ERROR_D32_INVALID_OBJ_OR_ADDR | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1146 }
1147
1148
1149 #ifndef R3TST
1150 if (aImportTab[i].ulAddress < 0xff400000UL)
1151 {
1152 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address, %#08x!\n",
1153 i, aImportTab[i].ulAddress));
1154 return (USHORT)(ERROR_D32_INVALID_ADDRESS | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1155 }
1156 #endif
1157
1158 switch (aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ | EPT_WRAPPED))
1159 {
1160 case EPT_PROC:
1161 case EPT_PROCIMPORT:
1162 /*
1163 * Verify known function prolog.
1164 */
1165 if (EPT32BitEntry(aImportTab[i]))
1166 {
1167 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1168 cbmax = OVERLOAD32_ENTRY - 5; /* 5 = Size of the jump instruction */
1169 }
1170 else
1171 {
1172 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1173 cbmax = OVERLOAD16_ENTRY - 7; /* 7 = Size of the far jump instruction */
1174 }
1175
1176 /*
1177 * Check result of the function prolog interpretations.
1178 */
1179 if (cb <= 0 || cb > cbmax)
1180 { /* failed, too small or too large. */
1181 kprintf(("VerifyImportTab32: verify failed for procedure no.%d (cb=%d), %s\n", i, cb, aImportTab[i].achName));
1182 return (USHORT)(ERROR_D32_TOO_INVALID_PROLOG | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1183 }
1184 break;
1185
1186 case EPT_VARIMPORT:
1187 /* do nothing! */
1188 break;
1189
1190 default:
1191 kprintf(("VerifyImportTab32: invalid type/type not implemented. Proc no.%d, %s\n",i, aImportTab[i].achName));
1192 Int3(); /* temporary fix! */
1193 return (USHORT)(ERROR_D32_NOT_IMPLEMENTED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1194 }
1195 }
1196
1197 return NO_ERROR;
1198}
1199
1200
1201/**
1202 * Initiates the overrided functions.
1203 * @returns 16-bit errorcode where the high byte is the procedure number which
1204 * the error occured on and the low byte the error code.
1205 */
1206int importTabInit(void)
1207{
1208 int i;
1209 int cb;
1210 int cbmax;
1211 char * pchCTEntry; /* Pointer to current calltab entry. */
1212
1213 /*
1214 * Apply build specific changes to the auFuncs table
1215 */
1216 if (options.ulBuild < 14053)
1217 {
1218 #ifdef DEBUG
1219 if (auFuncs[0] != (unsigned)myldrOpenPath)
1220 {
1221 kprintf(("importTabInit: ASSERTION FAILED auFuncs don't point at myldrOpenPath\n"));
1222 Int3();
1223 }
1224 #endif
1225 auFuncs[0] = (unsigned)myldrOpenPath_old;
1226 }
1227
1228#ifdef R3TST
1229 R3TstFixImportTab();
1230#endif
1231
1232 /*
1233 * verify proctable
1234 */
1235 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1236 {
1237 /* EPT_VARIMPORTs are skipped */
1238 if ((aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ)) == EPT_VARIMPORT)
1239 continue;
1240 /* EPT_NOT_REQ which is not found are set pointing to the nop function provided. */
1241 if (!aImportTab[i].fFound && EPTNotReq(aImportTab[i]))
1242 continue;
1243
1244 if (EPT32BitEntry(aImportTab[i]))
1245 {
1246 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1247
1248 cbmax = OVERLOAD16_ENTRY - 5; /* 5 = Size of the jump instruction */
1249 }
1250 else
1251 {
1252 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1253 cbmax = OVERLOAD16_ENTRY - 7; /* 7 = Size of the far jump instruction */
1254 }
1255 if (cb <= 0 || cb > cbmax)
1256 {
1257 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
1258 return ERROR_D32_VERIFY_FAILED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1259 }
1260 }
1261
1262 /*
1263 * rehook / import
1264 */
1265 pchCTEntry = &callTab[0];
1266 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1267 {
1268 switch (aImportTab[i].fType & ~EPT_WRAPPED)
1269 {
1270 /*
1271 * 32-bit procedure overload.
1272 * The overloading procedure is found in the auFuncs table (at the same index
1273 * as the overloaded procedure has in aImportTab).
1274 * The overloaded procedure is called by issuing a call to the callTab entry.
1275 */
1276 case EPT_PROC32:
1277 {
1278 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, TRUE);
1279 aImportTab[i].cbProlog = (char)cb;
1280 if (cb >= 5 && cb + 5 < OVERLOAD32_ENTRY) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
1281 { /* 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. */
1282 /*
1283 * Copy function prolog which will be overwritten by the jmp to calltabl.
1284 */
1285 memcpy(pchCTEntry, (void*)aImportTab[i].ulAddress, (size_t)cb);
1286
1287 /*
1288 * Make jump instruction which jumps from calltab to original function.
1289 * 0xE9 <four bytes displacement>
1290 * Note: the displacement is relative to the next instruction
1291 */
1292 pchCTEntry[cb] = 0xE9; /* jmp */
1293 *(unsigned long*)(void*)&pchCTEntry[cb+1] = aImportTab[i].ulAddress + cb - (unsigned long)&pchCTEntry[cb+5];
1294
1295 /*
1296 * Jump from original function to my function - an cli(?) could be needed here
1297 */
1298 *(char*)aImportTab[i].ulAddress = 0xE9; /* jmp */
1299 *(unsigned long*)(aImportTab[i].ulAddress + 1) = auFuncs[i] - (aImportTab[i].ulAddress + 5);
1300 }
1301 else
1302 { /* !fatal! - this could never happen really... */
1303 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1304 Int3(); /* ipe - later! */
1305 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1306 }
1307 pchCTEntry += OVERLOAD32_ENTRY;
1308 break;
1309 }
1310
1311
1312 /*
1313 * 16-bit procedure overload.
1314 * Currently disabled due to expected problems when calltab is a 32-bit segment.
1315 */
1316 case EPT_PROC16:
1317 {
1318 kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
1319 Int3();
1320
1321 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, TRUE);
1322 aImportTab[i].cbProlog = (char)cb;
1323 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) */
1324 { /* 7: size of a 16:32 jump which is added to the call tab */
1325 /*
1326 * Copy function prolog which is to be overwritten.
1327 */
1328 memcpy(pchCTEntry, (void*)aImportTab[i].ulAddress, (size_t)cb);
1329
1330 /*
1331 * Create far jump from calltab to original function.
1332 * 0xEA <four byte target address> <two byte target selector>
1333 */
1334 pchCTEntry[cb] = 0xEA; /* jmp far ptr */
1335 *(unsigned long*)(void*)&pchCTEntry[cb+1] = aImportTab[i].offObject;
1336 *(unsigned short*)(void*)&pchCTEntry[cb+5] = aImportTab[i].usSel;
1337
1338 /*
1339 * jump from original function to my function - an cli(?) could be needed here
1340 * 0x66 0xEA <four byte target address> <two byte target selector>
1341 */
1342 *(char*)(aImportTab[i].ulAddress ) = 0x66; /* operandsize prefix */
1343 *(char*)(aImportTab[i].ulAddress + 1) = 0xEA; /* jmp far ptr */
1344 *(unsigned long*)(aImportTab[i].ulAddress + 2) = auFuncs[i]; /* FIXME? */
1345 *(unsigned short*)(aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
1346 }
1347 else
1348 { /* !fatal! - this could never happen really... */
1349 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1350 Int3(); /* ipe - later! */
1351 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1352 }
1353 pchCTEntry += OVERLOAD16_ENTRY;
1354 break;
1355 }
1356
1357
1358 /*
1359 * 32-bit imported procedure.
1360 * This is called by issuing a near call to the callTab entry.
1361 */
1362 case EPT_PROCIMPORTNR32: /* Not required */
1363 if (!(pchCTEntry[6] = aImportTab[i].fFound))
1364 aImportTab[i].ulAddress = auFuncs[i];
1365 case EPT_PROCIMPORT32:
1366 {
1367 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, FALSE);
1368 aImportTab[i].cbProlog = (char)cb;
1369 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1370 {
1371 /*
1372 * Make jump instruction which jumps from calltab to original function.
1373 * 0xE9 <four bytes displacement>
1374 * Note: the displacement is relative to the next instruction
1375 */
1376 pchCTEntry[0] = 0xE9; /* jmp */
1377 *(unsigned*)(void*)&pchCTEntry[1] = aImportTab[i].ulAddress - (unsigned)&pchCTEntry[5];
1378 }
1379 else
1380 { /* !fatal! - this should never really happen... */
1381 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1382 Int3(); /* ipe - later! */
1383 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1384 }
1385 pchCTEntry += IMPORT32_ENTRY;
1386 break;
1387 }
1388
1389
1390 /*
1391 * 16-bit imported procedure.
1392 * This is called by issuing a far call to the calltab entry.
1393 */
1394 case EPT_PROCIMPORTNR16: /* Not required */
1395 if (!(pchCTEntry[7] = aImportTab[i].fFound))
1396 {
1397 aImportTab[i].ulAddress = auFuncs[i];
1398 Int3();
1399 break;
1400 }
1401 case EPT_PROCIMPORT16:
1402 {
1403 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, FALSE);
1404 aImportTab[i].cbProlog = (char)cb;
1405 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1406 {
1407 /*
1408 * Create far jump from calltab to original function.
1409 * 0xEA <four byte target address> <two byte target selector>
1410 */
1411 pchCTEntry[0] = 0xEA; /* jmp far ptr */
1412 *(unsigned long*)(void*)&pchCTEntry[1] = aImportTab[i].offObject;
1413 *(unsigned short*)(void*)&pchCTEntry[5] = aImportTab[i].usSel;
1414 }
1415 else
1416 { /* !fatal! - this should never really happen... */
1417 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1418 Int3(); /* ipe - later! */
1419 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1420 }
1421 pchCTEntry += IMPORT16_ENTRY;
1422 break;
1423 }
1424
1425
1426 /*
1427 * 16/32-bit importe variable.
1428 * This is used by accessing the 32-bit flat address in the callTab.
1429 * callTab-entry + 4 holds the offset of the variable into the object.
1430 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1431 * callTab-entry + a holds the 16-bit offset for the variable.
1432 * callTab-entry + c holds the selector for the object. (These two fields is the 16:16-bit pointer to the variable.)
1433 */
1434 case EPT_VARIMPORT32:
1435 case EPT_VARIMPORT16:
1436 aImportTab[i].cbProlog = (char)0;
1437 *(unsigned long*)(void*)&pchCTEntry[0] = aImportTab[i].ulAddress;
1438 *(unsigned long*)(void*)&pchCTEntry[4] = aImportTab[i].offObject;
1439 *(unsigned short*)(void*)&pchCTEntry[8] = aImportTab[i].usSel;
1440 *(unsigned short*)(void*)&pchCTEntry[0xa] = (unsigned short)aImportTab[i].offObject;
1441 *(unsigned short*)(void*)&pchCTEntry[0xc] = aImportTab[i].usSel;
1442 pchCTEntry += VARIMPORT_ENTRY;
1443 break;
1444
1445 default:
1446 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1447 Int3(); /* ipe - later! */
1448 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1449 } /* switch - type */
1450 } /* for */
1451
1452 return NO_ERROR;
1453}
1454
1455
1456#ifdef R3TST
1457/**
1458 * Creates a fake kernel MTE, SMTE and OTE for use while testing in Ring3.
1459 * @returns Pointer to the fake kernel MTE.
1460 * @status completely implemented.
1461 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1462 */
1463PMTE GetOS2KrnlMTETst(void)
1464{
1465 static MTE KrnlMTE;
1466 static SMTE KrnlSMTE;
1467
1468 KrnlMTE.mte_swapmte = &KrnlSMTE;
1469 KrnlSMTE.smte_objtab = &aKrnlOTE[0];
1470 KrnlSMTE.smte_objcnt = cObjectsFake;
1471
1472 return &KrnlMTE;
1473}
1474
1475/**
1476 * -Ring-3 testing-
1477 * Changes the entries in aImportTab to point to their fake equivalents.
1478 * @returns void
1479 * @param void
1480 * @status completely implemented.
1481 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1482 * @remark Called before the aImportTab array is used/verified.
1483 */
1484VOID R3TstFixImportTab(VOID)
1485{
1486 int i;
1487
1488 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1489 {
1490 switch (aImportTab[i].fType & ~EPT_NOT_REQ)
1491 {
1492 case EPT_PROC32:
1493 if (aTstFakers[i].fObj != 1)
1494 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROC32)\n", i));
1495 break;
1496 case EPT_PROCIMPORT32:
1497 if (aTstFakers[i].fObj != 1)
1498 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT32)\n", i));
1499 break;
1500 case EPT_PROCIMPORT16:
1501 if (aTstFakers[i].fObj != 2)
1502 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT16)\n", i));
1503 break;
1504 case EPT_VARIMPORT32:
1505 case EPT_VARIMPORT16:
1506 if (aTstFakers[i].fObj != 3 && aTstFakers[i].fObj != 4)
1507 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (VARIMPORT32/16)\n", i));
1508 break;
1509 } /* switch - type */
1510
1511 aImportTab[i].ulAddress = aTstFakers[i].uAddress;
1512 switch (aTstFakers[i].fObj)
1513 {
1514 case 1:
1515 aImportTab[i].usSel = GetSelectorCODE32();
1516 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE32START;
1517 break;
1518 case 2:
1519 aImportTab[i].usSel = GetSelectorCODE16();
1520 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE16START;
1521 break;
1522 case 3:
1523 aImportTab[i].usSel = GetSelectorDATA32();
1524 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA32START;
1525 break;
1526 case 4:
1527 aImportTab[i].usSel = GetSelectorDATA16();
1528 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA16START;
1529 break;
1530 default:
1531 kprintf(("R3TstFixImportTab: invalid segment config for entry %i.\n", i));
1532 }
1533 } /* for */
1534}
1535#endif
1536
1537/**
1538 * Dummy nop function if SecPathFromSFN isn't found.
1539 */
1540PSZ SECCALL nopSecPathFromSFN(SFN hFile)
1541{
1542 NOREF(hFile);
1543 return NULL;
1544}
Note: See TracBrowser for help on using the repository browser.