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

Last change on this file since 2878 was 2878, checked in by bird, 26 years ago

Corrections for Aurora retail kernel.

File size: 46.7 KB
Line 
1/* $Id: d32init.c,v 1.15 2000-02-23 23:01:00 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
18
19#define INCL_DOSERRORS
20#define INCL_NOPMAPI
21#define LDR_INCL_INITONLY
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#include <os2.h>
27
28#include <string.h>
29
30#include "OS2Krnl.h"
31#include "options.h"
32#include "dev1632.h"
33#include "dev32.h"
34#include "dev32hlp.h"
35#include "probkrnl.h"
36#include "log.h"
37#include "asmutils.h"
38#include "malloc.h"
39#include "ldr.h"
40#include "ldrCalls.h"
41#include "macros.h"
42
43
44/*******************************************************************************
45* Global Variables *
46*******************************************************************************/
47#ifdef DEBUG
48static char * apszPE[] = {"FLAGS_PE_NOT", "FLAGS_PE_PE2LX", "FLAGS_PE_PE", "FLAGS_PE_MIXED", "!invalid!"};
49static char * apszInfoLevel[] = {"INFOLEVEL_QUIET", "INFOLEVEL_ERROR", "INFOLEVEL_WARNING", "INFOLEVEL_INFO", "INFOLEVEL_INFOALL", "!invalid!"};
50#endif
51
52/*******************************************************************************
53* Internal Functions *
54*******************************************************************************/
55static ULONG readnum(const char *pszNum);
56_Inline int ModR_M_32bit(char bModRM);
57static int interpretFunctionProlog32(char *pach, BOOL fOverload);
58static int interpretFunctionProlog16(char *pach, BOOL fOverload);
59static int ImportTabInit(void);
60
61
62/* externs located in 16-bit data segement in ProbKrnl.c */
63extern ULONG _TKSSBase16;
64extern USHORT _R0FlatCS16;
65extern USHORT _R0FlatDS16;
66
67/* extern(s) located in calltab.asm */
68extern char callTab[NBR_OF_KRNLIMPORTS][MAXSIZE_PROLOG];
69
70/* extern(s) located in mytkExecPgm.asm */
71extern char mytkExecPgm;
72extern char CODE32START;
73extern char CODE32END;
74extern char CONST32_ROEND;
75extern char DATA16START;
76extern char DATA16_CONSTEND;
77
78
79#ifndef DEBUGR3
80/**
81 * Ring-0, 32-bit, init function.
82 * @returns Status word.
83 * @param pRpInit Pointer init request packet.
84 * @sketch Set TKSSBase32.
85 * Set default parameters.
86 * Parse command line options.
87 * Show (kprint) configuration.
88 * Init heap.
89 * Init ldr.
90 * Init procs. (overloaded ldr procedures)
91 * @status completely implemented.
92 * @author knut st. osmundsen
93 */
94USHORT _loadds _Far32 _Pascal R0Init32(RP32INIT *pRpInit)
95{
96 char *pszTmp2;
97 char *pszTmp;
98 ULONG ul;
99 APIRET rc;
100 LOCKHANDLE lhData16={0,0,0,0, 0,0,0,0, 0,0,0,0};
101 LOCKHANDLE lhData = {0,0,0,0, 0,0,0,0, 0,0,0,0};
102 LOCKHANDLE lhCode = {0,0,0,0, 0,0,0,0, 0,0,0,0};
103
104 pulTKSSBase32 = (PULONG)_TKSSBase16;
105
106 SET_OPTIONS_TO_DEFAULT(options);
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 = _ulBuild;
276 options.usVerMajor = _usVerMajor;
277 options.usVerMinor = _usVerMinor;
278
279 /* log option summary - FIXME */
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 /* end option summary */
309
310
311 /*
312 * init sub-parts
313 */
314 /* heap */
315 if (heapInit(options.cbResHeapInit, options.cbResHeapMax,
316 options.cbSwpHeapInit, options.cbSwpHeapMax) != NO_ERROR)
317 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
318
319 /* loader */
320 if (!options.fNoLoader)
321 if (ldrInit() != NO_ERROR)
322 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
323
324 /* functionoverrides */
325 if (!options.fNoLoader)
326 if (ImportTabInit() != NO_ERROR)
327 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
328
329 /*
330 * Lock the 32-bit objects/segments and 16-bit datasegment in memory
331 */
332 /* 32-bit code segment */
333 rc = D32Hlp_VMLock2(&CODE32START,
334 ((unsigned)&CODE32END & ~0xFFF) - (unsigned)&CODE32START, /* Round down so we don't overlap with the next request. */
335 VMDHL_LONG,
336 SSToDS(&lhCode));
337 if (rc != NO_ERROR)
338 kprintf(("code segment lock failed with with rc=%d\n", rc));
339
340 /* 32-bit data segment */
341 rc = D32Hlp_VMLock2(callTab,
342 &CONST32_ROEND - (char*)callTab,
343 VMDHL_LONG | VMDHL_WRITE,
344 SSToDS(&lhData));
345 if (rc != NO_ERROR)
346 kprintf(("data segment lock failed with with rc=%d\n", rc));
347
348 /* 16-bit data segment */
349 rc = D32Hlp_VMLock2(&DATA16START,
350 &DATA16_CONSTEND - &DATA16START,
351 VMDHL_LONG | VMDHL_WRITE,
352 SSToDS(&lhData16));
353 if (rc != NO_ERROR)
354 kprintf(("data segment lock failed with with rc=%d\n", rc));
355
356 return STATUS_DONE;
357}
358
359
360/**
361 * Reads a number (unsigned long integer) for a string.
362 * @returns number read, ~0UL on error / no number read.
363 * @param pszNum Pointer to the string containing the number.
364 * @status competely implemented.
365 * @author knut st. osmundsen
366 */
367static ULONG readnum(const char *pszNum)
368{
369 ULONG ulRet = 0;
370 ULONG ulBase = 10;
371 int i = 0;
372
373 if (*pszNum == '0')
374 if (pszNum[1] == 'x' || pszNum[1] == 'X')
375 {
376 ulBase = 16;
377 pszNum += 2;
378 }
379 else
380 {
381 ulBase = 8;
382 i = 1;
383 }
384
385 /* read digits */
386 while (ulBase == 16 ? (pszNum[i] >= '0' && pszNum[i] <= '9') || (pszNum[i] >= 'a' && pszNum[i] <= 'f') || (pszNum[i] >= 'A' && pszNum[i] <= 'F')
387 : (pszNum[i] >= '0' && pszNum[i] <= (ulBase == 10 ? '9' : '7'))
388 )
389 {
390 ulRet *= ulBase;
391 if (ulBase <= 10)
392 ulRet += pszNum[i] - '0';
393 else
394 ulRet += pszNum[i] - (pszNum[i] >= 'A' ? 'A' - 10 : (pszNum[i] >= 'a' ? 'a' + 9 : '0'));
395
396 i++;
397 }
398
399 return i > 0 ? ulRet : ~0UL;
400}
401
402
403/**
404 * Get kernel OTEs
405 * @returns Strategy return code:
406 * STATUS_DONE on success.
407 * STATUS_DONE | STERR | errorcode on failure.
408 * @param pOTEBuf Pointer to output buffer.
409 * @status completely implemented and tested.
410 * @author knut st. osmundsen
411 * @remark Called from IOCtl.
412 */
413USHORT _loadds _Far32 _Pascal GetOTEs32(PKRNLOBJTABLE pOTEBuf)
414{
415 PMTE pMTE;
416 PSMTE pSMTE;
417 POTE pOTE;
418 int i;
419 USHORT usRc;
420
421 pMTE = GetOS2KrnlMTE();
422 if (pMTE != NULL)
423 {
424 pSMTE = pMTE->mte_swapmte;
425 if (pSMTE != NULL)
426 {
427 pOTEBuf->cObjects = (unsigned char)pSMTE->smte_objcnt;
428 if (pSMTE->smte_objcnt <= MAXKRNLOBJECTS)
429 {
430 pOTE = pSMTE->smte_objtab;
431 if (pOTE != NULL)
432 {
433 /* Copy OTEs */
434 for (i = 0; i < pOTEBuf->cObjects; i++)
435 memcpy((void*)&pOTEBuf->aObjects[i], &pOTE[i], sizeof(OTE));
436 usRc = 0;
437
438 /*
439 * Search for internal revision stuff in the two first objects.
440 */
441 #if 0
442 for (i = 0; i < 2; i++)
443 {
444 const char *psz = (const char*)pOTE[i].ote_base;
445 const char *pszEnd = psz + pOTE[i].ote_size;
446
447 while (psz + 100 < pszEnd)
448 {
449 strncmp(psz, "Internal revision");
450
451 /* next */
452 psz++;
453 }
454 }
455 #endif
456 }
457 else
458 usRc = 4;
459 }
460 else
461 usRc = 3;
462 }
463 else
464 usRc = 2;
465 }
466 else
467 usRc = 1;
468
469 if (usRc != 0)
470 kprintf(("GetOTEs32: failed. usRc = %d\n", usRc));
471
472 return (USHORT)(usRc | (usRc != NO_ERROR ? STATUS_DONE | STERR : STATUS_DONE));
473}
474#endif /* !DEBUGR3*/
475
476
477
478/**
479 * Functions which cacluates the instructionsize given a ModR/M byte.
480 * @returns Number of bytes to add to cb and pach.
481 * @param bModRM ModR/M byte.
482 * @status completely implemented.
483 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
484 */
485_Inline int ModR_M_32bit(char bModRM)
486{
487 if ((bModRM & 0xc0) == 0x80 /* ex. mov ax,[ebp+11145543h] */
488 || ((bModRM & 0xc0) == 0 && (bModRM & 0x07) == 5)) /* ex. mov ebp,[0ff231234h] */
489 { /* 32-bit displacement */
490 return 5;
491 }
492 else if ((bModRM & 0xc0) == 0x40) /* ex. mov ecx,[esi]+4fh */
493 { /* 8-bit displacement */
494 return 2;
495 }
496 /* no displacement (only /r byte) */
497 return 1;
498}
499
500
501
502
503
504/**
505 * 32-bit! Interpret function prolog to find where to jmp back.
506 * @returns Length of prolog need to be copied - which is also the offset of
507 * where the jmp instr should be placed.
508 * On error it returns 0.
509 * @param pach Pointer to prolog.
510 * @param fOverload TRUE: Function is to be overloaded.
511 * FALSE: Function is to be imported.
512 */
513static int interpretFunctionProlog32(char *pach, BOOL fOverload)
514{
515 int cb = -3;
516
517 kprintf(("interpretFunctionProlog32(0x%08x, %d):\n"
518 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
519 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
520 pach, fOverload,
521 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
522 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
523
524 /*
525 * check for the well known prolog (the only that is supported now)
526 * which is:
527 * push ebp
528 * mov ebp,esp
529 * or
530 * push ebp
531 * mov eax, dword ptr [xxxxxxxx]
532 *
533 * These are allowed when not overloading:
534 * mov eax, imm32
535 * jmp short
536 * or
537 * mov eax, imm32
538 * push ebp
539 * or
540 * mov eax, msoff32
541 *
542 */
543 if ((pach[0] == 0x55 && (pach[1] == 0x8b || pach[1] == 0xa1)) /* two first prologs */
544 ||
545 (pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55 ) && !fOverload) /* two next prologs */
546 ||
547 (pach[0] == 0xa1 && !fOverload) /* last prolog */
548 )
549 {
550 BOOL fForce;
551 cb = 0;
552 while (cb < 5 || fForce) /* 5 is the size of a jump instruction. */
553 {
554 int cb2;
555 fForce = FALSE;
556 switch (*pach)
557 {
558 /* simple one byte prefixes */
559 case 0x2e: /* cs segment override */
560 case 0x36: /* ss segment override */
561 case 0x3e: /* ds segment override */
562 case 0x26: /* es segment override */
563 case 0x64: /* fs segment override */
564 case 0x65: /* gs segment override */
565 fForce = TRUE;
566 break;
567
568 /* simple one byte instructions */
569 case 0x50: /* push ax */
570 case 0x51: /* push cx */
571 case 0x52: /* push dx */
572 case 0x53: /* push bx */
573 case 0x54: /* push sp */
574 case 0x55: /* push bp */
575 case 0x56: /* push si */
576 case 0x57: /* push di */
577 break;
578
579 /* simple two byte instructions */
580 case 0xb0: /* mov al, imm8 */
581 case 0xb1: /* mov cl, imm8 */
582 case 0xb2: /* mov dl, imm8 */
583 case 0xb3: /* mov bl, imm8 */
584 case 0xb4: /* mov ah, imm8 */
585 case 0xb5: /* mov ch, imm8 */
586 case 0xb6: /* mov dh, imm8 */
587 case 0xb7: /* mov bh, imm8 */
588 case 0x2c: /* sub al, imm8 */
589 case 0x34: /* xor al, imm8 */
590 case 0x3c: /* cmp al, imm8 */
591 case 0x6a: /* push <byte> */
592 case 0xa0: /* mov al, moffs8 */
593 case 0xa2: /* mov moffs8, al */
594 pach++;
595 cb++;
596 break;
597
598 /* simple five byte instructions */
599 case 0xb8: /* mov eax, imm32 */
600 case 0xb9: /* mov ecx, imm32 */
601 case 0xba: /* mov edx, imm32 */
602 case 0xbb: /* mov ebx, imm32 */
603 case 0xbc: /* mov esx, imm32 */
604 case 0xbd: /* mov ebx, imm32 */
605 case 0xbe: /* mov esi, imm32 */
606 case 0xbf: /* mov edi, imm32 */
607 case 0x2d: /* sub eax, imm32 */
608 case 0x35: /* xor eax, imm32 */
609 case 0x3d: /* cmp eax, imm32 */
610 case 0x68: /* push <dword> */
611 case 0xa1: /* mov eax, moffs16 */
612 case 0xa3: /* mov moffs16, eax */
613 pach += 4;
614 cb += 4;
615 break;
616
617 /* complex sized instructions - "/r" */
618 case 0x30: /* xor r/m8, r8 */
619 case 0x31: /* xor r/m32, r32 */
620 case 0x32: /* xor r8, r/m8 */
621 case 0x33: /* xor r32, r/m32 */
622 case 0x38: /* cmp r/m8, r8 */
623 case 0x39: /* cmp r/m32, r32 */
624 case 0x3a: /* cmp r8, r/m8 */
625 case 0x3b: /* cmp r32, r/m32 */
626 case 0x28: /* sub r/m8, r8 */
627 case 0x29: /* sub r/m32, r32 */
628 case 0x2a: /* sub r8, r/m8 */
629 case 0x2b: /* sub r32, r/m32 */
630 case 0x8b: /* mov /r */
631 case 0x8d: /* lea /r */
632 if ((pach[1] & 0x7) == 4 && (pach[1] & 0xc0) != 0xc0) /* invalid instruction!?! */
633 return -1;
634 cb += cb2 = ModR_M_32bit(pach[1]);
635 pach += cb2;
636 break;
637
638 /* complex sized instruction - "/5 ib" */
639 case 0x80: /* 5: sub r/m8, imm8 7: cmp r/m8, imm8 */
640 case 0x83: /* 5: sub r/m32, imm8 7: cmp r/m32, imm8 */
641 if ((pach[1] & 0x38) == (5<<3)
642 || (pach[1] & 0x38) == (7<<3)
643 )
644 {
645 cb += cb2 = 1 + ModR_M_32bit(pach[1]); /* 1 is the size of the imm8 */
646 pach += cb2;
647 }
648 else
649 {
650 kprintf(("interpretFunctionProlog32: unknown instruction (-3) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
651 return -3;
652 }
653 break;
654
655 /* complex sized instruction - "/digit id" */
656 case 0x81: /* sub r/m32, imm32 + more instructions! */
657 if ((pach[1] & 0x38) == (5<<3) /* sub r/m32, imm32 */
658 || (pach[1] & 0x38) == (7<<3) /* cmp r/m32, imm32 */
659 )
660 {
661 cb += cb2 = 4 + ModR_M_32bit(pach[1]); /* 4 is the size of the imm32 */
662 pach += cb2;
663 }
664 else
665 {
666 kprintf(("interpretFunctionProlog32: unknown instruction (-2) 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
667 return -2;
668 }
669 break;
670
671 default:
672 kprintf(("interpretFunctionProlog32: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
673 return 0;
674 }
675 pach++;
676 cb++;
677 }
678 }
679 else
680 {
681 kprintf(("interpretFunctionProlog32: unknown prolog start. 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
682 cb = 0;
683 }
684 return cb;
685}
686
687
688/**
689 * 16-bit! Interpret function prolog to find where to jmp back.
690 * @returns Length of prolog need to be copied - which is also the offset of
691 * where the jmp instr should be placed.
692 * On error it returns 0.
693 * @param pach Pointer to prolog.
694 * @param fOverload TRUE: Function is to be overloaded.
695 * FALSE: Function is to be imported.
696 */
697static int interpretFunctionProlog16(char *pach, BOOL fOverload)
698{
699 int cb = -7;
700
701 kprintf(("interpretFunctionProlog16(0x%08x, %d):\n"
702 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n"
703 "\t%02x %02x %02x %02x - %02x %02x %02x %02x\n",
704 pach, fOverload,
705 pach[0], pach[1], pach[2], pach[3], pach[4], pach[5], pach[6], pach[7],
706 pach[8], pach[9], pach[10],pach[11],pach[12],pach[13],pach[14],pach[15]));
707 /*
708 * Check for the well known prolog (the only that is supported now)
709 * which is:
710 * push 2
711 */
712 if (*pach == 0x6A) /* push 2 (don't check for the 2) */
713 {
714 BOOL fForce;
715 int cOpPrefix = 0;
716 cb = 0;
717 while (cb < 8 || fForce) /* 8 is the size of a 66h prefixed far jump instruction. */
718 {
719 fForce = FALSE;
720 switch (*pach)
721 {
722 case 0x0f: /* push gs and push fs */
723 if (pach[1] != 0xA0 && pach[1] != 0xA8)
724 {
725 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
726 return -11;
727 }
728 pach++;
729 cb++;
730 break;
731
732 case 0x50: /* push ax */
733 case 0x51: /* push cx */
734 case 0x52: /* push dx */
735 case 0x53: /* push bx */
736 case 0x54: /* push sp */
737 case 0x55: /* push bp */
738 case 0x56: /* push si */
739 case 0x57: /* push di */
740 break;
741
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 if (cOpPrefix > 0)
750 cOpPrefix++;
751 break;
752
753 case 0x66:
754 cOpPrefix = 2; /* it's decremented once before it's used. */
755 fForce = TRUE;
756 break;
757
758 case 0x6a: /* push <byte> */
759 pach++;
760 cb++;
761 break;
762
763 case 0x68: /* push <word> */
764 if (cOpPrefix > 0)
765 {
766 pach += 2;
767 cb += 2;
768 }
769 pach += 2;
770 cb += 2;
771 break;
772
773 case 0x8b: /* mov /r */
774 if ((pach[1] & 0xc0) == 0x80 /* ex. mov ax,bp+1114h */
775 || ((pach[1] & 0xc0) == 0 && (pach[1] & 0x7) == 6)) /* ex. mov bp,0ff23h */
776 { /* 16-bit displacement */
777 if (cOpPrefix > 0)
778 {
779 pach += 2;
780 cb += 2;
781 }
782 pach += 3;
783 cb += 3;
784 }
785 else
786 if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
787 { /* 8-bit displacement */
788 pach += 2;
789 cb += 2;
790 }
791 else
792 { /* no displacement (only /r byte) */
793 pach++;
794 cb++;
795 }
796 break;
797
798 default:
799 kprintf(("interpretFunctionProlog16: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
800 return 0;
801 }
802 pach++;
803 cb++;
804 if (cOpPrefix > 0)
805 cOpPrefix--;
806 }
807 }
808
809 fOverload = fOverload;
810 return cb;
811}
812
813
814#ifndef DEBUGR3
815/**
816 * Verifies the aImportTab.
817 * @returns 0 if ok. !0 if not ok.
818 * @remark Called from IOCtl.
819 * WARNING! VerifyImporTab32 is called before the initroutine!
820 */
821USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
822{
823 int i;
824 int cb;
825 int cbmin;
826
827 /* VerifyImporTab32 is called before the initroutine! */
828 pulTKSSBase32 = (PULONG)_TKSSBase16;
829
830 /* verify */
831 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
832 {
833 /* verify that it is found */
834 if (!_aImportTab[i].fFound)
835 {
836 kprintf(("VerifyImportTab32: procedure no.%d was not found!\n", i));
837 return STATUS_DONE | STERR | 1;
838 }
839
840 /* verify read/writeable. - FIXME */
841 if (_aImportTab[i].ulAddress < 0xffe00000UL)
842 {
843 kprintf(("VerifyImportTab32: procedure no.%d has an invlalid address, %#08x!\n",
844 i, _aImportTab[i].ulAddress));
845 return STATUS_DONE | STERR | 2;
846 }
847
848 switch (_aImportTab[i].fType & ~EPT_BIT_MASK)
849 {
850 case EPT_PROC:
851 case EPT_PROCIMPORT:
852 /*
853 * Verify known function prolog.
854 */
855 if (EPT32BitEntry(_aImportTab[i]))
856 {
857 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
858 cbmin = 5; /* Size of the jump instruction */
859 }
860 else
861 {
862 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
863 cbmin = 7; /* Size of the far jump instruction */
864 }
865
866 /*
867 * Check result of the function prolog interpretations.
868 */
869 if (cb <= 0 && cb + cbmin >= MAXSIZE_PROLOG)
870 { /* failed, too small or too large. */
871 kprintf(("VerifyImportTab32: verify failed for procedure no.%d (cd=%d)\n", i, cb));
872 return STATUS_DONE | STERR | 3;
873 }
874 break;
875
876 case EPT_VARIMPORT:
877 /* do nothing! */
878 break;
879
880 default:
881 kprintf(("VerifyImportTab32: only EPT_PROC is implemented\n",i));
882 Int3(); /* temporary fix! */
883 return STATUS_DONE | STERR | 4;
884 }
885 }
886
887 return STATUS_DONE;
888}
889
890
891/**
892 * Initiates the overrided functions.
893 * @returns NO_ERROR on success. !0 on error.
894 */
895static int importTabInit(void)
896{
897 /* This table must be updated with the overloading functions. */
898 static unsigned auFuncs[NBR_OF_KRNLIMPORTS] =
899 {
900 (unsigned)myldrRead,
901 (unsigned)myldrOpen,
902 (unsigned)myldrClose,
903 (unsigned)myLDRQAppType,
904 (unsigned)myldrEnum32bitRelRecs,
905 0,
906 0,
907 0,
908 0,
909 0,
910 0,
911 0,
912 0,
913 (unsigned)&mytkExecPgm,
914 0,
915 0,
916 0
917 };
918
919 int i;
920 int cb;
921 int cbmin;
922
923 /*
924 * verify proctable
925 */
926 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
927 {
928 /* EPT_VARIMPORTs are skipped */
929 if ((_aImportTab[i].fType & ~EPT_BIT_MASK) == EPT_VARIMPORT)
930 continue;
931
932 if (EPT32BitEntry(_aImportTab[i]))
933 {
934 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
935 cbmin = 5; /* Size of the jump instruction */
936 }
937 else
938 {
939 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
940 cbmin = 7; /* Size of the far jump instruction */
941 }
942 if (cb <= 0 || cb + cbmin >= MAXSIZE_PROLOG)
943 {
944 kprintf(("ImportTabInit: Verify failed for procedure no.%d, cb=%d\n", i, cb));
945 return 1;
946 }
947 }
948
949 /*
950 * rehook / import
951 */
952 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
953 {
954 switch (_aImportTab[i].fType)
955 {
956 /*
957 * 32-bit procedure overload.
958 * The overloading procedure is found in the auFuncs table (at the same index
959 * as the overloaded procedure has in aImportTab).
960 * The overloaded procedure is called by issuing a call to the callTab entry.
961 */
962 case EPT_PROC32:
963 {
964 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, TRUE);
965 _aImportTab[i].cbProlog = (char)cb;
966 if (cb >= 5 && cb + 5 < MAXSIZE_PROLOG) /* 5(1st): size of jump instruction in the function prolog which jumps to my overloading function */
967 { /* 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. */
968 /*
969 * Copy function prolog which will be overwritten by the jmp to calltabl.
970 */
971 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
972
973 /*
974 * Make jump instruction which jumps from calltab to original function.
975 * 0xE9 <four bytes displacement>
976 * Note: the displacement is relative to the next instruction
977 */
978 callTab[i][cb] = 0xE9; /* jmp */
979 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].ulAddress + cb - (unsigned long)&callTab[i][cb+5];
980
981 /*
982 * Jump from original function to my function - an cli(?) could be needed here
983 */
984 *(char*)_aImportTab[i].ulAddress = 0xE9; /* jmp */
985 *(unsigned long*)(_aImportTab[i].ulAddress + 1) = auFuncs[i] - (_aImportTab[i].ulAddress + 5);
986 }
987 else
988 { /* !fatal! - this could never happen really... */
989 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
990 Int3(); /* ipe - later! */
991 return 1;
992 }
993 break;
994 }
995
996
997 /*
998 * 16-bit procedure overload.
999 * Currently disabled due to expected problems when calltab is a 32-bit segment.
1000 */
1001 case EPT_PROC16:
1002 {
1003 kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
1004 Int3();
1005
1006 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, TRUE);
1007 _aImportTab[i].cbProlog = (char)cb;
1008 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) */
1009 { /* 7: size of a 16:32 jump which is added to the call tab */
1010 /*
1011 * Copy function prolog which is to be overwritten.
1012 */
1013 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
1014
1015 /*
1016 * Create far jump from calltab to original function.
1017 * 0xEA <four byte target address> <two byte target selector>
1018 */
1019 callTab[i][cb] = 0xEA; /* jmp far ptr */
1020 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].offObject;
1021 *(unsigned short*)(void*)&callTab[i][cb+5] = _aImportTab[i].usSel;
1022
1023 /*
1024 * jump from original function to my function - an cli(?) could be needed here
1025 * 0x66 0xEA <four byte target address> <two byte target selector>
1026 */
1027 *(char*)(_aImportTab[i].ulAddress ) = 0x66; /* operandsize prefix */
1028 *(char*)(_aImportTab[i].ulAddress + 1) = 0xEA; /* jmp far ptr */
1029 *(unsigned long*)(_aImportTab[i].ulAddress + 2) = auFuncs[i]; /* FIXME? */
1030 *(unsigned short*)(_aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
1031 }
1032 else
1033 { /* !fatal! - this could never happen really... */
1034 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
1035 Int3(); /* ipe - later! */
1036 return 1;
1037 }
1038 break;
1039 }
1040
1041
1042 /*
1043 * 32-bit imported procedure
1044 * This is called by issuing a near call to the callTab entry.
1045 */
1046 case EPT_PROCIMPORT32:
1047 {
1048 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, FALSE);
1049 _aImportTab[i].cbProlog = (char)cb;
1050 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1051 {
1052 /*
1053 * Make jump instruction which jumps from calltab to original function.
1054 * 0xE9 <four bytes displacement>
1055 * Note: the displacement is relative to the next instruction
1056 */
1057 callTab[i][0] = 0xE9; /* jmp */
1058 *(unsigned*)(void*)&callTab[i][1] = _aImportTab[i].ulAddress - (unsigned)&callTab[i][5];
1059 }
1060 else
1061 { /* !fatal! - this should never really happen... */
1062 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
1063 Int3(); /* ipe - later! */
1064 return 1;
1065 }
1066 break;
1067 }
1068
1069
1070 /*
1071 * 16-bit imported procedure.
1072 * This is called by issuing a far call to the calltab entry.
1073 */
1074 case EPT_PROCIMPORT16:
1075 {
1076 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, FALSE);
1077 _aImportTab[i].cbProlog = (char)cb;
1078 if (cb > 0) /* Since no prolog part is copied to the function table, it's ok as long as the prolog has been recognzied. */
1079 {
1080 /*
1081 * Create far jump from calltab to original function.
1082 * 0xEA <four byte target address> <two byte target selector>
1083 */
1084 callTab[i][0] = 0xEA; /* jmp far ptr */
1085 *(unsigned long*)(void*)&callTab[i][1] = _aImportTab[i].offObject;
1086 *(unsigned short*)(void*)&callTab[i][5] = _aImportTab[i].usSel;
1087 }
1088 else
1089 { /* !fatal! - this should never really happen... */
1090 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
1091 Int3(); /* ipe - later! */
1092 return 1;
1093 }
1094 break;
1095 }
1096
1097
1098 /*
1099 * 16/32-bit importe variable.
1100 * This is used by accessing the 32-bit flat address in the callTab.
1101 * callTab-entry + 4 holds the offset of the variable into the object.
1102 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
1103 * callTab-entry + a holds the 16-bit offset for the variable.
1104 * callTab-entry + c holds the selector for the object. (These two fiels is the 16:16-bit pointer to the variable.)
1105 */
1106 case EPT_VARIMPORT32:
1107 case EPT_VARIMPORT16:
1108 _aImportTab[i].cbProlog = (char)0;
1109 *(unsigned long*)(void*)&callTab[i][0] = _aImportTab[i].ulAddress;
1110 *(unsigned long*)(void*)&callTab[i][4] = _aImportTab[i].offObject;
1111 *(unsigned short*)(void*)&callTab[i][8] = _aImportTab[i].usSel;
1112 *(unsigned short*)(void*)&callTab[i][0xa] = (unsigned short)_aImportTab[i].offObject;
1113 *(unsigned short*)(void*)&callTab[i][0xc] = _aImportTab[i].usSel;
1114 break;
1115
1116 default:
1117 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
1118 Int3(); /* ipe - later! */
1119 return 1;
1120 } /* switch - type */
1121 } /* for */
1122
1123 return NO_ERROR;
1124}
1125#endif /* !DEBUGR3 */
1126
1127
1128
1129
1130/*******************************************************************************
1131* Ring-3 Debug Stuff
1132*******************************************************************************/
1133#ifdef DEBUGR3
1134#include <stdio.h>
1135
1136void main(void)
1137{
1138 char ach_ldrRead[] = {
1139 0x55, 0x8b, 0xec, 0x8d, 0x65, 0xf8, 0x53, 0x56,
1140 0x57, 0x33, 0xd2, 0x42, 0x89, 0x55, 0xf8, 0x38,
1141 0x35, 0xce, 0x70, 0x00, 0x00, 0x75, 0x4d, 0x8b,
1142 0x55, 0x08, 0x66, 0x83, 0xfa, 0xff, 0x74, 0x62
1143 };
1144 char ach_ldrOpen[] = {
1145 0x55, 0x8b, 0xec, 0x33, 0xc0, 0x38, 0x05, 0xce,
1146 0x70, 0x00, 0x00, 0x75, 0x4b, 0x50, 0xff, 0x75,
1147 0x08, 0x6a, 0x01, 0x68, 0xa3, 0x00, 0x00, 0x00,
1148 0xff, 0x75, 0x0c, 0xff, 0x15, 0xc4, 0xc1, 0x0d
1149 };
1150 char ach_ldrClose[] = {
1151 0x55, 0x8b, 0xec, 0x33, 0xc0, 0x38, 0x05, 0xce,
1152 0x70, 0x00, 0x00, 0x75, 0x13, 0x8b, 0x55, 0x08,
1153 0x0f, 0xb7, 0xd2, 0x66, 0x83, 0xfa, 0xff, 0x74,
1154 0x07, 0x52, 0xff, 0x15, 0xcc, 0xc1, 0x0d, 0x00
1155 };
1156 char ach_LDRQAppType[] = {
1157 0x55, 0x8b, 0x0d, 0xa0, 0x0a, 0x00, 0x00, 0x8b,
1158 0xec, 0x83, 0xec, 0x3c, 0x53, 0x81, 0xc1, 0x24,
1159 0x06, 0x00, 0x00, 0x57, 0x56, 0x6a, 0xff, 0x66,
1160 0xc7, 0x45, 0xc6, 0x00, 0x00, 0x51, 0xe8, 0x38
1161 };
1162 char ach_ldrEnum32bitRelRecs[] = {
1163 0x55, 0xa1, 0xe8, 0xcf, 0x0d, 0x00, 0x8b, 0xec,
1164 0x83, 0xec, 0x5c, 0x53, 0x8b, 0x55, 0x08, 0x57,
1165 0x56, 0x8b, 0x52, 0x04, 0xf6, 0x40, 0x04, 0x80,
1166 0x89, 0x55, 0xfc, 0x0f, 0x84, 0x10, 0x01, 0x00
1167 };
1168 char ach_IOSftOpen[] = {
1169 0x55, 0x8b, 0xec, 0x8d, 0xa5, 0xa0, 0xfe, 0xff,
1170 0xff, 0xf6, 0x05, 0x95, 0x2d, 0x00, 0x00, 0x80,
1171 0x74, 0x13, 0x66, 0x68, 0x50, 0x30, 0xff, 0x75,
1172 0x08, 0x6a, 0x3c, 0x6a, 0x06, 0xe8, 0x5a, 0x03
1173 };
1174 char ach_IOSftClose[] = {
1175 0x55, 0x8b, 0xec, 0x8d, 0xa5, 0x28, 0xff, 0xff,
1176 0xff, 0xf6, 0x05, 0x95, 0x2d, 0x00, 0x00, 0x80,
1177 0x74, 0x16, 0x50, 0x66, 0x68, 0x51, 0x30, 0x8b,
1178 0x45, 0x08, 0x50, 0x6a, 0x0c, 0x6a, 0x06, 0xe8
1179 };
1180 char ach_IOSftTransPath[] = {
1181 0x55, 0x8b, 0xec, 0x8d, 0xa5, 0xd8, 0xfd, 0xff,
1182 0xff, 0x53, 0x56, 0x57, 0x1e, 0x06, 0xa1, 0xa4,
1183 0x0a, 0x00, 0x00, 0x66, 0x8d, 0x9d, 0xe2, 0xfe,
1184 0xff, 0xff, 0x66, 0x89, 0x98, 0xf6, 0x01, 0x00
1185 };
1186 char ach_IOSftReadAt[] = {
1187 0xb8, 0xc4, 0x68, 0x14, 0x00, 0xeb, 0x05, 0xb8,
1188 0xcc, 0x68, 0x14, 0x00, 0x55, 0x8b, 0xec, 0x8d,
1189 0xa5, 0x20, 0xff, 0xff, 0xff, 0xf6, 0x05, 0x95,
1190 0x2d, 0x00, 0x00, 0x80, 0x74, 0x28, 0x50, 0x66
1191 };
1192 char ach_IOSftWriteAt[] = {
1193 0xb8, 0xcc, 0x68, 0x14, 0x00, 0x55, 0x8b, 0xec,
1194 0x8d, 0xa5, 0x20, 0xff, 0xff, 0xff, 0xf6, 0x05,
1195 0x95, 0x2d, 0x00, 0x00, 0x80, 0x74, 0x28, 0x50,
1196 0x66, 0x68, 0x52, 0x30, 0x8b, 0x45, 0x08, 0x25
1197 };
1198 char ach_SftFileSize[] = {
1199 0x55, 0x8b, 0xec, 0x8d, 0xa5, 0x28, 0xff, 0xff,
1200 0xff, 0x57, 0x56, 0x53, 0xc6, 0x85, 0x2b, 0xff,
1201 0xff, 0xff, 0x00, 0x8b, 0x35, 0xa4, 0x0a, 0x00,
1202 0x00, 0xf6, 0x46, 0x04, 0x01, 0x74, 0x0a, 0x80
1203 };
1204 char ach_VMAllocMem[] = {
1205 0xa1, 0xe8, 0xcf, 0x0d, 0x00, 0x55, 0x8b, 0xec,
1206 0x83, 0xec, 0x44, 0x53, 0x57, 0xf6, 0x40, 0x04,
1207 0x80, 0x56, 0x0f, 0x84, 0x34, 0x01, 0x00, 0x00,
1208 0xf6, 0x00, 0x40, 0x74, 0x44, 0xa1, 0xcc, 0x02
1209 };
1210 char ach_VMGetOwner[] = {
1211 0x55, 0x8b, 0xec, 0x83, 0xec, 0x30, 0x57, 0x66,
1212 0x8b, 0x4d, 0x08, 0x66, 0x89, 0x4d, 0xd8, 0xf6,
1213 0xc1, 0x04, 0x75, 0x39, 0x80, 0x3d, 0x40, 0x8c,
1214 0x00, 0x00, 0x00, 0x74, 0x07, 0xa1, 0xac, 0x0a
1215 };
1216 char achg_tkExecPgm[] = {
1217 0x55, 0x8b, 0xec, 0x8d, 0x65, 0xa4, 0x66, 0x89,
1218 0x5d, 0xf4, 0x66, 0x8c, 0x45, 0xf6, 0x66, 0x89,
1219 0x55, 0xfc, 0x66, 0x8c, 0x5d, 0xfe, 0x66, 0x89,
1220 0x75, 0xf0, 0x66, 0x89, 0x7d, 0xf2, 0xc7, 0x45
1221 };
1222 char achf_FuStrLenZ[] = {
1223 0x6a, 0x02, 0x52, 0x66, 0x55, 0x0f, 0xa8, 0x68,
1224 0x0c, 0x00, 0x0f, 0xa9, 0x65, 0x67, 0x66, 0x8b,
1225 0x2d, 0xa8, 0x0a, 0x00, 0x00, 0x65, 0x67, 0xff,
1226 0xb5, 0xb4, 0x1f, 0x00, 0x00, 0x65, 0x67, 0x66
1227 };
1228 char achf_FuStrLen[] = {
1229 0x6a, 0x02, 0x52, 0x66, 0x55, 0x0f, 0xa8, 0x68,
1230 0x0c, 0x00, 0x0f, 0xa9, 0x65, 0x67, 0x66, 0x8b,
1231 0x2d, 0xa8, 0x0a, 0x00, 0x00, 0x65, 0x67, 0xff,
1232 0xb5, 0xb4, 0x1f, 0x00, 0x00, 0x65, 0x67, 0x66
1233 };
1234 char achf_FuBuff[] = {
1235 0x6a, 0x02, 0x52, 0x66, 0x55, 0x0f, 0xa8, 0x68,
1236 0x0c, 0x00, 0x0f, 0xa9, 0x65, 0x67, 0x66, 0x8b,
1237 0x2d, 0xa8, 0x0a, 0x00, 0x00, 0x65, 0x67, 0xff,
1238 0xb5, 0xb4, 0x1f, 0x00, 0x00, 0x65, 0x67, 0x66
1239 };
1240
1241
1242 char *aProcs[] =
1243 {
1244 ach_ldrRead ,
1245 ach_ldrOpen ,
1246 ach_ldrClose ,
1247 ach_LDRQAppType ,
1248 ach_ldrEnum32bitRelRecs,
1249 ach_IOSftOpen ,
1250 ach_IOSftClose ,
1251 ach_IOSftTransPath ,
1252 ach_IOSftReadAt ,
1253 ach_IOSftWriteAt ,
1254 ach_SftFileSize ,
1255 ach_VMAllocMem ,
1256 ach_VMGetOwner ,
1257 achg_tkExecPgm ,
1258 achf_FuStrLenZ ,
1259 achf_FuStrLen ,
1260 achf_FuBuff ,
1261 NULL
1262 };
1263 int i;
1264
1265 /* loop thru procs */
1266 for (i = 0; aProcs[i] != NULL; i++)
1267 {
1268 unsigned cb;
1269 printf("Proc.no.%i\n", i);
1270 if (i < 14 )
1271 cb = interpretFunctionProlog32(aProcs[i], i < 5 || i == 13);
1272 else
1273 cb = interpretFunctionProlog16(aProcs[i], FALSE);
1274 printf(" cb=%d\n\n", cb);
1275 }
1276}
1277#endif
Note: See TracBrowser for help on using the repository browser.