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

Last change on this file since 2802 was 2802, checked in by sandervl, 26 years ago

Added new logging feature

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