Release 980201
[wine/multimedia.git] / win32 / kernel32.c
bloba22c775437546ea704b953dbd5c198e0c88f7538
1 /*
2 * KERNEL32 thunks and other undocumented stuff
4 * Copyright 1997 Marcus Meissner
5 */
7 #include <stdio.h>
8 #include "windows.h"
9 #include "callback.h"
10 #include "resource.h"
11 #include "task.h"
12 #include "user.h"
13 #include "heap.h"
14 #include "module.h"
15 #include "process.h"
16 #include "stackframe.h"
17 #include "selectors.h"
18 #include "task.h"
19 #include "win.h"
20 #include "stddebug.h"
21 #include "debug.h"
23 /***********************************************************************
24 * *
25 * Win95 internal thunks *
26 * *
27 ***********************************************************************/
29 /***********************************************************************
30 * Generates a FT_Prolog call.
32 * 0FB6D1 movzbl edx,cl
33 * 8B1495xxxxxxxx mov edx,[4*edx + xxxxxxxx]
34 * 68xxxxxxxx push FT_Prolog
35 * C3 lret
37 static void _write_ftprolog(LPBYTE thunk,DWORD thunkstart) {
38 LPBYTE x;
40 x = thunk;
41 *x++ = 0x0f;*x++=0xb6;*x++=0xd1; /* movzbl edx,cl */
42 *x++ = 0x8B;*x++=0x14;*x++=0x95;*(DWORD*)x= thunkstart;
43 x+=4; /* mov edx, [4*edx + thunkstart] */
44 *x++ = 0x68; *(DWORD*)x = (DWORD)GetProcAddress32(GetModuleHandle32A("KERNEL32"),"FT_Prolog");
45 x+=4; /* push FT_Prolog */
46 *x++ = 0xC3; /* lret */
47 /* fill rest with 0xCC / int 3 */
50 /***********************************************************************
51 * FT_PrologPrime (KERNEL32.89)
53 void WINAPI FT_PrologPrime(DWORD startind,LPBYTE thunk) {
54 _write_ftprolog(thunk,*(DWORD*)(startind+thunk));
57 /***********************************************************************
58 * Generates a QT_Thunk style call.
60 * 33C9 xor ecx, ecx
61 * 8A4DFC mov cl , [ebp-04]
62 * 8B148Dxxxxxxxx mov edx, [4*ecx + (EAX+EDX)]
63 * B8yyyyyyyy mov eax, QT_Thunk
64 * FFE0 jmp eax
66 static void _write_qtthunk(LPBYTE start,DWORD thunkstart) {
67 LPBYTE x;
69 x = start;
70 *x++ = 0x33;*x++=0xC9; /* xor ecx,ecx */
71 *x++ = 0x8A;*x++=0x4D;*x++=0xFC; /* movb cl,[ebp-04] */
72 *x++ = 0x8B;*x++=0x14;*x++=0x8D;*(DWORD*)x= thunkstart;
73 x+=4; /* mov edx, [4*ecx + (EAX+EDX) */
74 *x++ = 0xB8; *(DWORD*)x = (DWORD)GetProcAddress32(GetModuleHandle32A("KERNEL32"),"QT_Thunk");
75 x+=4; /* mov eax , QT_Thunk */
76 *x++ = 0xFF; *x++ = 0xE0; /* jmp eax */
77 /* should fill the rest of the 32 bytes with 0xCC */
80 /***********************************************************************
81 * ThunkConnect32 (KERNEL32)
82 * Connects a 32bit and a 16bit thunkbuffer.
84 struct thunkstruct
86 char magic[4];
87 DWORD length;
88 DWORD ptr;
89 DWORD x0C;
91 DWORD x10;
92 DWORD x14;
93 DWORD x18;
94 DWORD x1C;
95 DWORD x20;
98 UINT32 WINAPI ThunkConnect32( struct thunkstruct *ths, LPSTR thunkfun16,
99 LPSTR module16, LPSTR module32, HMODULE32 hmod32,
100 DWORD dllinitarg1 )
102 HINSTANCE16 hmm;
103 SEGPTR thkbuf;
104 struct thunkstruct *ths16;
106 dprintf_thunk(stddeb,"ThunkConnect32(<struct>,%s,%s,%s,%x,%lx)\n",
107 thunkfun16,module32,module16,hmod32,dllinitarg1
109 dprintf_thunk(stddeb," magic = %c%c%c%c\n",
110 ths->magic[0],
111 ths->magic[1],
112 ths->magic[2],
113 ths->magic[3]
115 dprintf_thunk(stddeb," length = %lx\n",ths->length);
116 if (lstrncmp32A(ths->magic,"SL01",4)&&lstrncmp32A(ths->magic,"LS01",4))
117 return 0;
118 hmm=LoadModule16(module16,NULL);
119 if (hmm<=32)
120 return 0;
121 thkbuf=(SEGPTR)WIN32_GetProcAddress16(hmm,thunkfun16);
122 if (!thkbuf)
123 return 0;
124 ths16=(struct thunkstruct*)PTR_SEG_TO_LIN(thkbuf);
125 if (lstrncmp32A(ths16->magic,ths->magic,4))
126 return 0;
128 if (!lstrncmp32A(ths->magic,"SL01",4)) {
129 if (ths16->length != ths->length)
130 return 0;
131 ths->x0C = (DWORD)ths16;
133 dprintf_thunk(stddeb," ths16 magic is 0x%08lx\n",*(DWORD*)ths16->magic);
134 if (*((DWORD*)ths16->magic) != 0x0000304C)
135 return 0;
136 if (!*(WORD*)(((LPBYTE)ths16)+0x12))
137 return 0;
140 if (!lstrncmp32A(ths->magic,"LS01",4)) {
141 if (ths16->length != ths->length)
142 return 0;
143 ths->ptr = (DWORD)PTR_SEG_TO_LIN(ths16->ptr);
144 /* code offset for QT_Thunk is at 0x1C... */
145 _write_qtthunk (((LPBYTE)ths) + ths->x1C,ths->ptr);
146 /* code offset for FT_Prolog is at 0x20... */
147 _write_ftprolog(((LPBYTE)ths) + ths->x20,ths->ptr);
148 return 1;
150 return TRUE;
154 /**********************************************************************
155 * QT_Thunk (KERNEL32)
157 * The target address is in EDX.
158 * The 16 bit arguments start at ESP+4.
159 * The number of 16bit argumentbytes is EBP-ESP-0x44 (68 Byte thunksetup).
160 * [ok]
162 VOID WINAPI QT_Thunk(CONTEXT *context)
164 CONTEXT context16;
165 DWORD argsize;
166 THDB *thdb = THREAD_Current();
168 memcpy(&context16,context,sizeof(context16));
170 CS_reg(&context16) = HIWORD(EDX_reg(context));
171 IP_reg(&context16) = LOWORD(EDX_reg(context));
172 EBP_reg(&context16) = OFFSETOF( thdb->cur_stack )
173 + (WORD)&((STACK16FRAME*)0)->bp;
175 argsize = EBP_reg(context)-ESP_reg(context)-0x44;
177 memcpy( ((LPBYTE)THREAD_STACK16(thdb))-argsize,
178 (LPBYTE)ESP_reg(context)+4, argsize );
180 EAX_reg(context) = Callbacks->CallRegisterShortProc( &context16, argsize );
184 /**********************************************************************
185 * WOWCallback16 (KERNEL32.62)(WOW32.2)
187 DWORD WINAPI WOWCallback16(FARPROC16 fproc,DWORD arg)
189 DWORD ret;
190 dprintf_thunk(stddeb,"WOWCallback16(%p,0x%08lx) ",fproc,arg);
191 ret = Callbacks->CallWOWCallbackProc(fproc,arg);
192 dprintf_thunk(stddeb,"... returns %ld\n",ret);
193 return ret;
196 /**********************************************************************
197 * WOWCallback16Ex (KERNEL32.55)(WOW32.3)
199 BOOL32 WINAPI WOWCallback16Ex(
200 FARPROC16 vpfn16,DWORD dwFlags,DWORD cbArgs,LPVOID pArgs,
201 LPDWORD pdwRetCode
203 return Callbacks->CallWOWCallback16Ex(vpfn16,dwFlags,cbArgs,pArgs,pdwRetCode);
206 /***********************************************************************
207 * _KERNEL32_52 (KERNEL32.52)
208 * Returns a pointer to ThkBuf in the 16bit library SYSTHUNK.DLL.
209 * [ok probably]
211 LPVOID WINAPI _KERNEL32_52()
213 HMODULE32 hmod = LoadLibrary16("systhunk.dll");
215 dprintf_thunk(stddeb, "_KERNEL32_52: systhunk.dll module %d\n", hmod);
217 if (hmod<=32)
218 return 0;
219 return PTR_SEG_TO_LIN(WIN32_GetProcAddress16(hmod,"ThkBuf"));
222 /***********************************************************************
223 * _KERNEL32_43 (KERNEL32.42)
224 * A thunkbuffer link routine
225 * The thunkbuf looks like:
227 * 00: DWORD length ? don't know exactly
228 * 04: SEGPTR ptr ? where does it point to?
229 * The pointer ptr is written into the first DWORD of 'thunk'.
230 * (probably correct implemented)
231 * [ok probably]
233 DWORD WINAPI _KERNEL32_43(LPDWORD thunk,LPCSTR thkbuf,DWORD len,
234 LPCSTR dll16,LPCSTR dll32)
236 HINSTANCE16 hmod;
237 LPDWORD addr;
238 SEGPTR segaddr;
240 hmod = LoadLibrary16(dll16);
241 if (hmod<32) {
242 fprintf(stderr,"KERNEL32_43->failed to load 16bit DLL %s, error %d\n",dll16,hmod);
243 return 0;
245 segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf);
246 if (!segaddr) {
247 fprintf(stderr,"KERNEL32_43->no %s exported from %s!\n",thkbuf,dll16);
248 return 0;
250 addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
251 if (addr[0] != len) {
252 fprintf(stderr,"KERNEL32_43->thkbuf length mismatch? %ld vs %ld\n",len,addr[0]);
253 return 0;
255 if (!addr[1])
256 return 0;
257 *(DWORD*)thunk = addr[1];
259 dprintf_thunk(stddeb, "_KERNEL32_43: loaded module %d, func %s (%d) @ %p (%p), returning %p\n",
260 hmod, HIWORD(thkbuf)==0 ? "<ordinal>" : thkbuf, (int)thkbuf, (void*)segaddr, addr, (void*)addr[1]);
262 return addr[1];
265 /***********************************************************************
266 * _KERNEL32_45 (KERNEL32.44)
267 * Another 32->16 thunk, the difference to QT_Thunk is, that the called routine
268 * uses 0x66 lret, and that we have to pass CX in DI.
269 * (there seems to be some kind of BL/BX return magic too...)
271 * [doesn't crash anymore]
273 VOID WINAPI _KERNEL32_45(CONTEXT *context)
275 CONTEXT context16;
276 LPBYTE curstack;
277 DWORD ret,stacksize;
278 THDB *thdb = THREAD_Current();
280 dprintf_thunk(stddeb,"KERNEL32_45(%%eax=0x%08lx(%%cx=0x%04lx,%%edx=0x%08lx))\n",
281 (DWORD)EAX_reg(context),(DWORD)CX_reg(context),(DWORD)EDX_reg(context)
283 stacksize = EBP_reg(context)-ESP_reg(context);
284 dprintf_thunk(stddeb," stacksize = %ld\n",stacksize);
286 memcpy(&context16,context,sizeof(context16));
288 DI_reg(&context16) = CX_reg(context);
289 CS_reg(&context16) = HIWORD(EAX_reg(context));
290 IP_reg(&context16) = LOWORD(EAX_reg(context));
292 curstack = PTR_SEG_TO_LIN(STACK16_PUSH( thdb, stacksize ));
293 memcpy(curstack - stacksize,(LPBYTE)ESP_reg(context),stacksize);
294 ret = Callbacks->CallRegisterLongProc(&context16,0);
295 STACK16_POP( thdb, stacksize );
297 dprintf_thunk(stddeb,". returned %08lx\n",ret);
298 EAX_reg(context) = ret;
301 /***********************************************************************
302 * _KERNEL32_40 (KERNEL32.40)
303 * YET Another 32->16 thunk, the difference to the others is still mysterious
304 * target address is EDX
306 * [crashes]
308 VOID WINAPI _KERNEL32_40(CONTEXT *context)
310 CONTEXT context16;
311 LPBYTE curstack;
312 DWORD ret,stacksize;
313 THDB *thdb = THREAD_Current();
315 dprintf_thunk(stddeb,"_KERNEL32_40(EDX=0x%08lx)\n",
316 EDX_reg(context)
318 stacksize = EBP_reg(context)-ESP_reg(context);
319 dprintf_thunk(stddeb," stacksize = %ld\n",stacksize);
320 dprintf_thunk(stddeb,"on top of stack: 0x%04x\n",*(WORD*)ESP_reg(context));
322 memcpy(&context16,context,sizeof(context16));
324 CS_reg(&context16) = HIWORD(EDX_reg(context));
325 IP_reg(&context16) = LOWORD(EDX_reg(context));
327 curstack = PTR_SEG_TO_LIN(STACK16_PUSH( thdb, stacksize ));
328 memcpy(curstack-stacksize,(LPBYTE)ESP_reg(context),stacksize);
329 ret = Callbacks->CallRegisterShortProc(&context16,0);
330 STACK16_POP( thdb, stacksize );
332 dprintf_thunk(stddeb,". returned %08lx\n",ret);
333 EAX_reg(context) = ret;
337 /***********************************************************************
338 * (KERNEL32.41)
339 * A thunk setup routine.
340 * Expects a pointer to a preinitialized thunkbuffer in the first argument
341 * looking like:
342 * 00..03: unknown (pointer, check _41, _43, _46)
343 * 04: EB1E jmp +0x20
345 * 06..23: unknown (space for replacement code, check .90)
347 * 24:>E800000000 call offset 29
348 * 29:>58 pop eax ( target of call )
349 * 2A: 2D25000000 sub eax,0x00000025 ( now points to offset 4 )
350 * 2F: BAxxxxxxxx mov edx,xxxxxxxx
351 * 34: 68yyyyyyyy push KERNEL32.90
352 * 39: C3 ret
354 * 3A: EB1E jmp +0x20
355 * 3E ... 59: unknown (space for replacement code?)
356 * 5A: E8xxxxxxxx call <32bitoffset xxxxxxxx>
357 * 5F: 5A pop edx
358 * 60: 81EA25xxxxxx sub edx, 0x25xxxxxx
359 * 66: 52 push edx
360 * 67: 68xxxxxxxx push xxxxxxxx
361 * 6C: 68yyyyyyyy push KERNEL32.89
362 * 71: C3 ret
363 * 72: end?
364 * This function checks if the code is there, and replaces the yyyyyyyy entries
365 * by the functionpointers.
366 * The thunkbuf looks like:
368 * 00: DWORD length ? don't know exactly
369 * 04: SEGPTR ptr ? where does it point to?
370 * The segpointer ptr is written into the first DWORD of 'thunk'.
371 * [ok probably]
374 LPVOID WINAPI _KERNEL32_41(LPBYTE thunk,LPCSTR thkbuf,DWORD len,LPCSTR dll16,
375 LPCSTR dll32)
377 HMODULE32 hkrnl32 = GetModuleHandle32A("KERNEL32");
378 HMODULE16 hmod;
379 LPDWORD addr,addr2;
380 DWORD segaddr;
382 /* FIXME: add checks for valid code ... */
383 /* write pointers to kernel32.89 and kernel32.90 (+ordinal base of 1) */
384 *(DWORD*)(thunk+0x35) = (DWORD)GetProcAddress32(hkrnl32,(LPSTR)90);
385 *(DWORD*)(thunk+0x6D) = (DWORD)GetProcAddress32(hkrnl32,(LPSTR)89);
388 hmod = LoadLibrary16(dll16);
389 if (hmod<32) {
390 fprintf(stderr,"KERNEL32_41->failed to load 16bit DLL %s, error %d\n",dll16,hmod);
391 return NULL;
393 segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf);
394 if (!segaddr) {
395 fprintf(stderr,"KERNEL32_41->no %s exported from %s!\n",thkbuf,dll16);
396 return NULL;
398 addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
399 if (addr[0] != len) {
400 fprintf(stderr,"KERNEL32_41->thkbuf length mismatch? %ld vs %ld\n",len,addr[0]);
401 return NULL;
403 addr2 = PTR_SEG_TO_LIN(addr[1]);
404 if (HIWORD(addr2))
405 *(DWORD*)thunk = (DWORD)addr2;
407 dprintf_thunk(stddeb, "_KERNEL32_41: loaded module %d, func %s(%d) @ %p (%p), returning %p\n",
408 hmod, HIWORD(thkbuf)==0 ? "<ordinal>" : thkbuf, (int)thkbuf, (void*)segaddr, addr, addr2);
410 return addr2;
413 /***********************************************************************
414 * (KERNEL32.90)
415 * QT Thunk priming function
416 * Rewrites the first part of the thunk to use the QT_Thunk interface
417 * and jumps to the start of that code.
418 * [ok]
420 VOID WINAPI _KERNEL32_90(CONTEXT *context)
422 dprintf_thunk(stddeb, "_KERNEL32_90: QT Thunk priming; context %p\n", context);
424 _write_qtthunk((LPBYTE)EAX_reg(context),*(DWORD*)(EAX_reg(context)+EDX_reg(context)));
425 /* we just call the real QT_Thunk right now
426 * we can bypass the relaycode, for we already have the registercontext
428 EDX_reg(context) = *(DWORD*)((*(DWORD*)(EAX_reg(context)+EDX_reg(context)))+4*(((BYTE*)EBP_reg(context))[-4]));
429 return QT_Thunk(context);
432 /***********************************************************************
433 * (KERNEL32.45)
434 * Another thunkbuf link routine.
435 * The start of the thunkbuf looks like this:
436 * 00: DWORD length
437 * 04: SEGPTR address for thunkbuffer pointer
438 * [ok probably]
440 VOID WINAPI _KERNEL32_46(LPBYTE thunk,LPSTR thkbuf,DWORD len,LPSTR dll16,
441 LPSTR dll32)
443 LPDWORD addr;
444 HMODULE16 hmod;
445 SEGPTR segaddr;
447 hmod = LoadLibrary16(dll16);
448 if (hmod < 32) {
449 fprintf(stderr,"KERNEL32_46->couldn't load %s, error %d\n",dll16,hmod);
450 return;
452 segaddr = (SEGPTR)WIN32_GetProcAddress16(hmod,thkbuf);
453 if (!segaddr) {
454 fprintf(stderr,"KERNEL32_46-> haven't found %s in %s!\n",thkbuf,dll16);
455 return;
457 addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr);
458 if (addr[0] != len) {
459 fprintf(stderr,"KERNEL32_46-> length of thkbuf differs from expected length! (%ld vs %ld)\n",addr[0],len);
460 return;
462 *(DWORD*)PTR_SEG_TO_LIN(addr[1]) = (DWORD)thunk;
464 dprintf_thunk(stddeb, "_KERNEL32_46: loaded module %d, func %s(%d) @ %p (%p)\n",
465 hmod, HIWORD(thkbuf)==0 ? "<ordinal>" : thkbuf, (int)thkbuf, (void*)segaddr, addr);
468 /**********************************************************************
469 * _KERNEL32_87
470 * Check if thunking is initialized (ss selector set up etc.)
471 * We do that differently, so just return TRUE.
472 * [ok]
474 BOOL32 WINAPI _KERNEL32_87()
476 dprintf_thunk(stddeb, "_KERNEL32_87: Yes, thunking is initialized\n");
477 return TRUE;
480 /**********************************************************************
481 * _KERNEL32_88
482 * One of the real thunking functions. This one seems to be for 32<->32
483 * thunks. It should probably be capable of crossing processboundaries.
485 * And YES, I've seen nr=48 (somewhere in the Win95 32<->16 OLE coupling)
486 * [ok]
488 DWORD WINAPIV _KERNEL32_88( DWORD nr, DWORD flags, FARPROC32 fun, ... )
490 DWORD i,ret;
491 DWORD *args = ((DWORD *)&fun) + 1;
493 dprintf_thunk(stddeb,"KERNEL32_88(%ld,0x%08lx,%p,[ ",nr,flags,fun);
494 for (i=0;i<nr/4;i++) { dprintf_thunk(stddeb,"0x%08lx,",args[i]); }
495 dprintf_thunk(stddeb,"])\n");
496 switch (nr) {
497 case 0: ret = fun();
498 break;
499 case 4: ret = fun(args[0]);
500 break;
501 case 8: ret = fun(args[0],args[1]);
502 break;
503 case 12: ret = fun(args[0],args[1],args[2]);
504 break;
505 case 16: ret = fun(args[0],args[1],args[2],args[3]);
506 break;
507 case 20: ret = fun(args[0],args[1],args[2],args[3],args[4]);
508 break;
509 case 24: ret = fun(args[0],args[1],args[2],args[3],args[4],args[5]);
510 break;
511 case 28: ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
512 break;
513 case 32: ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
514 break;
515 case 36: ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
516 break;
517 case 40: ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
518 break;
519 case 44: ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
520 break;
521 case 48: ret = fun(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
522 break;
523 default:
524 fprintf(stderr,"_KERNEL32_88: unsupported nr of arguments, %ld\n",nr);
525 ret = 0;
526 break;
529 dprintf_thunk(stddeb," returning %ld ...\n",ret);
530 return ret;
533 /**********************************************************************
534 * KERNEL_619 (KERNEL)
535 * Seems to store y and z depending on x in some internal lists...
537 WORD WINAPI _KERNEL_619(WORD x,DWORD y,DWORD z)
539 fprintf(stderr,"KERNEL_619(0x%04x,0x%08lx,0x%08lx)\n",x,y,z);
540 return x;
543 /**********************************************************************
544 * AllocSLCallback (KERNEL32)
546 * Win95 uses some structchains for callbacks. It allocates them
547 * in blocks of 100 entries, size 32 bytes each, layout:
548 * blockstart:
549 * 0: PTR nextblockstart
550 * 4: entry *first;
551 * 8: WORD sel ( start points to blockstart)
552 * A: WORD unknown
553 * 100xentry:
554 * 00..17: Code
555 * 18: PDB *owning_process;
556 * 1C: PTR blockstart
558 * We ignore this for now. (Just a note for further developers)
559 * FIXME: use this method, so we don't waste selectors...
561 * Following code is then generated by AllocSLCallback. The code is 16 bit, so
562 * the 0x66 prefix switches from word->long registers.
564 * 665A pop edx
565 * 6668x arg2 x pushl <arg2>
566 * 6652 push edx
567 * EAx arg1 x jmpf <arg1>
569 * returns the startaddress of this thunk.
571 * Note, that they look very similair to the ones allocates by THUNK_Alloc.
573 DWORD WINAPI
574 AllocSLCallback(DWORD finalizer,DWORD callback) {
575 LPBYTE x,thunk = HeapAlloc( GetProcessHeap(), 0, 32 );
576 WORD sel;
578 x=thunk;
579 *x++=0x66;*x++=0x5a; /* popl edx */
580 *x++=0x66;*x++=0x68;*(DWORD*)x=finalizer;x+=4; /* pushl finalizer */
581 *x++=0x66;*x++=0x52; /* pushl edx */
582 *x++=0xea;*(DWORD*)x=callback;x+=4; /* jmpf callback */
584 *(PDB32**)(thunk+18) = PROCESS_Current();
586 sel = SELECTOR_AllocBlock( thunk , 32, SEGMENT_CODE, FALSE, FALSE );
587 return (sel<<16)|0;
590 void WINAPI
591 FreeSLCallback(DWORD x) {
592 fprintf(stderr,"FreeSLCallback(0x%08lx)\n",x);
595 /**********************************************************************
596 * KERNEL_358 (KERNEL)
597 * Allocates a code segment which starts at the address passed in x. limit
598 * 0xfffff, and returns the pointer to the start.
600 DWORD WINAPI
601 _KERNEL_358(DWORD x) {
602 WORD sel;
604 fprintf(stderr,"_KERNEL_358(0x%08lx),stub\n",x);
605 if (!HIWORD(x))
606 return x;
608 sel = SELECTOR_AllocBlock( PTR_SEG_TO_LIN(x) , 0xffff, SEGMENT_CODE, FALSE, FALSE );
609 return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
612 /**********************************************************************
613 * KERNEL_359 (KERNEL)
614 * Frees the code segment of the passed linear pointer (This has usually
615 * been allocated by _KERNEL_358).
617 VOID WINAPI
618 _KERNEL_359(DWORD x) {
619 fprintf(stderr,"_KERNEL_359(0x%08lx),stub\n",x);
620 if ((HIWORD(x) & 7)!=7)
621 return;
622 SELECTOR_FreeBlock(x>>16,1);
623 return;
626 /**********************************************************************
627 * KERNEL_472 (KERNEL)
628 * something like GetCurrenthInstance.
630 VOID WINAPI
631 _KERNEL_472(CONTEXT *context) {
632 fprintf(stderr,"_KERNEL_472(0x%08lx),stub\n",EAX_reg(context));
633 if (!EAX_reg(context)) {
634 TDB *pTask = (TDB*)GlobalLock16(GetCurrentTask());
635 AX_reg(context)=pTask->hInstance;
636 return;
638 if (!HIWORD(EAX_reg(context)))
639 return; /* returns the passed value */
640 /* hmm ... fixme */
643 /**********************************************************************
644 * KERNEL_431 (KERNEL.431)
645 * IsPeFile
647 BOOL16 WINAPI KERNEL_431(LPSTR fn,WORD x) {
648 IMAGE_DOS_HEADER mzh;
649 HFILE32 hf;
650 OFSTRUCT ofs;
651 DWORD xmagic;
653 hf = OpenFile32(fn,&ofs,OF_READ);
654 if (hf==HFILE_ERROR32)
655 return FALSE;
656 if (sizeof(mzh)!=_lread32(hf,&mzh,sizeof(mzh))) {
657 _lclose32(hf);
658 return FALSE;
660 if (mzh.e_magic!=IMAGE_DOS_SIGNATURE) {
661 fprintf(stderr,"file has not got dos signature!\n");
662 _lclose32(hf);
663 return FALSE;
665 _llseek32(hf,mzh.e_lfanew,SEEK_SET);
666 if (sizeof(DWORD)!=_lread32(hf,&xmagic,sizeof(DWORD))) {
667 _lclose32(hf);
668 return FALSE;
670 _lclose32(hf);
671 return (xmagic == IMAGE_NT_SIGNATURE);
674 HANDLE32 WINAPI WOWHandle32(WORD handle,WOW_HANDLE_TYPE type) {
675 fprintf(stderr,"WOWHandle32(0x%04x,%d)\n",handle,type);
676 return (HANDLE32)handle;