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

Last change on this file since 8449 was 8449, checked in by sandervl, 23 years ago

added MapSL stub

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