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

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

Added new function import.
Added some new modules.

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