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

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

Corrected problem with kernel build 14053. (new parameter to ldrOpenPath)
Added symbols for 14053 and 8266.

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