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

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

Moved ldrCalls.h into the OS2Krnl.h tree as OS2KLDR.h.
Also moved the Ldr definitions from OS2Krnl.h and into OS2KLDR.h.

File size: 59.7 KB
Line 
1/* $Id: d32init.c,v 1.32 2001-02-10 11:11:42 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 == 'a')
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 *
766 */
767 if ((pach[0] == 0x55 && (pach[1] == 0x8b || pach[1] == 0xa1)) /* the two first prologs */
768 ||
769 (pach[0] == 0x83 && pach[3] == 0x53 && pach[4] == 0x57) /* the third prolog */
770 ||
771 (pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55) && !fOverload) /* the two next prologs */
772 ||
773 (pach[0] == 0x8B && !fOverload) /* the next prolog */
774 ||
775 (pach[0] == 0xFF && !fOverload) /* the next prolog */
776 ||
777 (pach[0] == 0x83 && !fOverload) /* the next prolog */
778 ||
779 (pach[0] == 0x9a && !fOverload) /* the next prolog */
780 ||
781 (pach[0] == 0xc8) /* the next prolog */
782 ||
783 (pach[0] == 0xB8 && !fOverload) /* the next prolog */
784 ||
785 (pach[0] == 0x33 && !fOverload) /* the next prolog */
786 ||
787 (pach[0] == 0xa1 && !fOverload) /* last prolog */
788 )
789 {
790 BOOL fForce = FALSE;
791 int cbWord = 4;
792 cb = 0;
793 while (cb < 5 || fForce) /* 5 is the size of a jump instruction. */
794 {
795 int cb2;
796 if (!fForce && cbWord != 4)
797 cbWord = 4;
798 fForce = FALSE;
799 switch (*pach)
800 {
801 /* simple one byte prefixes */
802 case 0x2e: /* cs segment override */
803 case 0x36: /* ss segment override */
804 case 0x3e: /* ds segment override */
805 case 0x26: /* es segment override */
806 case 0x64: /* fs segment override */
807 case 0x65: /* gs segment override */
808 fForce = TRUE;
809 break;
810
811 case 0x66: /* 16 bit */
812 fForce = TRUE;
813 cbWord = 2;
814 break;
815
816 /* simple one byte instructions */
817 case 0x50: /* push ax */
818 case 0x51: /* push cx */
819 case 0x52: /* push dx */
820 case 0x53: /* push bx */
821 case 0x54: /* push sp */
822 case 0x55: /* push bp */
823 case 0x56: /* push si */
824 case 0x57: /* push di */
825 break;
826
827 /* simple two byte instructions */
828 case 0xb0: /* mov al, imm8 */
829 case 0xb1: /* mov cl, imm8 */
830 case 0xb2: /* mov dl, imm8 */
831 case 0xb3: /* mov bl, imm8 */
832 case 0xb4: /* mov ah, imm8 */
833 case 0xb5: /* mov ch, imm8 */
834 case 0xb6: /* mov dh, imm8 */
835 case 0xb7: /* mov bh, imm8 */
836 case 0x2c: /* sub al, imm8 */
837 case 0x34: /* xor al, imm8 */
838 case 0x3c: /* cmp al, imm8 */
839 case 0x6a: /* push <byte> */
840 case 0xa0: /* mov al, moffs8 */
841 case 0xa2: /* mov moffs8, al */
842 pach++;
843 cb++;
844 break;
845
846 /* simple five byte instructions */
847 case 0xb8: /* mov eax, imm32 */
848 case 0xb9: /* mov ecx, imm32 */
849 case 0xba: /* mov edx, imm32 */
850 case 0xbb: /* mov ebx, imm32 */
851 case 0xbc: /* mov esx, imm32 */
852 case 0xbd: /* mov ebx, imm32 */
853 case 0xbe: /* mov esi, imm32 */
854 case 0xbf: /* mov edi, imm32 */
855 case 0x2d: /* sub eax, imm32 */
856 case 0x35: /* xor eax, imm32 */
857 case 0x3d: /* cmp eax, imm32 */
858 case 0x68: /* push <dword> */
859 case 0xa1: /* mov eax, moffs16 */
860 case 0xa3: /* mov moffs16, eax */
861 pach += cbWord;
862 cb += cbWord;
863 break;
864
865 /* complex sized instructions - "/r" */
866 case 0x30: /* xor r/m8, r8 */
867 case 0x31: /* xor r/m32, r32 */
868 case 0x32: /* xor r8, r/m8 */
869 case 0x33: /* xor r32, r/m32 */
870 case 0x38: /* cmp r/m8, r8 */
871 case 0x39: /* cmp r/m32, r32 */
872 case 0x3a: /* cmp r8, r/m8 */
873 case 0x3b: /* cmp r32, r/m32 */
874 case 0x28: /* sub r/m8, r8 */
875 case 0x29: /* sub r/m32, r32 */
876 case 0x2a: /* sub r8, r/m8 */
877 case 0x2b: /* sub r32, r/m32 */
878 case 0x8b: /* mov /r */
879 case 0x8d: /* lea /r */
880 cb += cb2 = ModR_M_32bit(pach[1]);
881 pach += cb2;
882 break;
883
884 /* complex sized instruction - "/5 ib" */
885 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
886 case 0x83: /* 5: sub r/m32, imm8 7: cmp r/m32, imm8 */
887 if ((pach[1] & 0x38) == (5<<3)
888 || (pach[1] & 0x38) == (7<<3)
889 )
890 {
891 cb += cb2 = 1 + ModR_M_32bit(pach[1]); /* 1 is the size of the imm8 */
892 pach += cb2;
893 }
894 else
895 {
896 kprintf(("interpretFunctionProlog32: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
897 return -3;
898 }
899 break;
900
901 /* complex sized instruction - "/digit id" */
902 case 0x81: /* sub r/m32, imm32 + more instructions! */
903 if ((pach[1] & 0x38) == (5<<3) /* sub r/m32, imm32 */
904 || (pach[1] & 0x38) == (7<<3) /* cmp r/m32, imm32 */
905 )
906 {
907 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
908 pach += cb2;
909 }
910 else
911 {
912 kprintf(("interpretFunctionProlog32: unknown instruction (-2) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
913 return -2;
914 }
915 break;
916
917 case 0x9a: /* call ptr16:32 */
918 cb += cb2 = 6;
919 pach += cb2;
920 break;
921
922 case 0xc8: /* enter imm16, imm8 */
923 cb += cb = 3;
924 pach += cb2;
925 break;
926
927 /*
928 * jmp /digit
929 */
930 case 0xff:
931 cb += cb2 = cbWord + ModR_M_32bit(pach[1]); /* cbWord is the size of the imm32/imm16 */
932 pach += cb2;
933 break;
934
935 default:
936 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
937 return 0;
938 }
939 pach++;
940 cb++;
941 }
942 }
943 else
944 {
945 kprintf(("interpretFunctionProlog32: unknown prolog start. 0x%x 0x%x 0x%x 0x%x 0x%x\n",
946 pach[0], pach[1], pach[2], pach[3], pach[4]));
947 cb = 0;
948 }
949 return cb;
950}
951
952
953/**
954 * 16-bit! Interpret function prolog to find where to jmp back.
955 * @returns Length of prolog need to be copied - which is also the offset of
956 * where the jmp instr should be placed.
957 * On error it returns 0.
958 * @param pach Pointer to prolog.
959 * @param fOverload TRUE: Function is to be overloaded.
960 * FALSE: Function is to be imported.
961 */
962int interpretFunctionProlog16(char *pach, BOOL fOverload)
963{
964 int cb = -7;
965
966 kprintf2(("interpretFunctionProlog16(0x%08x, %d):\n"
967 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
968 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
969 pach, fOverload,
970 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
971 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
972 /*
973 * Check for the well known prolog (the only that is supported now)
974 * which is:
975 * push 2
976 */
977 if (*pach == 0x6A) /* push 2 (don't check for the 2) */
978 {
979 BOOL fForce;
980 int cOpPrefix = 0;
981 cb = 0;
982 while (cb < 8 || fForce) /* 8 is the size of a 66h prefixed far jump instruction. */
983 {
984 int cb2;
985 fForce = FALSE;
986 switch (*pach)
987 {
988 case 0x06: /* push es */
989 case 0x0e: /* push cs */
990 case 0x1e: /* push ds */
991 case 0x16: /* push ss */
992 break;
993
994 case 0x0f: /* push gs and push fs */
995 if (pach[1] != 0xA0 && pach[1] != 0xA8)
996 {
997 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
998 return -11;
999 }
1000 pach++;
1001 cb++;
1002 break;
1003
1004 case 0x50: /* push ax */
1005 case 0x51: /* push cx */
1006 case 0x52: /* push dx */
1007 case 0x53: /* push bx */
1008 case 0x54: /* push sp */
1009 case 0x55: /* push bp */
1010 case 0x56: /* push si */
1011 case 0x57: /* push di */
1012 break;
1013
1014 case 0x2e: /* cs segment override */
1015 case 0x36: /* ss segment override */
1016 case 0x3e: /* ds segment override */
1017 case 0x26: /* es segment override */
1018 case 0x64: /* fs segment override */
1019 case 0x65: /* gs segment override */
1020 fForce = TRUE;
1021 if (cOpPrefix > 0)
1022 cOpPrefix++;
1023 break;
1024
1025 case 0x66:
1026 cOpPrefix = 2; /* it's decremented once before it's used. */
1027 fForce = TRUE;
1028 break;
1029
1030 case 0x6a: /* push <byte> */
1031 pach++;
1032 cb++;
1033 break;
1034
1035 case 0x68: /* push <word> */
1036 if (cOpPrefix > 0)
1037 {
1038 pach += 2;
1039 cb += 2;
1040 }
1041 pach += 2;
1042 cb += 2;
1043 break;
1044
1045 case 0x8b: /* mov /r */
1046 if ((pach[1] & 0xc0) == 0x80 /* ex. mov ax,bp+1114h */
1047 || ((pach[1] & 0xc0) == 0 && (pach[1] & 0x7) == 6)) /* ex. mov bp,0ff23h */
1048 { /* 16-bit displacement */
1049 if (cOpPrefix > 0)
1050 {
1051 pach += 2;
1052 cb += 2;
1053 }
1054 pach += 3;
1055 cb += 3;
1056 }
1057 else
1058 if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
1059 { /* 8-bit displacement */
1060 pach += 2;
1061 cb += 2;
1062 }
1063 else
1064 { /* no displacement (only /r byte) */
1065 pach++;
1066 cb++;
1067 }
1068 break;
1069
1070 /* complex sized instruction - "/5 ib" */
1071 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
1072 case 0x83: /* 5: sub r/m16, imm8 7: cmp r/m16, imm8 */
1073 if ((pach[1] & 0x38) == (5<<3)
1074 || (pach[1] & 0x38) == (7<<3)
1075 )
1076 {
1077 cb += cb2 = 1 + ModR_M_16bit(pach[1]); /* 1 is the size of the imm8 */
1078 pach += cb2;
1079 }
1080 else
1081 {
1082 kprintf(("interpretFunctionProlog16: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1083 return -3;
1084 }
1085 break;
1086
1087
1088 default:
1089 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
1090 return 0;
1091 }
1092 pach++;
1093 cb++;
1094 if (cOpPrefix > 0)
1095 cOpPrefix--;
1096 }
1097 }
1098
1099 fOverload = fOverload;
1100 return cb;
1101}
1102
1103
1104/**
1105 * Verifies the aImportTab.
1106 * @returns 16-bit errorcode where the high byte is the procedure number which
1107 * the error occured on and the low byte the error code.
1108 * @remark Called from IOCtl.
1109 * WARNING! This function is called before the initroutine (R0INIT)!
1110 */
1111USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
1112{
1113 USHORT usRc;
1114 int i;
1115 int cb;
1116 int cbmax;
1117
1118 /* VerifyImporTab32 is called before the initroutine! */
1119 pulTKSSBase32 = (PULONG)_TKSSBase16;
1120
1121 /* Check that pKrnlOTE is set */
1122 usRc = GetKernelInfo32(NULL);
1123 if (usRc != NO_ERROR)
1124 return usRc;
1125
1126 /*
1127 * Verify aImportTab.
1128 */
1129 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1130 {
1131 /*
1132 * Debug info
1133 */
1134 kprintf2(("VerifyImportTab32: procedure no.%d is being checked: %s addr=0x%08x iObj=%d offObj=%d\n",
1135 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1136 aImportTab[i].iObject, aImportTab[i].offObject));
1137
1138 /* Verify that it is found */
1139 if (!aImportTab[i].fFound)
1140 {
1141 if (EPTNotReq(aImportTab[i]))
1142 continue;
1143 else
1144 {
1145 kprintf(("VerifyImportTab32: procedure no.%d was not fFound!\n", i));
1146 return (USHORT)(ERROR_D32_PROC_NOT_FOUND | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1147 }
1148 }
1149
1150 /* Verify read/writeable. */
1151 if ( aImportTab[i].iObject >= pKrnlSMTE->smte_objcnt /* object index valid? */
1152 || aImportTab[i].ulAddress < pKrnlOTE[aImportTab[i].iObject].ote_base /* address valid? */
1153 || aImportTab[i].ulAddress + 16 > (pKrnlOTE[aImportTab[i].iObject].ote_base +
1154 pKrnlOTE[aImportTab[i].iObject].ote_size) /* address valid? */
1155 || aImportTab[i].ulAddress - aImportTab[i].offObject
1156 != pKrnlOTE[aImportTab[i].iObject].ote_base /* offObject ok? */
1157 )
1158 {
1159 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address or object number.!\n"
1160 " %s addr=0x%08x iObj=%d offObj=%d\n",
1161 i, &aImportTab[i].achName[0], aImportTab[i].ulAddress,
1162 aImportTab[i].iObject, aImportTab[i].offObject));
1163 return (USHORT)(ERROR_D32_INVALID_OBJ_OR_ADDR | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1164 }
1165
1166
1167 #ifndef R3TST
1168 if (aImportTab[i].ulAddress < 0xff400000UL)
1169 {
1170 kprintf(("VerifyImportTab32: procedure no.%d has an invalid address, %#08x!\n",
1171 i, aImportTab[i].ulAddress));
1172 return (USHORT)(ERROR_D32_INVALID_ADDRESS | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1173 }
1174 #endif
1175
1176 switch (aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ | EPT_WRAPPED))
1177 {
1178 case EPT_PROC:
1179 case EPT_PROCIMPORT:
1180 /*
1181 * Verify known function prolog.
1182 */
1183 if (EPT32BitEntry(aImportTab[i]))
1184 {
1185 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1186 cbmax = OVERLOAD32_ENTRY - 5; /* 5 = Size of the jump instruction */
1187 }
1188 else
1189 {
1190 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1191 cbmax = OVERLOAD16_ENTRY - 7; /* 7 = Size of the far jump instruction */
1192 }
1193
1194 /*
1195 * Check result of the function prolog interpretations.
1196 */
1197 if (cb <= 0 || cb > cbmax)
1198 { /* failed, too small or too large. */
1199 kprintf(("VerifyImportTab32: verify failed for procedure no.%d (cb=%d), %s\n", i, cb, aImportTab[i].achName));
1200 return (USHORT)(ERROR_D32_TOO_INVALID_PROLOG | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1201 }
1202 break;
1203
1204 case EPT_VARIMPORT:
1205 /* do nothing! */
1206 break;
1207
1208 default:
1209 kprintf(("VerifyImportTab32: invalid type/type not implemented. Proc no.%d, %s\n",i, aImportTab[i].achName));
1210 Int3(); /* temporary fix! */
1211 return (USHORT)(ERROR_D32_NOT_IMPLEMENTED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG);
1212 }
1213 }
1214
1215 return NO_ERROR;
1216}
1217
1218
1219/**
1220 * Initiates the overrided functions.
1221 * @returns 16-bit errorcode where the high byte is the procedure number which
1222 * the error occured on and the low byte the error code.
1223 */
1224int importTabInit(void)
1225{
1226 int i;
1227 int cb;
1228 int cbmax;
1229 char * pchCTEntry; /* Pointer to current calltab entry. */
1230
1231 /*
1232 * Apply build specific changes to the auFuncs table
1233 */
1234 if (options.ulBuild < 14053)
1235 {
1236 #ifdef DEBUG
1237 if (auFuncs[0] != (unsigned)myldrOpenPath)
1238 {
1239 kprintf(("importTabInit: ASSERTION FAILED auFuncs don't point at myldrOpenPath\n"));
1240 Int3();
1241 }
1242 #endif
1243 auFuncs[0] = (unsigned)myldrOpenPath_old;
1244 }
1245
1246#ifdef R3TST
1247 R3TstFixImportTab();
1248#endif
1249
1250 /*
1251 * verify proctable
1252 */
1253 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1254 {
1255 /* EPT_VARIMPORTs are skipped */
1256 if ((aImportTab[i].fType & ~(EPT_BIT_MASK | EPT_NOT_REQ)) == EPT_VARIMPORT)
1257 continue;
1258 /* EPT_NOT_REQ which is not found are set pointing to the nop function provided. */
1259 if (!aImportTab[i].fFound && EPTNotReq(aImportTab[i]))
1260 continue;
1261
1262 if (EPT32BitEntry(aImportTab[i]))
1263 {
1264 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, EPT32Proc(aImportTab[i]));
1265
1266 cbmax = OVERLOAD16_ENTRY - 5; /* 5 = Size of the jump instruction */
1267 }
1268 else
1269 {
1270 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, EPT16Proc(aImportTab[i]));
1271 cbmax = OVERLOAD16_ENTRY - 7; /* 7 = Size of the far jump instruction */
1272 }
1273 if (cb <= 0 || cb > cbmax)
1274 {
1275 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
1276 return ERROR_D32_VERIFY_FAILED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1277 }
1278 }
1279
1280 /*
1281 * rehook / import
1282 */
1283 pchCTEntry = &callTab[0];
1284 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1285 {
1286 switch (aImportTab[i].fType & ~EPT_WRAPPED)
1287 {
1288 /*
1289 * 32-bit procedure overload.
1290 * The overloading procedure is found in the auFuncs table (at the same index
1291 * as the overloaded procedure has in aImportTab).
1292 * The overloaded procedure is called by issuing a call to the callTab entry.
1293 */
1294 case EPT_PROC32:
1295 {
1296 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, TRUE);
1297 aImportTab[i].cbProlog = (char)cb;
1298 if (cb >= 5 && cb + 5 < OVERLOAD32_ENTRY) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
1299 { /* 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. */
1300 /*
1301 * Copy function prolog which will be overwritten by the jmp to calltabl.
1302 */
1303 memcpy(pchCTEntry, (void*)aImportTab[i].ulAddress, (size_t)cb);
1304
1305 /*
1306 * Make jump instruction which jumps from calltab to original function.
1307 * 0xE9 <four bytes displacement>
1308 * Note: the displacement is relative to the next instruction
1309 */
1310 pchCTEntry[cb] = 0xE9; /* jmp */
1311 *(unsigned long*)(void*)&pchCTEntry[cb+1] = aImportTab[i].ulAddress + cb - (unsigned long)&pchCTEntry[cb+5];
1312
1313 /*
1314 * Jump from original function to my function - an cli(?) could be needed here
1315 */
1316 *(char*)aImportTab[i].ulAddress = 0xE9; /* jmp */
1317 *(unsigned long*)(aImportTab[i].ulAddress + 1) = auFuncs[i] - (aImportTab[i].ulAddress + 5);
1318 }
1319 else
1320 { /* !fatal! - this could never happen really... */
1321 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1322 Int3(); /* ipe - later! */
1323 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1324 }
1325 pchCTEntry += OVERLOAD32_ENTRY;
1326 break;
1327 }
1328
1329
1330 /*
1331 * 16-bit procedure overload.
1332 * Currently disabled due to expected problems when calltab is a 32-bit segment.
1333 */
1334 case EPT_PROC16:
1335 {
1336 kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
1337 Int3();
1338
1339 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, TRUE);
1340 aImportTab[i].cbProlog = (char)cb;
1341 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) */
1342 { /* 7: size of a 16:32 jump which is added to the call tab */
1343 /*
1344 * Copy function prolog which is to be overwritten.
1345 */
1346 memcpy(pchCTEntry, (void*)aImportTab[i].ulAddress, (size_t)cb);
1347
1348 /*
1349 * Create far jump from calltab to original function.
1350 * 0xEA <four byte target address> <two byte target selector>
1351 */
1352 pchCTEntry[cb] = 0xEA; /* jmp far ptr */
1353 *(unsigned long*)(void*)&pchCTEntry[cb+1] = aImportTab[i].offObject;
1354 *(unsigned short*)(void*)&pchCTEntry[cb+5] = aImportTab[i].usSel;
1355
1356 /*
1357 * jump from original function to my function - an cli(?) could be needed here
1358 * 0x66 0xEA <four byte target address> <two byte target selector>
1359 */
1360 *(char*)(aImportTab[i].ulAddress ) = 0x66; /* operandsize prefix */
1361 *(char*)(aImportTab[i].ulAddress + 1) = 0xEA; /* jmp far ptr */
1362 *(unsigned long*)(aImportTab[i].ulAddress + 2) = auFuncs[i]; /* FIXME? */
1363 *(unsigned short*)(aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
1364 }
1365 else
1366 { /* !fatal! - this could never happen really... */
1367 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1368 Int3(); /* ipe - later! */
1369 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1370 }
1371 pchCTEntry += OVERLOAD16_ENTRY;
1372 break;
1373 }
1374
1375
1376 /*
1377 * 32-bit imported procedure.
1378 * This is called by issuing a near call to the callTab entry.
1379 */
1380 case EPT_PROCIMPORTNR32: /* Not required */
1381 if (!(pchCTEntry[6] = aImportTab[i].fFound))
1382 aImportTab[i].ulAddress = auFuncs[i];
1383 case EPT_PROCIMPORT32:
1384 {
1385 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, FALSE);
1386 aImportTab[i].cbProlog = (char)cb;
1387 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1388 {
1389 /*
1390 * Make jump instruction which jumps from calltab to original function.
1391 * 0xE9 <four bytes displacement>
1392 * Note: the displacement is relative to the next instruction
1393 */
1394 pchCTEntry[0] = 0xE9; /* jmp */
1395 *(unsigned*)(void*)&pchCTEntry[1] = aImportTab[i].ulAddress - (unsigned)&pchCTEntry[5];
1396 }
1397 else
1398 { /* !fatal! - this should never really happen... */
1399 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1400 Int3(); /* ipe - later! */
1401 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1402 }
1403 pchCTEntry += IMPORT32_ENTRY;
1404 break;
1405 }
1406
1407
1408 /*
1409 * 16-bit imported procedure.
1410 * This is called by issuing a far call to the calltab entry.
1411 */
1412 case EPT_PROCIMPORTNR16: /* Not required */
1413 if (!(pchCTEntry[7] = aImportTab[i].fFound))
1414 {
1415 aImportTab[i].ulAddress = auFuncs[i];
1416 Int3();
1417 break;
1418 }
1419 case EPT_PROCIMPORT16:
1420 {
1421 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, FALSE);
1422 aImportTab[i].cbProlog = (char)cb;
1423 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1424 {
1425 /*
1426 * Create far jump from calltab to original function.
1427 * 0xEA <four byte target address> <two byte target selector>
1428 */
1429 pchCTEntry[0] = 0xEA; /* jmp far ptr */
1430 *(unsigned long*)(void*)&pchCTEntry[1] = aImportTab[i].offObject;
1431 *(unsigned short*)(void*)&pchCTEntry[5] = aImportTab[i].usSel;
1432 }
1433 else
1434 { /* !fatal! - this should never really happen... */
1435 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1436 Int3(); /* ipe - later! */
1437 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1438 }
1439 pchCTEntry += IMPORT16_ENTRY;
1440 break;
1441 }
1442
1443
1444 /*
1445 * 16/32-bit importe variable.
1446 * This is used by accessing the 32-bit flat address in the callTab.
1447 * callTab-entry + 4 holds the offset of the variable into the object.
1448 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1449 * callTab-entry + a holds the 16-bit offset for the variable.
1450 * callTab-entry + c holds the selector for the object. (These two fields is the 16:16-bit pointer to the variable.)
1451 */
1452 case EPT_VARIMPORT32:
1453 case EPT_VARIMPORT16:
1454 aImportTab[i].cbProlog = (char)0;
1455 *(unsigned long*)(void*)&pchCTEntry[0] = aImportTab[i].ulAddress;
1456 *(unsigned long*)(void*)&pchCTEntry[4] = aImportTab[i].offObject;
1457 *(unsigned short*)(void*)&pchCTEntry[8] = aImportTab[i].usSel;
1458 *(unsigned short*)(void*)&pchCTEntry[0xa] = (unsigned short)aImportTab[i].offObject;
1459 *(unsigned short*)(void*)&pchCTEntry[0xc] = aImportTab[i].usSel;
1460 pchCTEntry += VARIMPORT_ENTRY;
1461 break;
1462
1463 default:
1464 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1465 Int3(); /* ipe - later! */
1466 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1467 } /* switch - type */
1468 } /* for */
1469
1470 return NO_ERROR;
1471}
1472
1473
1474#ifdef R3TST
1475/**
1476 * Creates a fake kernel MTE, SMTE and OTE for use while testing in Ring3.
1477 * @returns Pointer to the fake kernel MTE.
1478 * @status completely implemented.
1479 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1480 */
1481PMTE GetOS2KrnlMTETst(void)
1482{
1483 static MTE KrnlMTE;
1484 static SMTE KrnlSMTE;
1485
1486 KrnlMTE.mte_swapmte = &KrnlSMTE;
1487 KrnlSMTE.smte_objtab = &aKrnlOTE[0];
1488 KrnlSMTE.smte_objcnt = cObjectsFake;
1489
1490 return &KrnlMTE;
1491}
1492
1493/**
1494 * -Ring-3 testing-
1495 * Changes the entries in aImportTab to point to their fake equivalents.
1496 * @returns void
1497 * @param void
1498 * @status completely implemented.
1499 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1500 * @remark Called before the aImportTab array is used/verified.
1501 */
1502VOID R3TstFixImportTab(VOID)
1503{
1504 int i;
1505
1506 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1507 {
1508 switch (aImportTab[i].fType & ~EPT_NOT_REQ)
1509 {
1510 case EPT_PROC32:
1511 if (aTstFakers[i].fObj != 1)
1512 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROC32)\n", i));
1513 break;
1514 case EPT_PROCIMPORT32:
1515 if (aTstFakers[i].fObj != 1)
1516 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT32)\n", i));
1517 break;
1518 case EPT_PROCIMPORT16:
1519 if (aTstFakers[i].fObj != 2)
1520 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT16)\n", i));
1521 break;
1522 case EPT_VARIMPORT32:
1523 case EPT_VARIMPORT16:
1524 if (aTstFakers[i].fObj != 3 && aTstFakers[i].fObj != 4)
1525 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (VARIMPORT32/16)\n", i));
1526 break;
1527 } /* switch - type */
1528
1529 aImportTab[i].ulAddress = aTstFakers[i].uAddress;
1530 switch (aTstFakers[i].fObj)
1531 {
1532 case 1:
1533 aImportTab[i].usSel = GetSelectorCODE32();
1534 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE32START;
1535 break;
1536 case 2:
1537 aImportTab[i].usSel = GetSelectorCODE16();
1538 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE16START;
1539 break;
1540 case 3:
1541 aImportTab[i].usSel = GetSelectorDATA32();
1542 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA32START;
1543 break;
1544 case 4:
1545 aImportTab[i].usSel = GetSelectorDATA16();
1546 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA16START;
1547 break;
1548 default:
1549 kprintf(("R3TstFixImportTab: invalid segment config for entry %i.\n", i));
1550 }
1551 } /* for */
1552}
1553#endif
1554
1555/**
1556 * Dummy nop function if SecPathFromSFN isn't found.
1557 */
1558PSZ SECCALL nopSecPathFromSFN(SFN hFile)
1559{
1560 NOREF(hFile);
1561 return NULL;
1562}
Note: See TracBrowser for help on using the repository browser.