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

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

ldrCheckInternalName starts with an "sub esp, imm8; push..". This
is now supported for overriding. (It wasn't this way in 14.039!, it is in
14.063.)

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