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

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

16-bit imports and import of global variables.
(But there are some problems left)

File size: 29.0 KB
Line 
1/* $Id: d32init.c,v 1.12 2000-02-20 04:27:23 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 0x10 /* 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 "probkrnl.h"
35#include "log.h"
36#include "asmutils.h"
37#include "malloc.h"
38#include "ldr.h"
39#include "ldrCalls.h"
40
41
42/*******************************************************************************
43* Internal Functions *
44*******************************************************************************/
45static ULONG readnum(const char *pszNum);
46static signed char interpretFunctionProlog32(char *pach, BOOL fOverload);
47static signed char interpretFunctionProlog16(char *pach, BOOL fOverload);
48static int ImportTabInit(void);
49
50
51/* externs located in 16-bit data segement in ProbKrnl.c */
52extern ULONG _TKSSBase16;
53extern USHORT _R0FlatCS16;
54extern USHORT _R0FlatDS16;
55
56/* extern(s) located in calltab.asm */
57extern char callTab[NBR_OF_KRNLIMPORTS][MAXSIZE_PROLOG];
58
59/* extern(s) located in mytkExecPgm.asm */
60extern char mytkExecPgm;
61
62
63
64/**
65 * Ring-0, 32-bit, init function.
66 * @returns Status word.
67 * @param pRpInit Pointer init request packet.
68 * @sketch Set TKSSBase32.
69 * Set default parameters.
70 * Parse command line options.
71 * Show (kprint) configuration.
72 * Init heap.
73 * Init ldr.
74 * Init procs. (overloaded ldr procedures)
75 * @status completely implemented.
76 * @author knut st. osmundsen
77 */
78USHORT _loadds _Far32 _Pascal R0Init32(RP32INIT *pRpInit)
79{
80 char *pszTmp2;
81 char *pszTmp;
82 ULONG ul;
83
84 pulTKSSBase32 = (PULONG)_TKSSBase16;
85
86 SET_OPTIONS_TO_DEFAULT(options);
87
88 /*---------------------*/
89 /* commandline options */
90 /*---------------------*/
91 kprintf(("Options start\n"));
92 pszTmp = strpbrk(pRpInit->InitArgs, "-/");
93 while (pszTmp != NULL)
94 {
95 int cch;
96 pszTmp++; //skip [-/]
97 cch = strlen(pszTmp);
98 switch (*pszTmp)
99 {
100 case 'c':
101 case 'C': /* -C[1|2] - com-port no, def:-C2 */
102 switch (pszTmp[1])
103 {
104 case '1':
105 options.usCom = OUTPUT_COM1;
106 break;
107
108 case '2':
109 default:
110 options.usCom = OUTPUT_COM2;
111 }
112 break;
113
114 case 'e':
115 case 'E':/* ELF */
116 pszTmp2 = strpbrk(pszTmp, ":=/- ");
117 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
118 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
119 )
120 options.fElf = FALSE;
121 else
122 options.fElf = TRUE;
123 break;
124
125 case 'h':
126 case 'H': /* Heap options */
127 pszTmp2 = strpbrk(pszTmp, ":=/- ");
128 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
129 && (*pszTmp2 == ':' || *pszTmp2 == '='))
130 {
131 ul = readnum(pszTmp2 + 1);
132 if (ul > 0x1000UL && ul < 0x2000000UL) /* 4KB < ul < 32MB */
133 {
134 if (strnicmp(pszTmp, "heapm", 5) == 0)
135 options.cbSwpHeapMax = ul;
136 else
137 options.cbSwpHeapInit = ul;
138 }
139 }
140 break;
141
142 case 'l':
143 case 'L': /* -L[..]<:|=| >[<Y..|E..| > | <N..|D..>] */
144 pszTmp2 = strpbrk(pszTmp, ":=/- ");
145 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
146 && (pszTmp2[1] == 'N' ||pszTmp2[1] == 'n' || pszTmp2[1] == 'D' || pszTmp2[1] == 'd')
147 )
148 options.fLogging = FALSE;
149 else
150 options.fLogging = TRUE;
151 break;
152
153 case 'n':
154 case 'N': /* NoLoader */
155 options.fNoLoader = TRUE;
156 break;
157
158 case 'p':
159 case 'P': /* PE */
160 pszTmp2 = strpbrk(pszTmp, ":=/- ");
161 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
162 && (*pszTmp2 == ':' || *pszTmp2 == '='))
163 {
164 pszTmp++;
165 if (strnicmp(pszTmp, "pe2lx", 5) == 0)
166 options.fPE = FLAGS_PE_PE2LX;
167 else if (strnicmp(pszTmp, "pe", 2) == 0)
168 options.fPE = FLAGS_PE_PE;
169 else if (strnicmp(pszTmp, "mixed", 2) == 0)
170 options.fPE = FLAGS_PE_MIXED;
171 else if (strnicmp(pszTmp, "not", 2) == 0)
172 options.fPE = FLAGS_PE_NOT;
173 else
174 kprintf(("R0Init32: invalid parameter -PE:...\n"));
175 }
176 else
177 kprintf(("R0Init32: invalid parameter -PE...\n"));
178 break;
179
180 case 'q':
181 case 'Q': /* quiet initialization */
182 options.fQuiet = TRUE;
183 break;
184
185 case 'r':
186 case 'R': /* ResHeap options */
187 pszTmp2 = strpbrk(pszTmp, ":=/- ");
188 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
189 && (*pszTmp2 == ':' || *pszTmp2 == '='))
190 {
191 ul = readnum(pszTmp2 + 1);
192 if (ul > 0x1000UL && ul < 0x700000UL) /* 4KB < ul < 7MB */
193 {
194 if (strnicmp(pszTmp, "resheapm", 8) == 0)
195 options.cbResHeapMax = ul;
196 else
197 options.cbResHeapInit = ul;
198 }
199 }
200 break;
201
202 case 's':
203 case 'S': /* Sym:<filename> or Script:<Yes|No> or Smp */
204 /* SMP kernel */
205 if (pszTmp[1] == 'm' || pszTmp[1] == 'M')
206 options.fKernel = KF_SMP;
207 else
208 {
209 if (pszTmp[1] == 'c' || pszTmp[1] == 'C')
210 {
211 pszTmp2 = strpbrk(pszTmp, ":=/- ");
212 options.fScript = pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
213 && (*pszTmp2 == ':' || *pszTmp2 == '=')
214 && (pszTmp2[1] == 'Y' || pszTmp2[1] == 'y');
215 }
216 }
217 break;
218
219 case 'u':
220 case 'U': /* UNI kernel */
221 options.fKernel = KF_UNI;
222 break;
223
224 case 'v':
225 case 'V': /* verbose initialization */
226 options.fQuiet = FALSE;
227 break;
228
229 case 'w':
230 case 'W':
231 if (pszTmp[1] >= '0' && pszTmp[1] <= '4')
232 options.ulInfoLevel = pszTmp[1] - '0';
233 else
234 {
235 pszTmp2 = strpbrk(pszTmp, ":=/- ");
236 if (pszTmp2 != NULL && (int)(pszTmp2-pszTmp) < cch-1
237 && (*pszTmp2 == ':' || *pszTmp2 == '=')
238 && pszTmp2[1] >= '0' && pszTmp2[1] <= '4'
239 )
240 options.ulInfoLevel = pszTmp2[1] - '0';
241 }
242 break;
243
244 }
245 pszTmp = strpbrk(pszTmp, "-/");
246 }
247
248 /* heap min/max corrections */
249 if (options.cbSwpHeapInit > options.cbSwpHeapMax)
250 options.cbSwpHeapMax = options.cbSwpHeapInit;
251 if (options.cbResHeapInit > options.cbResHeapMax)
252 options.cbResHeapMax = options.cbResHeapInit;
253
254 /* Transfer version and build number from 16-bit probkrnl.c */
255 options.ulBuild = _ulBuild;
256 options.usVerMajor = _usVerMajor;
257 options.usVerMinor = _usVerMinor;
258
259 /* log option summary - FIXME */
260 kprintf(("Options - Summary\n"));
261 kprintf(("\tKernel: ver%d.%d build %d type %s\n",
262 options.usVerMajor,
263 options.usVerMinor,
264 options.ulBuild,
265 (options.fKernel & KF_SMP) ? "SMP" : "UNI"
266 ));
267 kprintf(("\tCom port no.%d\n", options.usCom));
268 if (options.fQuiet)
269 kprintf(("\tQuiet init\n"));
270 else
271 kprintf(("\tVerbose init\n"));
272 if (options.fLogging)
273 kprintf(("\tlogging enabled\n"));
274 else
275 kprintf(("\tlogging disabled\n"));
276 /* end option summary */
277
278
279 /*
280 * init sub-parts
281 */
282 /* heap */
283 if (heapInit(options.cbResHeapInit, options.cbResHeapMax,
284 options.cbSwpHeapInit, options.cbSwpHeapMax) != NO_ERROR)
285 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
286
287 /* loader */
288 if (!options.fNoLoader)
289 if (ldrInit() != NO_ERROR)
290 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
291
292 /* functionoverrides */
293 if (!options.fNoLoader)
294 if (ImportTabInit() != NO_ERROR)
295 return STATUS_DONE | STERR | ERROR_I24_QUIET_INIT_FAIL;
296
297 return STATUS_DONE;
298}
299
300
301/**
302 * Reads a number (unsigned long integer) for a string.
303 * @returns number read, ~0UL on error / no number read.
304 * @param pszNum Pointer to the string containing the number.
305 * @status competely implemented.
306 * @author knut st. osmundsen
307 */
308static ULONG readnum(const char *pszNum)
309{
310 ULONG ulRet = 0;
311 ULONG ulBase = 10;
312 int i = 0;
313
314 if (*pszNum == '0')
315 if (pszNum[1] == 'x' || pszNum[1] == 'X')
316 {
317 ulBase = 16;
318 pszNum += 2;
319 }
320 else
321 {
322 ulBase = 8;
323 i = 1;
324 }
325
326 /* read digits */
327 while (ulBase == 16 ? (pszNum[i] >= '0' && pszNum[i] <= '9') || (pszNum[i] >= 'a' && pszNum[i] <= 'f') || (pszNum[i] >= 'A' && pszNum[i] <= 'F')
328 : (pszNum[i] >= '0' && pszNum[i] <= (ulBase == 10 ? '9' : '7'))
329 )
330 {
331 ulRet *= ulBase;
332 if (ulBase <= 10)
333 ulRet += pszNum[i] - '0';
334 else
335 ulRet += pszNum[i] - (pszNum[i] >= 'A' ? 'A' - 10 : (pszNum[i] >= 'a' ? 'a' + 9 : '0'));
336
337 i++;
338 }
339
340 return i > 0 ? ulRet : ~0UL;
341}
342
343
344/**
345 * Get kernel OTEs
346 * @returns Strategy return code:
347 * STATUS_DONE on success.
348 * STATUS_DONE | STERR | errorcode on failure.
349 * @param pOTEBuf Pointer to output buffer.
350 * @status completely implemented and tested.
351 * @author knut st. osmundsen
352 * @remark Called from IOCtl.
353 */
354USHORT _loadds _Far32 _Pascal GetOTEs32(PKRNLOBJTABLE pOTEBuf)
355{
356 PMTE pMTE;
357 PSMTE pSMTE;
358 POTE pOTE;
359 int i;
360 USHORT usRc;
361
362 pMTE = GetOS2KrnlMTE();
363 if (pMTE != NULL)
364 {
365 pSMTE = pMTE->mte_swapmte;
366 if (pSMTE != NULL)
367 {
368 pOTEBuf->cObjects = (unsigned char)pSMTE->smte_objcnt;
369 if (pSMTE->smte_objcnt <= MAXKRNLOBJECTS)
370 {
371 pOTE = pSMTE->smte_objtab;
372 if (pOTE != NULL)
373 {
374 for (i = 0; i < pOTEBuf->cObjects; i++)
375 memcpy((void*)&pOTEBuf->aObjects[i], &pOTE[i], sizeof(OTE));
376 usRc = 0;
377 }
378 else
379 usRc = 4;
380 }
381 else
382 usRc = 3;
383 }
384 else
385 usRc = 2;
386 }
387 else
388 usRc = 1;
389
390 if (usRc != 0)
391 kprintf(("GetOTEs32: failed. usRc = %d\n", usRc));
392
393 return (USHORT)(usRc | (usRc != NO_ERROR ? STATUS_DONE | STERR : STATUS_DONE));
394}
395
396
397/**
398 * 32-bit! Interpret function prolog to find where to jmp back.
399 * @returns Length of prolog need to be copied - which is also the offset of
400 * where the jmp instr should be placed.
401 * On error it returns 0.
402 * @param pach Pointer to prolog.
403 * @param fOverload TRUE: Function is to be overloaded.
404 * FALSE: Function is to be imported.
405 */
406static signed char interpretFunctionProlog32(char *pach, BOOL fOverload)
407{
408 int cb;
409
410 /*
411 * check for the well known prolog (the only that is supported now)
412 * which is:
413 * push ebp
414 * mov ebp,esp
415 * or
416 * push ebp
417 * mov ecx, dword ptr [xxxxxxxx]
418 */
419
420 if (pach[0] == 0x55 && pach[1] == 0x8b)
421 {
422 if (pach[2] == 0xec)
423 cb = 3;
424 else
425 cb = 1;
426 while (cb < 5)
427 {
428 /*
429 * This is not at all very stable or correct - but it works
430 * for the current functions.
431 * There will never be any doubt when something goes wrong!
432 */
433 switch(pach[cb])
434 {
435 case 0x33: /* xor (ldrClose, ldrOpen) */
436 cb +=2;
437 break;
438 case 0x8b:
439 if (pach[cb+1] == 0x0d)
440 cb += 6;
441 else
442 cb += 2; /*????!*/
443 break;
444 case 0x8d: /* lea (ldrRead) */
445 cb += 3;
446 break;
447 case 0x83: /* sub (LDRQAppType) */
448 cb += 3;
449 break;
450 default:
451 kprintf(("interpretFunctionProlog: unknown instruction 0x%x\n", pach[cb]));
452 return 0;
453 }
454 }
455 }
456 else if (pach[0] == 0x55 && pach[1] == 0xa1) /* ldrEnum32bitRelRecs on WS4eB */
457 {
458 cb = 1 + 5;
459 }
460 else
461 {
462 /* special case for IOSftReadAt and IOSftWriteAt */
463 if (fOverload == FALSE && pach[0] == 0xB8 && (pach[5] == 0xEB || pach[5] == 0x55))
464 cb = 5;
465 else
466 cb = 0;
467 }
468
469 return (signed char)cb;
470}
471
472
473/**
474 * 16-bit! Interpret function prolog to find where to jmp back.
475 * @returns Length of prolog need to be copied - which is also the offset of
476 * where the jmp instr should be placed.
477 * On error it returns 0.
478 * @param pach Pointer to prolog.
479 * @param fOverload TRUE: Function is to be overloaded.
480 * FALSE: Function is to be imported.
481 */
482static signed char interpretFunctionProlog16(char *pach, BOOL fOverload)
483{
484 int cb;
485
486 /*
487 * Check for the well known prolog (the only that is supported now)
488 * which is:
489 * push 2
490 */
491 if (*pach == 0x6A) /* push 2 (don't check for the 2) */
492 {
493 BOOL fForce;
494 cb = 0;
495 while (cb < 8 || fForce)
496 {
497 fForce = FALSE;
498 switch (*pach)
499 {
500 case 0x50: /* push ax */
501 case 0x51: /* push cx */
502 case 0x52: /* push dx */
503 case 0x53: /* push bx */
504 case 0x54: /* push sp */
505 case 0x55: /* push bp */
506 case 0x56: /* push si */
507 case 0x57: /* push di */
508 break;
509
510 case 0x2e: /* cs segment override */
511 case 0x36: /* ss segment override */
512 case 0x3e: /* ds segment override */
513 case 0x26: /* es segment override */
514 case 0x64: /* fs segment override */
515 case 0x65: /* gs segment override */
516 fForce = TRUE;
517 break;
518
519 case 0x6a: /* push <byte> */
520 pach++;
521 cb++;
522 break;
523
524 case 0x68: /* push <word> */
525 pach += 2;
526 cb += 2;
527 break;
528
529 case 0x8b: /* mov /r */
530 if ((pach[1] & 0xc0) == 10 /* ex. mov ax,bp+1114h */
531 || ((pach[1] & 0xc0) == 0 && (pach[1] & 0xc0) == 6)) /* ex. mov bp,0ff23h */
532 { /* 16-bit displacement */
533 pach += 3;
534 cb += 3;
535 }
536 else
537 if ((pach[1] & 0xc0) == 0x40) /* ex. mov ax,[si]+4fh */
538 { /* 8-bit displacement */
539 pach += 2;
540 cb += 2;
541 }
542 else
543 { /* no displacement (only /r byte) */
544 pach++;
545 cb++;
546 }
547 break;
548
549 default:
550 kprintf(("interpretFunctionProlog: unknown instruction 0x%x 0x%x 0x%x\n", pach[0], pach[1], pach[2]));
551 return 0;
552 }
553 pach++;
554 cb++;
555 }
556 }
557
558 fOverload = fOverload;
559 return (signed char)cb;
560}
561
562
563/**
564 * Verifies the aImportTab.
565 * @returns 0 if ok. !0 if not ok.
566 * @remark Called from IOCtl.
567 * WARNING! VerifyImporTab32 is called before the initroutine!
568 */
569USHORT _loadds _Far32 _Pascal VerifyImportTab32(void)
570{
571 int i;
572 int cb;
573 int cbmin;
574
575 /* VerifyImporTab32 is called before the initroutine! */
576 pulTKSSBase32 = (PULONG)_TKSSBase16;
577
578 /* verify */
579 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
580 {
581 /* verify that it is found */
582 if (!_aImportTab[i].fFound)
583 {
584 kprintf(("VerifyImportTab32: procedure no.%d was not found!\n", i));
585 return STATUS_DONE | STERR | 1;
586 }
587
588 /* verify read/writeable. - FIXME */
589 if (_aImportTab[i].ulAddress < 0xffe00000UL)
590 {
591 kprintf(("VerifyImportTab32: procedure no.%d has an invlalid address, %#08x!\n",
592 i, _aImportTab[i].ulAddress));
593 return STATUS_DONE | STERR | 2;
594 }
595
596 switch (_aImportTab[i].fType & ~EPT_BIT_MASK)
597 {
598 case EPT_PROC:
599 case EPT_PROCIMPORT:
600 /*
601 * Verify known function prolog.
602 */
603 if (_aImportTab[i].fType & EPT_32BIT)
604 {
605 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
606 cbmin = 5;
607 }
608 else
609 {
610 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
611 cbmin = 8;
612 }
613
614 /*
615 * Check result of the function prolog interpretations.
616 */
617 if (cb <= 0 && cb + cbmin >= MAXSIZE_PROLOG)
618 { /* failed, too small or too large. */
619 kprintf(("VerifyImportTab32: verify failed for procedure no.%d (cd=%d)\n", i, cb));
620 return STATUS_DONE | STERR | 3;
621 }
622 break;
623
624 case EPT_VARIMPORT:
625 /* do nothing! */
626 break;
627
628 default:
629 kprintf(("VerifyImportTab32: only EPT_PROC is implemented\n",i));
630 return STATUS_DONE | STERR | 4;
631 }
632 }
633
634 return STATUS_DONE;
635}
636
637
638/**
639 * Initiates the overrided functions.
640 * @returns NO_ERROR on success. !0 on error.
641 */
642static int importTabInit(void)
643{
644 /* This table must be updated with the overloading functions. */
645 static unsigned auFuncs[NBR_OF_KRNLIMPORTS] =
646 {
647 (unsigned)myldrRead,
648 (unsigned)myldrOpen,
649 (unsigned)myldrClose,
650 0,//(unsigned)myLDRQAppType,
651 (unsigned)myldrEnum32bitRelRecs,
652 0,
653 0,
654 0,
655 0,
656 0,
657 0,
658 0,
659 0,
660 (unsigned)&mytkExecPgm,
661 0,
662 0
663 };
664
665 int i;
666 int cb;
667
668
669 /*
670 * verify proctable
671 */
672 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
673 {
674 /* EPT_VARIMPORTs are skipped */
675 if ((_aImportTab[i].fType & ~EPT_BIT_MASK) == EPT_VARIMPORT)
676 continue;
677
678 if (_aImportTab[i].fType & EPT_32BIT)
679 cb = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC32);
680 else
681 cb = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, _aImportTab[i].fType == EPT_PROC16);
682 if (cb <= 0 || cb + 5 >= MAXSIZE_PROLOG)
683 {
684 kprintf(("ImportTabInit: verify failed for procedure no.%d, cb=%d\n", i, cb));
685 return 1;
686 }
687 }
688
689 /*
690 * rehook / import
691 */
692 for (i = 0; i < NBR_OF_KRNLIMPORTS; i++)
693 {
694 switch (_aImportTab[i].fType)
695 {
696 /*
697 * 32-bit procedure overload.
698 * The overloading procedure is found in the auFuncs table (at the same index
699 * as the overloaded procedure has in aImportTab).
700 * The overloaded procedure is called by issuing a call to the callTab entry.
701 */
702 case EPT_PROC32:
703 {
704 cb = _aImportTab[i].cbProlog = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, TRUE);
705 if (cb > 0 && cb + 5 < MAXSIZE_PROLOG)
706 {
707 /*
708 * Copy function prolog which will be overwritten by the jmp to calltabl.
709 */
710 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
711
712 /*
713 * Make jump instruction which jumps from calltab to original function.
714 * 0xE9 <four bytes displacement>
715 * Note: the displacement is relative to the next instruction
716 */
717 callTab[i][cb] = 0xE9; /* jmp */
718 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].ulAddress + cb - (unsigned long)&callTab[i][cb+5];
719
720 /*
721 * Jump from original function to my function - an cli(?) could be needed here
722 */
723 *(char*)_aImportTab[i].ulAddress = 0xE9; /* jmp */
724 *(unsigned long*)(_aImportTab[i].ulAddress + 1) = auFuncs[i] - (_aImportTab[i].ulAddress + 5);
725 }
726 else
727 { /* !fatal! - this could never happen really... */
728 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
729 Int3(); /* ipe - later! */
730 return 1;
731 }
732 break;
733 }
734
735
736 /*
737 * 16-bit procedure overload.
738 * Currently disabled due to expected problems when calltab is a 32-bit segment.
739 */
740 case EPT_PROC16:
741 {
742 kprintf(("ImportTabInit: Overloading 16-bit procedures are not supported yet!!! Calltable in 32-bit segment!\n", i));
743 Int3();
744
745 cb = _aImportTab[i].cbProlog = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, TRUE);
746 if (cb > 0 && cb + 8 < MAXSIZE_PROLOG) /* a 16:32 jump must be prefixed with 66h in a 16-bit segment */
747 {
748 /*
749 * Copy function prolog which is to be overwritten.
750 */
751 memcpy(callTab[i], (void*)_aImportTab[i].ulAddress, (size_t)cb);
752
753 /*
754 * Create far jump from calltab to original function.
755 * 0xEA <four byte target address> <two byte target selector>
756 */
757 callTab[i][cb] = 0xEA; /* jmp far ptr */
758 *(unsigned long*)(void*)&callTab[i][cb+1] = _aImportTab[i].offObject;
759 *(unsigned short*)(void*)&callTab[i][cb+5] = _aImportTab[i].usSel;
760
761 /*
762 * jump from original function to my function - an cli(?) could be needed here
763 * 0x66 0xEA <four byte target address> <two byte target selector>
764 */
765 *(char*)(_aImportTab[i].ulAddress ) = 0x66; /* operandsize prefix */
766 *(char*)(_aImportTab[i].ulAddress + 1) = 0xEA; /* jmp far ptr */
767 *(unsigned long*)(_aImportTab[i].ulAddress + 2) = auFuncs[i]; /* FIXME? */
768 *(unsigned short*)(_aImportTab[i].ulAddress + 6) = _R0FlatCS16; /* FIXME */
769 }
770 else
771 { /* !fatal! - this could never happen really... */
772 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when rehooking it!\n",i));
773 Int3(); /* ipe - later! */
774 return 1;
775 }
776 break;
777 }
778
779
780 /*
781 * 32-bit imported procedure
782 * This is called by issuing a near call to the callTab entry.
783 */
784 case EPT_PROCIMPORT32:
785 {
786 cb = _aImportTab[i].cbProlog = interpretFunctionProlog32((char*)_aImportTab[i].ulAddress, FALSE);
787 if (cb > 0 && cb + 5 < MAXSIZE_PROLOG)
788 {
789 /*
790 * Make jump instruction which jumps from calltab to original function.
791 * 0xE9 <four bytes displacement>
792 * Note: the displacement is relative to the next instruction
793 */
794 callTab[i][0] = 0xE9; /* jmp */
795 *(unsigned*)(void*)&callTab[i][1] = _aImportTab[i].ulAddress - (unsigned)&callTab[i][cb+5];
796 }
797 else
798 { /* !fatal! - this should never really happen... */
799 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
800 Int3(); /* ipe - later! */
801 return 1;
802 }
803 break;
804 }
805
806
807 /*
808 * 16-bit imported procedure.
809 * This is called by issuing a far call to the calltab entry.
810 */
811 case EPT_PROCIMPORT16:
812 {
813 cb = _aImportTab[i].cbProlog = interpretFunctionProlog16((char*)_aImportTab[i].ulAddress, FALSE);
814 if (cb > 0 && cb + 8 < MAXSIZE_PROLOG)
815 {
816 /*
817 * Create far jump from calltab to original function.
818 * 0xEA <four byte target address> <two byte target selector>
819 */
820 callTab[i][0] = 0xEA; /* jmp far ptr */
821 *(unsigned long*)(void*)&callTab[i][1] = _aImportTab[i].offObject;
822 *(unsigned short*)(void*)&callTab[i][5] = _aImportTab[i].usSel;
823 }
824 else
825 { /* !fatal! - this should never really happen... */
826 kprintf(("ImportTabInit: FATAL verify failed for procedure no.%d when importing it!\n",i));
827 Int3(); /* ipe - later! */
828 return 1;
829 }
830 break;
831 }
832
833
834 /*
835 * 16/32-bit importe variable.
836 * This is used by accessing the 32-bit flat address in the callTab.
837 * callTab-entry + 4 holds the offset of the variable into the object.
838 * callTab-entry + 8 holds the selector for the object. (These two fields is the 16:32-bit pointer to the variable.)
839 * callTab-entry + a holds the 16-bit offset for the variable.
840 * callTab-entry + c holds the selector for the object. (These two fiels is the 16:16-bit pointer to the variable.)
841 */
842 case EPT_VARIMPORT32:
843 case EPT_VARIMPORT16:
844 *(unsigned long*)(void*)&callTab[i][0] = _aImportTab[i].ulAddress;
845 *(unsigned long*)(void*)&callTab[i][4] = _aImportTab[i].offObject;
846 *(unsigned short*)(void*)&callTab[i][8] = _aImportTab[i].usSel;
847 *(unsigned short*)(void*)&callTab[i][0xa] = (unsigned short)_aImportTab[i].offObject;
848 *(unsigned short*)(void*)&callTab[i][0xc] = _aImportTab[i].usSel;
849 break;
850
851 default:
852 kprintf(("ImportTabInit: unsupported type. (procedure no.%d, cb=%d)\n", i, cb));
853 Int3(); /* ipe - later! */
854 return 1;
855 } /* switch - type */
856 } /* for */
857
858 return NO_ERROR;
859}
860
Note: See TracBrowser for help on using the repository browser.