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

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

Added option for EXE fixes.

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