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

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

Merged in the Grace branch. New Win32k!

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