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

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

Added support for kernel revisions up to 'E'. Added support for new import prolog (PGPhysAvail).

File size: 60.1 KB
Line 
1/* $Id: d32init.c,v 1.33 2001-02-11 15:21:09 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 break;
1463 }
1464 case EPT_VARIMPORT32:
1465 case EPT_VARIMPORT16:
1466 aImportTab[i].cbProlog = (char)0;
1467 *(unsigned long*)(void*)&pchCTEntry[0] = aImportTab[i].ulAddress;
1468 *(unsigned long*)(void*)&pchCTEntry[4] = aImportTab[i].offObject;
1469 *(unsigned short*)(void*)&pchCTEntry[8] = aImportTab[i].usSel;
1470 *(unsigned short*)(void*)&pchCTEntry[0xa] = (unsigned short)aImportTab[i].offObject;
1471 *(unsigned short*)(void*)&pchCTEntry[0xc] = aImportTab[i].usSel;
1472 pchCTEntry += VARIMPORT_ENTRY;
1473 break;
1474
1475 default:
1476 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1477 Int3(); /* ipe - later! */
1478 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1479 } /* switch - type */
1480 } /* for */
1481
1482 return NO_ERROR;
1483}
1484
1485
1486#ifdef R3TST
1487/**
1488 * Creates a fake kernel MTE, SMTE and OTE for use while testing in Ring3.
1489 * @returns Pointer to the fake kernel MTE.
1490 * @status completely implemented.
1491 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1492 */
1493PMTE GetOS2KrnlMTETst(void)
1494{
1495 static MTE KrnlMTE;
1496 static SMTE KrnlSMTE;
1497
1498 KrnlMTE.mte_swapmte = &KrnlSMTE;
1499 KrnlSMTE.smte_objtab = &aKrnlOTE[0];
1500 KrnlSMTE.smte_objcnt = cObjectsFake;
1501
1502 return &KrnlMTE;
1503}
1504
1505/**
1506 * -Ring-3 testing-
1507 * Changes the entries in aImportTab to point to their fake equivalents.
1508 * @returns void
1509 * @param void
1510 * @status completely implemented.
1511 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1512 * @remark Called before the aImportTab array is used/verified.
1513 */
1514VOID R3TstFixImportTab(VOID)
1515{
1516 int i;
1517
1518 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1519 {
1520 switch (aImportTab[i].fType & ~EPT_NOT_REQ)
1521 {
1522 case EPT_PROC32:
1523 if (aTstFakers[i].fObj != 1)
1524 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROC32)\n", i));
1525 break;
1526 case EPT_PROCIMPORT32:
1527 if (aTstFakers[i].fObj != 1)
1528 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT32)\n", i));
1529 break;
1530 case EPT_PROCIMPORT16:
1531 if (aTstFakers[i].fObj != 2)
1532 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT16)\n", i));
1533 break;
1534 case EPT_VARIMPORT32:
1535 case EPT_VARIMPORT16:
1536 if (aTstFakers[i].fObj != 3 && aTstFakers[i].fObj != 4)
1537 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (VARIMPORT32/16)\n", i));
1538 break;
1539 } /* switch - type */
1540
1541 aImportTab[i].ulAddress = aTstFakers[i].uAddress;
1542 switch (aTstFakers[i].fObj)
1543 {
1544 case 1:
1545 aImportTab[i].usSel = GetSelectorCODE32();
1546 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE32START;
1547 break;
1548 case 2:
1549 aImportTab[i].usSel = GetSelectorCODE16();
1550 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE16START;
1551 break;
1552 case 3:
1553 aImportTab[i].usSel = GetSelectorDATA32();
1554 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA32START;
1555 break;
1556 case 4:
1557 aImportTab[i].usSel = GetSelectorDATA16();
1558 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA16START;
1559 break;
1560 default:
1561 kprintf(("R3TstFixImportTab: invalid segment config for entry %i.\n", i));
1562 }
1563 } /* for */
1564}
1565#endif
1566
1567/**
1568 * Dummy nop function if SecPathFromSFN isn't found.
1569 */
1570PSZ SECCALL nopSecPathFromSFN(SFN hFile)
1571{
1572 NOREF(hFile);
1573 return NULL;
1574}
Note: See TracBrowser for help on using the repository browser.