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

Last change on this file since 3074 was 3074, checked in by sandervl, 25 years ago

file handle + registry changes

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