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

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

Experimenting with ldrSetVMflags. Page alignment possible.

File size: 61.4 KB
Line 
1/* $Id: d32init.c,v 1.23 2000-09-08 21:34:10 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 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, /* 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#ifdef R3TST
1230 R3TstFixImportTab();
1231#endif
1232
1233 /*
1234 * verify proctable
1235 */
1236 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1237 {
1238 /* EPT_VARIMPORTs are skipped */
1239 if ((aImportTab[i].fType & ~EPT_BIT_MASK) == EPT_VARIMPORT)
1240 continue;
1241 /* EPT_NOT_REQ which is not found are set pointing to the nop function provided. */
1242 if (!aImportTab[i].fFound && (aImportTab[i].fType & EPT_NOT_REQ))
1243 {
1244 aImportTab[i].ulAddress = auFuncs[i];
1245 continue;
1246 }
1247
1248 if (EPT32BitEntry(aImportTab[i]))
1249 {
1250 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, aImportTab[i].fType == EPT_PROC32);
1251 cbmin = 5; /* Size of the jump instruction */
1252 }
1253 else
1254 {
1255 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, aImportTab[i].fType == EPT_PROC16);
1256 cbmin = 7; /* Size of the far jump instruction */
1257 }
1258 if (cb <= 0 || cb + cbmin >= MAXSIZE_PROLOG)
1259 {
1260 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
1261 return ERROR_D32_VERIFY_FAILED | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1262 }
1263 }
1264
1265 /*
1266 * rehook / import
1267 */
1268 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1269 {
1270 switch (aImportTab[i].fType & ~EPT_NOT_REQ)
1271 {
1272 /*
1273 * 32-bit procedure overload.
1274 * The overloading procedure is found in the auFuncs table (at the same index
1275 * as the overloaded procedure has in aImportTab).
1276 * The overloaded procedure is called by issuing a call to the callTab entry.
1277 */
1278 case EPT_PROC32:
1279 {
1280 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, TRUE);
1281 aImportTab[i].cbProlog = (char)cb;
1282 if (cb >= 5 && cb + 5 < MAXSIZE_PROLOG) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
1283 { /* 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. */
1284 /*
1285 * Copy function prolog which will be overwritten by the jmp to calltabl.
1286 */
1287 memcpy(callTab[i], (void*)aImportTab[i].ulAddress, (size_t)cb);
1288
1289 /*
1290 * Make jump instruction which jumps from calltab to original function.
1291 * 0xE9 <four bytes displacement>
1292 * Note: the displacement is relative to the next instruction
1293 */
1294 callTab[i][cb] = 0xE9; /* jmp */
1295 *(unsigned long*)(void*)&callTab[i][cb+1] = aImportTab[i].ulAddress + cb - (unsigned long)&callTab[i][cb+5];
1296
1297 /*
1298 * Jump from original function to my function - an cli(?) could be needed here
1299 */
1300 *(char*)aImportTab[i].ulAddress = 0xE9; /* jmp */
1301 *(unsigned long*)(aImportTab[i].ulAddress + 1) = auFuncs[i] - (aImportTab[i].ulAddress + 5);
1302 }
1303 else
1304 { /* !fatal! - this could never happen really... */
1305 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1306 Int3(); /* ipe - later! */
1307 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1308 }
1309 break;
1310 }
1311
1312
1313 /*
1314 * 16-bit procedure overload.
1315 * Currently disabled due to expected problems when calltab is a 32-bit segment.
1316 */
1317 case EPT_PROC16:
1318 {
1319 kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
1320 Int3();
1321
1322 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, TRUE);
1323 aImportTab[i].cbProlog = (char)cb;
1324 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) */
1325 { /* 7: size of a 16:32 jump which is added to the call tab */
1326 /*
1327 * Copy function prolog which is to be overwritten.
1328 */
1329 memcpy(callTab[i], (void*)aImportTab[i].ulAddress, (size_t)cb);
1330
1331 /*
1332 * Create far jump from calltab to original function.
1333 * 0xEA <four byte target address> <two byte target selector>
1334 */
1335 callTab[i][cb] = 0xEA; /* jmp far ptr */
1336 *(unsigned long*)(void*)&callTab[i][cb+1] = aImportTab[i].offObject;
1337 *(unsigned short*)(void*)&callTab[i][cb+5] = aImportTab[i].usSel;
1338
1339 /*
1340 * jump from original function to my function - an cli(?) could be needed here
1341 * 0x66 0xEA <four byte target address> <two byte target selector>
1342 */
1343 *(char*)(aImportTab[i].ulAddress ) = 0x66; /* operandsize prefix */
1344 *(char*)(aImportTab[i].ulAddress + 1) = 0xEA; /* jmp far ptr */
1345 *(unsigned long*)(aImportTab[i].ulAddress + 2) = auFuncs[i]; /* FIXME? */
1346 *(unsigned short*)(aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
1347 }
1348 else
1349 { /* !fatal! - this could never happen really... */
1350 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n", i));
1351 Int3(); /* ipe - later! */
1352 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1353 }
1354 break;
1355 }
1356
1357
1358 /*
1359 * 32-bit imported procedure
1360 * This is called by issuing a near call to the callTab entry.
1361 */
1362 case EPT_PROCIMPORT32:
1363 {
1364 cb = interpretFunctionProlog32((char*)aImportTab[i].ulAddress, FALSE);
1365 aImportTab[i].cbProlog = (char)cb;
1366 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1367 {
1368 /*
1369 * Make jump instruction which jumps from calltab to original function.
1370 * 0xE9 <four bytes displacement>
1371 * Note: the displacement is relative to the next instruction
1372 */
1373 callTab[i][0] = 0xE9; /* jmp */
1374 *(unsigned*)(void*)&callTab[i][1] = aImportTab[i].ulAddress - (unsigned)&callTab[i][5];
1375 }
1376 else
1377 { /* !fatal! - this should never really happen... */
1378 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1379 Int3(); /* ipe - later! */
1380 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1381 }
1382 break;
1383 }
1384
1385
1386 /*
1387 * 16-bit imported procedure.
1388 * This is called by issuing a far call to the calltab entry.
1389 */
1390 case EPT_PROCIMPORT16:
1391 {
1392 cb = interpretFunctionProlog16((char*)aImportTab[i].ulAddress, FALSE);
1393 aImportTab[i].cbProlog = (char)cb;
1394 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1395 {
1396 /*
1397 * Create far jump from calltab to original function.
1398 * 0xEA <four byte target address> <two byte target selector>
1399 */
1400 callTab[i][0] = 0xEA; /* jmp far ptr */
1401 *(unsigned long*)(void*)&callTab[i][1] = aImportTab[i].offObject;
1402 *(unsigned short*)(void*)&callTab[i][5] = aImportTab[i].usSel;
1403 }
1404 else
1405 { /* !fatal! - this should never really happen... */
1406 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n", i));
1407 Int3(); /* ipe - later! */
1408 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1409 }
1410 break;
1411 }
1412
1413
1414 /*
1415 * 16/32-bit importe variable.
1416 * This is used by accessing the 32-bit flat address in the callTab.
1417 * callTab-entry + 4 holds the offset of the variable into the object.
1418 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1419 * callTab-entry + a holds the 16-bit offset for the variable.
1420 * callTab-entry + c holds the selector for the object. (These two fields is the 16:16-bit pointer to the variable.)
1421 */
1422 case EPT_VARIMPORT32:
1423 case EPT_VARIMPORT16:
1424 aImportTab[i].cbProlog = (char)0;
1425 *(unsigned long*)(void*)&callTab[i][0] = aImportTab[i].ulAddress;
1426 *(unsigned long*)(void*)&callTab[i][4] = aImportTab[i].offObject;
1427 *(unsigned short*)(void*)&callTab[i][8] = aImportTab[i].usSel;
1428 *(unsigned short*)(void*)&callTab[i][0xa] = (unsigned short)aImportTab[i].offObject;
1429 *(unsigned short*)(void*)&callTab[i][0xc] = aImportTab[i].usSel;
1430 break;
1431
1432 default:
1433 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1434 Int3(); /* ipe - later! */
1435 return ERROR_D32_IPE | (i << ERROR_D32_PROC_SHIFT) | ERROR_D32_PROC_FLAG;
1436 } /* switch - type */
1437 } /* for */
1438
1439 return NO_ERROR;
1440}
1441
1442
1443#ifdef R3TST
1444/**
1445 * Creates a fake kernel MTE, SMTE and OTE for use while testing in Ring3.
1446 * @returns Pointer to the fake kernel MTE.
1447 * @status completely implemented.
1448 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1449 */
1450PMTE GetOS2KrnlMTETst(void)
1451{
1452 static MTE KrnlMTE;
1453 static SMTE KrnlSMTE;
1454
1455 KrnlMTE.mte_swapmte = &KrnlSMTE;
1456 KrnlSMTE.smte_objtab = &aKrnlOTE[0];
1457 KrnlSMTE.smte_objcnt = cObjectsFake;
1458
1459 return &KrnlMTE;
1460}
1461
1462/**
1463 * -Ring-3 testing-
1464 * Changes the entries in aImportTab to point to their fake equivalents.
1465 * @returns void
1466 * @param void
1467 * @status completely implemented.
1468 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1469 * @remark Called before the aImportTab array is used/verified.
1470 */
1471VOID R3TstFixImportTab(VOID)
1472{
1473 struct _TstFaker
1474 {
1475 unsigned uAddress;
1476 int fObj; /* 1 = CODE32, 2 = CODE16, 3 = DATA32, 4 = DATA16 */
1477 }
1478 aTstFakers[NBR_OF_KRNLIMPORTS] =
1479 {
1480 {(unsigned)fakeldrRead, 1},
1481 {(unsigned)fakeldrOpen, 1},
1482 {(unsigned)fakeldrClose, 1},
1483 {(unsigned)fakeLDRQAppType, 1},
1484 {(unsigned)fakeldrEnum32bitRelRecs, 1},
1485 {(unsigned)fakeIOSftOpen, 1},
1486 {(unsigned)fakeIOSftClose, 1},
1487 {(unsigned)fakeIOSftTransPath, 1},
1488 {(unsigned)fakeIOSftReadAt, 1},
1489 {(unsigned)fakeIOSftWriteAt, 1},
1490 {(unsigned)fakeSftFileSize, 1},
1491 {(unsigned)fakeVMAllocMem, 1},
1492 {(unsigned)fakeVMGetOwner, 1},
1493 {(unsigned)fakeg_tkExecPgm, 1},
1494 {(unsigned)fake_tkStartProcess, 1},
1495 {(unsigned)fakef_FuStrLenZ, 2},
1496 {(unsigned)fakef_FuStrLen, 2},
1497 {(unsigned)fakef_FuBuff, 2},
1498 {(unsigned)fakeVMObjHandleInfo, 1},
1499 {(unsigned)fakeldrASMpMTEFromHandle,1},
1500 {(unsigned)fakeldrOpenPath, 1},
1501 {(unsigned)fakeLDRClearSem, 1},
1502 {(unsigned)fakeldrFindModule, 1},
1503 {(unsigned)fakeKSEMRequestMutex, 1},
1504 {(unsigned)fakeKSEMReleaseMutex, 1},
1505 {(unsigned)fakeKSEMQueryMutex, 1},
1506 {(unsigned)fakeKSEMInit, 1},
1507 {(unsigned)&fakeLDRSem, 3},
1508 {(unsigned)&fakeLDRLibPath, 3},
1509 {(unsigned)fakeTKSuBuff, 1},
1510 {(unsigned)fakeTKFuBuff, 1},
1511 {(unsigned)fakeTKFuBufLen, 1},
1512 {(unsigned)fakeldrValidateMteHandle,1},
1513 {(unsigned)&fakepTCBCur, 4},
1514 {(unsigned)&fakepPTDACur, 4},
1515 {(unsigned)&fakeptda_start, 4},
1516 {(unsigned)&fakeptda_environ, 4},
1517 {(unsigned)&fakeptda_ptdasem, 4},
1518 {(unsigned)&fakeptda_module, 4},
1519 {(unsigned)&fakeptda_pBeginLIBPATH, 4},
1520 {(unsigned)&fakeldrpFileNameBuf, 3},
1521 {(unsigned)&fakeSecPathFromSFN, 3}
1522 #if 0 /* experimenting */
1523 ,{(unsigned)&fakeldrSetVMflags, 1}
1524 #endif
1525 };
1526 int i;
1527
1528 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
1529 {
1530 switch (aImportTab[i].fType)
1531 {
1532 case EPT_PROC32:
1533 if (aTstFakers[i].fObj != 1)
1534 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROC32)\n", i));
1535 break;
1536 case EPT_PROCIMPORT32:
1537 if (aTstFakers[i].fObj != 1)
1538 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT32)\n", i));
1539 break;
1540 case EPT_PROCIMPORT16:
1541 if (aTstFakers[i].fObj != 2)
1542 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (PROCIMPORT16)\n", i));
1543 break;
1544 case EPT_VARIMPORT32:
1545 case EPT_VARIMPORT16:
1546 if (aTstFakers[i].fObj != 3 && aTstFakers[i].fObj != 4)
1547 kprintf(("R3TstFixImportTab: invalid segment config for entry %i. (VARIMPORT32/16)\n", i));
1548 break;
1549 } /* switch - type */
1550
1551 aImportTab[i].ulAddress = aTstFakers[i].uAddress;
1552 switch (aTstFakers[i].fObj)
1553 {
1554 case 1:
1555 aImportTab[i].usSel = GetSelectorCODE32();
1556 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE32START;
1557 break;
1558 case 2:
1559 aImportTab[i].usSel = GetSelectorCODE16();
1560 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&CODE16START;
1561 break;
1562 case 3:
1563 aImportTab[i].usSel = GetSelectorDATA32();
1564 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA32START;
1565 break;
1566 case 4:
1567 aImportTab[i].usSel = GetSelectorDATA16();
1568 aImportTab[i].offObject = aTstFakers[i].uAddress - (unsigned)&DATA16START;
1569 break;
1570 default:
1571 kprintf(("R3TstFixImportTab: invalid segment config for entry %i.\n", i));
1572 }
1573 } /* for */
1574}
1575#endif
1576
1577/**
1578 * Dummy nop function if SecPathFromSFN isn't found.
1579 */
1580PSZ SECCALL nopSecPathFromSFN(SFN hFile)
1581{
1582 NOREF(hFile);
1583 return NULL;
1584}
Note: See TracBrowser for help on using the repository browser.