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

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

Changed and hopefully corrected code identifying the kernel type.

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