source: trunk/src/kernel32/thunk.cpp@ 22018

Last change on this file since 22018 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 14.3 KB
Line 
1/* $Id: thunk.cpp,v 1.8 2002-05-17 10:14:08 sandervl Exp $ */
2
3/*
4 * Win32 thunking API functions (mostly stubs)
5 *
6 * Copyright 1998 Patrick Haller (stubs + Wine port) (?)
7 *
8 * Original WINE code (win32\kernel32.c)
9 *
10 * KERNEL32 thunks and other undocumented stuff
11 *
12 * Copyright 1997-1998 Marcus Meissner
13 * Copyright 1998 Ulrich Weigand
14 * Copyright 1995 Alexandre Julliard
15 *
16 * Project Odin Software License can be found in LICENSE.TXT
17 *
18 */
19#include <os2win.h>
20#include <string.h>
21#include "thunk.h"
22
23#define DBG_LOCALLOG DBG_thunk
24#include "dbglocal.h"
25
26extern "C" {
27
28/************************************************************************
29 * _ConfirmWin16Lock (KERNEL32.96)
30 */
31DWORD WINAPI _ConfirmWin16Lock(void)
32{
33 dprintf(("STUB: _ConfirmWin16Lock"));
34 return 0;
35}
36
37/************************************************************************
38 * ReleaseThunkLock (KERNEL32.48)
39 */
40VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
41{
42 dprintf(("STUB: ReleaseThunkLock"));
43}
44
45/************************************************************************
46 * RestoreThunkLock (KERNEL32.49)
47 */
48VOID WINAPI RestoreThunkLock(DWORD mutex_count)
49{
50 dprintf(("STUB: RestoreThunkLock"));
51}
52
53//******************************************************************************
54//******************************************************************************
55DWORD WIN32API MapLS(LPCVOID address)
56{
57// _interrupt(3);
58 dprintf(("MapLS %X, not supported\n", address));
59 return((DWORD)address);
60}
61/***********************************************************************
62 * UnMapLS (KERNEL32.700)
63 *
64 * Free mapped selector.
65 */
66void WIN32API UnMapLS( SEGPTR sptr )
67{
68 dprintf(("UnMapLS - stub\n"));
69#if 0
70 if (SELECTOROF(sptr))
71 SELECTOR_FreeBlock( SELECTOROF(sptr), 1 );
72#endif
73}
74//******************************************************************************
75//******************************************************************************
76DWORD WIN32API ThunkProc(DWORD arg1)
77{
78 dprintf(("ThunkProc - stub\n"));
79 return(0);
80}
81//******************************************************************************
82//******************************************************************************
83void WIN32API FT_Prolog(CONTEXT *context)
84{
85 dprintf(("FT_Prolog - stub\n"));
86}
87/**********************************************************************
88 * FT_Thunk (KERNEL32.234)
89 *
90 * This routine performs the actual call to 16-bit code,
91 * similar to QT_Thunk. The differences are:
92 * - The call target is taken from the buffer created by FT_Prolog
93 * - Those arguments requested by the thunk code (by setting the
94 * corresponding bit in the bitmap at EBP-20) are converted
95 * from 32-bit pointers to segmented pointers (those pointers
96 * are guaranteed to point to structures copied to the stack
97 * by the thunk code, so we always use the 16-bit stack selector
98 * for those addresses).
99 *
100 * The bit #i of EBP-20 corresponds here to the DWORD starting at
101 * ESP+4 + 2*i.
102 *
103 * FIXME: It is unclear what happens if there are more than 32 WORDs
104 * of arguments, so that the single DWORD bitmap is no longer
105 * sufficient ...
106 */
107void WINAPI FT_Thunk( CONTEXT86 *context )
108{
109 DWORD mapESPrelative = *(DWORD *)(EBP_reg(context) - 20);
110 DWORD callTarget = *(DWORD *)(EBP_reg(context) - 52);
111
112 CONTEXT86 context16;
113 DWORD i, argsize;
114 LPBYTE newstack, oldstack;
115
116 dprintf(("FT_Thunk - stub\n"));
117
118#if 0
119 memcpy(&context16,context,sizeof(context16));
120
121 CS_reg(&context16) = HIWORD(callTarget);
122 EIP_reg(&context16) = LOWORD(callTarget);
123 EBP_reg(&context16) = OFFSETOF( NtCurrentTeb()->cur_stack )
124 + (WORD)&((STACK16FRAME*)0)->bp;
125
126 argsize = EBP_reg(context)-ESP_reg(context)-0x40;
127 newstack = (LPBYTE)CURRENT_STACK16 - argsize;
128 oldstack = (LPBYTE)ESP_reg(context);
129
130 memcpy( newstack, oldstack, argsize );
131
132 for (i = 0; i < 32; i++) /* NOTE: What about > 32 arguments? */
133 if (mapESPrelative & (1 << i))
134 {
135 SEGPTR *arg = (SEGPTR *)(newstack + 2*i);
136 *arg = PTR_SEG_OFF_TO_SEGPTR(SELECTOROF(NtCurrentTeb()->cur_stack),
137 OFFSETOF(NtCurrentTeb()->cur_stack) - argsize
138 + (*(LPBYTE *)arg - oldstack));
139 }
140
141 EAX_reg(context) = Callbacks->CallRegisterShortProc( &context16, argsize );
142 EDX_reg(context) = HIWORD(EAX_reg(context));
143 EAX_reg(context) = LOWORD(EAX_reg(context));
144
145 /* Copy modified buffers back to 32-bit stack */
146 memcpy( oldstack, newstack, argsize );
147#endif
148}
149
150/**********************************************************************
151 * FT_ExitNN (KERNEL32.218 - 232)
152 *
153 * One of the FT_ExitNN functions is called at the end of the thunk code.
154 * It removes the stack frame created by FT_Prolog, moves the function
155 * return from EBX to EAX (yes, FT_Thunk did use EAX for the return
156 * value, but the thunk code has moved it from EAX to EBX in the
157 * meantime ... :-), restores the caller's EBX, ESI, and EDI registers,
158 * and perform a return to the CALLER of the thunk code (while removing
159 * the given number of arguments from the caller's stack).
160 */
161
162static void FT_Exit(CONTEXT86 *context, int nPopArgs)
163{
164 dprintf(("FT_Exit - stub\n"));
165#if 0
166 /* Return value is in EBX */
167 EAX_reg(context) = EBX_reg(context);
168
169 /* Restore EBX, ESI, and EDI registers */
170 EBX_reg(context) = *(DWORD *)(EBP_reg(context) - 4);
171 ESI_reg(context) = *(DWORD *)(EBP_reg(context) - 8);
172 EDI_reg(context) = *(DWORD *)(EBP_reg(context) - 12);
173
174 /* Clean up stack frame */
175 ESP_reg(context) = EBP_reg(context);
176 EBP_reg(context) = stack32_pop(context);
177
178 /* Pop return address to CALLER of thunk code */
179 EIP_reg(context) = stack32_pop(context);
180 /* Remove arguments */
181 ESP_reg(context) += nPopArgs;
182#endif
183}
184
185void WINAPI FT_Exit0 (CONTEXT86 *context) { FT_Exit(context, 0); }
186void WINAPI FT_Exit4 (CONTEXT86 *context) { FT_Exit(context, 4); }
187void WINAPI FT_Exit8 (CONTEXT86 *context) { FT_Exit(context, 8); }
188void WINAPI FT_Exit12(CONTEXT86 *context) { FT_Exit(context, 12); }
189void WINAPI FT_Exit16(CONTEXT86 *context) { FT_Exit(context, 16); }
190void WINAPI FT_Exit20(CONTEXT86 *context) { FT_Exit(context, 20); }
191void WINAPI FT_Exit24(CONTEXT86 *context) { FT_Exit(context, 24); }
192void WINAPI FT_Exit28(CONTEXT86 *context) { FT_Exit(context, 28); }
193void WINAPI FT_Exit32(CONTEXT86 *context) { FT_Exit(context, 32); }
194void WINAPI FT_Exit36(CONTEXT86 *context) { FT_Exit(context, 36); }
195void WINAPI FT_Exit40(CONTEXT86 *context) { FT_Exit(context, 40); }
196void WINAPI FT_Exit44(CONTEXT86 *context) { FT_Exit(context, 44); }
197void WINAPI FT_Exit48(CONTEXT86 *context) { FT_Exit(context, 48); }
198void WINAPI FT_Exit52(CONTEXT86 *context) { FT_Exit(context, 52); }
199void WINAPI FT_Exit56(CONTEXT86 *context) { FT_Exit(context, 56); }
200/**********************************************************************
201 * QT_Thunk (KERNEL32)
202 *
203 * The target address is in EDX.
204 * The 16 bit arguments start at ESP+4.
205 * The number of 16bit argumentbytes is EBP-ESP-0x44 (68 Byte thunksetup).
206 * [ok]
207 */
208VOID WIN32API QT_Thunk(CONTEXT *context)
209{
210 dprintf(("QT_Thunk\n"));
211#if 0
212 CONTEXT context16;
213 DWORD argsize;
214
215 memcpy(&context16,context,sizeof(context16));
216
217 CS_reg(&context16) = HIWORD(EDX_reg(context));
218 IP_reg(&context16) = LOWORD(EDX_reg(context));
219
220 argsize = EBP_reg(context)-ESP_reg(context)-0x44;
221
222 /* additional 4 bytes used by the relaycode for storing the stackptr */
223 memcpy( ((LPBYTE)CURRENT_STACK16)-argsize-4,
224 (LPBYTE)ESP_reg(context)+4,
225 argsize
226 );
227 EAX_reg(context) = CallTo16_regs_short(&context16,-argsize);
228#endif
229}
230//******************************************************************************
231/***********************************************************************
232 * Generates a FT_Prolog call.
233 *
234 * 0FB6D1 movzbl edx,cl
235 * 8B1495xxxxxxxx mov edx,[4*edx + xxxxxxxx]
236 * 68xxxxxxxx push FT_Prolog
237 * C3 lret
238 */
239static void _write_ftprolog(LPBYTE thunk,DWORD thunkstart)
240{
241 LPBYTE x;
242
243 x = thunk;
244 *x++ = 0x0f;*x++=0xb6;*x++=0xd1; /* movzbl edx,cl */
245 *x++ = 0x8B;*x++=0x14;*x++=0x95;*(DWORD*)x= thunkstart;
246 x+=4; /* mov edx, [4*edx + thunkstart] */
247 *x++ = 0x68; *(DWORD*)x = (DWORD)FT_Prolog;
248 x+=4; /* push FT_Prolog */
249 *x++ = 0xC3; /* lret */
250 /* fill rest with 0xCC / int 3 */
251}
252//******************************************************************************
253/***********************************************************************
254 * Generates a QT_Thunk style call.
255 *
256 * 33C9 xor ecx, ecx
257 * 8A4DFC mov cl , [ebp-04]
258 * 8B148Dxxxxxxxx mov edx, [4*ecx + (EAX+EDX)]
259 * B8yyyyyyyy mov eax, QT_Thunk
260 * FFE0 jmp eax
261 */
262static void _write_qtthunk(LPBYTE start,DWORD thunkstart)
263{
264 LPBYTE x;
265
266 x = start;
267 *x++ = 0x33;*x++=0xC9; /* xor ecx,ecx */
268 *x++ = 0x8A;*x++=0x4D;*x++=0xFC; /* movb cl,[ebp-04] */
269 *x++ = 0x8B;*x++=0x14;*x++=0x8D;*(DWORD*)x= thunkstart;
270 x+=4; /* mov edx, [4*ecx + (EAX+EDX) */
271 *x++ = 0xB8; *(DWORD*)x = (DWORD)QT_Thunk;
272 x+=4; /* mov eax , QT_Thunk */
273 *x++ = 0xFF; *x++ = 0xE0; /* jmp eax */
274 /* should fill the rest of the 32 bytes with 0xCC */
275}
276
277//******************************************************************************
278//******************************************************************************
279DWORD WIN32API ThunkConnect32(thunkstruct *ths, LPSTR thunkfun16,
280 LPSTR module16, LPSTR module32, HMODULE hmod32,
281 DWORD dllinitarg1 )
282{
283 thunkstruct *ths16;
284
285// _interrupt(3);
286 dprintf(("ThunkConnect32 %s %s %s not supported\n", thunkfun16, module16, module32));
287
288 if(strncmp(ths->magic,"SL01",4) && strncmp(ths->magic,"LS01",4))
289 return 0;
290
291 ths16 = (thunkstruct *)LocalAlloc(LPTR, ths->length);
292 ths16->length = ths->length;
293 ths16->ptr = (DWORD)ThunkProc;
294
295 if(!strncmp(ths->magic,"SL01",4)) {
296 ths->x0C = (DWORD)ths16;
297 *(DWORD *)ths16->magic = 0x0000304C;
298 }
299 if(!strncmp(ths->magic,"LS01",4)) {
300 ths->ptr = ths16->ptr;
301 /* code offset for QT_Thunk is at 0x1C... */
302 _write_qtthunk (((LPBYTE)ths) + ths->x1C,ths->ptr);
303
304 /* code offset for FT_Prolog is at 0x20... */
305 _write_ftprolog(((LPBYTE)ths) + ths->x20,ths->ptr);
306 return 1;
307 }
308 return TRUE;
309}
310//******************************************************************************
311//******************************************************************************
312DWORD WIN32API K32Thk1632Prolog(DWORD arg1)
313{
314 dprintf(("OS2K32Thk1632Prolog %X not supported\n", arg1));
315 return(0);
316}
317//******************************************************************************
318//******************************************************************************
319DWORD WIN32API K32Thk1632Epilog(DWORD arg1)
320{
321 dprintf(("K32Thk1632Epilog %X not supported\n", arg1));
322 return(0);
323}
324//******************************************************************************
325//******************************************************************************
326DWORD WIN32API MapSLFix(DWORD arg1)
327{
328 dprintf(("MapSLFix %X not supported\n", arg1));
329 return(0);
330}
331//******************************************************************************
332//******************************************************************************
333void *WIN32API MapSL(DWORD arg1)
334{
335 dprintf(("MapSL %X not supported\n", arg1));
336 return NULL;
337}
338/***********************************************************************
339 * UnMapSLFixArray (KERNEL32.701)
340 */
341void WIN32API UnMapSLFixArray( SEGPTR sptr[], INT length, CONTEXT86 *context )
342{
343 /* Must not change EAX, hence defined as 'register' function */
344}
345/**********************************************************************
346 * SMapLS* (KERNEL32)
347 * These functions map linear pointers at [EBP+xxx] to segmented pointers
348 * and return them.
349 * Win95 uses some kind of alias structs, which it stores in [EBP+x] to
350 * unravel them at SUnMapLS. We just store the segmented pointer there.
351 */
352static void
353x_SMapLS_IP_EBP_x(CONTEXT86 *context,int argoff) {
354 DWORD val,ptr;
355
356 val =*(DWORD*)(EBP_reg(context)+argoff);
357 if (val<0x10000) {
358 ptr=val;
359 *(DWORD*)(EBP_reg(context)+argoff) = 0;
360 } else {
361 ptr = MapLS((LPVOID)val);
362 *(DWORD*)(EBP_reg(context)+argoff) = ptr;
363 }
364 EAX_reg(context) = ptr;
365}
366
367void WINAPI SMapLS_IP_EBP_8 (CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context, 8);}
368void WINAPI SMapLS_IP_EBP_12(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,12);}
369void WINAPI SMapLS_IP_EBP_16(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,16);}
370void WINAPI SMapLS_IP_EBP_20(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,20);}
371void WINAPI SMapLS_IP_EBP_24(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,24);}
372void WINAPI SMapLS_IP_EBP_28(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,28);}
373void WINAPI SMapLS_IP_EBP_32(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,32);}
374void WINAPI SMapLS_IP_EBP_36(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,36);}
375void WINAPI SMapLS_IP_EBP_40(CONTEXT86 *context) {x_SMapLS_IP_EBP_x(context,40);}
376
377void WINAPI SMapLS( CONTEXT86 *context )
378{
379 if (EAX_reg(context)>=0x10000) {
380 EAX_reg(context) = MapLS((LPVOID)EAX_reg(context));
381 EDX_reg(context) = EAX_reg(context);
382 } else {
383 EDX_reg(context) = 0;
384 }
385}
386
387void WINAPI SUnMapLS( CONTEXT86 *context )
388{
389 if (EAX_reg(context)>=0x10000)
390 UnMapLS((SEGPTR)EAX_reg(context));
391}
392
393static void
394x_SUnMapLS_IP_EBP_x(CONTEXT86 *context,int argoff) {
395 if (*(DWORD*)(EBP_reg(context)+argoff))
396 UnMapLS(*(DWORD*)(EBP_reg(context)+argoff));
397 *(DWORD*)(EBP_reg(context)+argoff)=0;
398}
399void WINAPI SUnMapLS_IP_EBP_8 (CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context, 8); }
400void WINAPI SUnMapLS_IP_EBP_12(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,12); }
401void WINAPI SUnMapLS_IP_EBP_16(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,16); }
402void WINAPI SUnMapLS_IP_EBP_20(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,20); }
403void WINAPI SUnMapLS_IP_EBP_24(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,24); }
404void WINAPI SUnMapLS_IP_EBP_28(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,28); }
405void WINAPI SUnMapLS_IP_EBP_32(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,32); }
406void WINAPI SUnMapLS_IP_EBP_36(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,36); }
407void WINAPI SUnMapLS_IP_EBP_40(CONTEXT86 *context) { x_SUnMapLS_IP_EBP_x(context,40); }
408
409} // extern "C"
410
Note: See TracBrowser for help on using the repository browser.