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

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

Corrected fatal error in the handling of Not-Required variables.

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