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

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

Implemented tool for generating calltab for kernel imports. (mkcalltab)
Implemented API for accessing memory in another process. (*ProcessReadWrite)
Added kernel imports needed to implemented ProcessReadWrite.
Removed unused kernel imports.

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