Release 961013
[wine] / if1632 / thunk.c
1 /*
2  * Emulator thunks
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include "windows.h"
8 #include "callback.h"
9 #include "heap.h"
10 #include "hook.h"
11 #include "module.h"
12 #include "stddebug.h"
13 #include "debug.h"
14
15 typedef void (*RELAY)();
16
17 #pragma pack(1)
18
19 typedef struct tagTHUNK
20 {
21     BYTE             popl_eax;           /* 0x58  popl  %eax (return address)*/
22     BYTE             pushl_func;         /* 0x68  pushl $proc */
23     FARPROC32        proc WINE_PACKED;
24     BYTE             pushl_eax;          /* 0x50  pushl %eax */
25     BYTE             jmp;                /* 0xe9  jmp   relay (relative jump)*/
26     RELAY            relay WINE_PACKED;
27     struct tagTHUNK *next WINE_PACKED;
28 } THUNK;
29
30 #pragma pack(4)
31
32 #define DECL_THUNK(name,proc,relay) \
33     THUNK name = { 0x58, 0x68, (FARPROC32)(proc), 0x50, 0xe9, \
34                    (RELAY)((char *)(relay) - (char *)(&(name).next)), NULL }
35
36
37 static THUNK *firstThunk = NULL;
38
39 /***********************************************************************
40  *           THUNK_Alloc
41  */
42 static THUNK *THUNK_Alloc( FARPROC32 func, RELAY relay )
43 {
44     THUNK *thunk = HeapAlloc( SystemHeap, 0, sizeof(*thunk) );
45     if (thunk)
46     {
47         thunk->popl_eax   = 0x58;
48         thunk->pushl_func = 0x68;
49         thunk->proc       = func;
50         thunk->pushl_eax  = 0x50;
51         thunk->jmp        = 0xe9;
52         thunk->relay      = (RELAY)((char *)relay - (char *)(&thunk->next));
53         thunk->next       = firstThunk;
54         firstThunk = thunk;
55     }
56     return thunk;
57 }
58
59
60 /***********************************************************************
61  *           THUNK_Find
62  */
63 static THUNK *THUNK_Find( FARPROC32 func )
64 {
65     THUNK *thunk = firstThunk;
66     while (thunk && (thunk->proc != func)) thunk = thunk->next;
67     return thunk;
68 }
69
70
71 /***********************************************************************
72  *           THUNK_Free
73  */
74 void THUNK_Free( THUNK *thunk )
75 {
76     if (HEAP_IsInsideHeap( SystemHeap, 0, thunk ))
77     {
78         THUNK **prev = &firstThunk;
79         while (*prev && (*prev != thunk)) prev = &(*prev)->next;
80         if (*prev)
81         {
82             *prev = thunk->next;
83             HeapFree( SystemHeap, 0, thunk );
84             return;
85         }
86     }
87     fprintf( stderr, "THUNK_Free: invalid thunk addr %p\n", thunk );
88 }
89
90
91 /***********************************************************************
92  *           THUNK_EnumObjects16   (GDI.71)
93  */
94 INT16 THUNK_EnumObjects16( HDC16 hdc, INT16 nObjType,
95                            GOBJENUMPROC16 func, LPARAM lParam )
96 {
97     DECL_THUNK( thunk, func, CallTo16_word_ll );
98     return EnumObjects( hdc, nObjType, (GOBJENUMPROC16)&thunk, lParam );
99 }
100
101
102 /*************************************************************************
103  *           THUNK_EnumFonts16   (GDI.70)
104  */
105 INT16 THUNK_EnumFonts16( HDC16 hdc, LPCSTR lpFaceName,
106                          FONTENUMPROC16 func, LPARAM lParam )
107 {
108     DECL_THUNK( thunk, func, CallTo16_word_llwl );
109     return EnumFonts( hdc, lpFaceName, (FONTENUMPROC16)&thunk, lParam );
110 }
111
112
113 /******************************************************************
114  *           THUNK_EnumMetaFile16   (GDI.175)
115  */
116 BOOL16 THUNK_EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
117                              MFENUMPROC16 func, LPARAM lParam )
118 {
119     DECL_THUNK( thunk, func, CallTo16_word_wllwl );
120     return EnumMetaFile( hdc, hmf, (MFENUMPROC16)&thunk, lParam );
121 }
122
123
124 /*************************************************************************
125  *           THUNK_EnumFontFamilies16   (GDI.330)
126  */
127 INT16 THUNK_EnumFontFamilies16( HDC16 hdc, LPCSTR lpszFamily,
128                                 FONTENUMPROC16 func, LPARAM lParam )
129 {
130     DECL_THUNK( thunk, func, CallTo16_word_llwl );
131     return EnumFontFamilies( hdc, lpszFamily, (FONTENUMPROC16)&thunk, lParam );
132 }
133
134
135 /**********************************************************************
136  *           THUNK_LineDDA16   (GDI.100)
137  */
138 void THUNK_LineDDA16( INT16 nXStart, INT16 nYStart, INT16 nXEnd, INT16 nYEnd,
139                       LINEDDAPROC16 func, LPARAM lParam )
140 {
141     DECL_THUNK( thunk, func, CallTo16_word_wwl );
142     LineDDA16( nXStart, nYStart, nXEnd, nYEnd, (LINEDDAPROC16)&thunk, lParam );
143 }
144
145
146 /**********************************************************************
147  *           THUNK_LineDDA32   (GDI32.248)
148  */
149 BOOL32 THUNK_LineDDA32( INT32 nXStart, INT32 nYStart, INT32 nXEnd, INT32 nYEnd,
150                         LINEDDAPROC32 func, LPARAM lParam )
151 {
152     DECL_THUNK( thunk, func, CallTo32_3 );
153     return LineDDA32( nXStart, nYStart, nXEnd, nYEnd,
154                       (LINEDDAPROC32)&thunk, lParam );
155 }
156
157
158 /*******************************************************************
159  *           THUNK_EnumWindows16   (USER.54)
160  */
161 BOOL16 THUNK_EnumWindows16( WNDENUMPROC16 func, LPARAM lParam )
162 {
163     DECL_THUNK( thunk, func, CallTo16_word_wl );
164     return EnumWindows16( (WNDENUMPROC16)&thunk, lParam );
165 }
166
167
168 /*******************************************************************
169  *           THUNK_EnumWindows32   (USER32.192)
170  */
171 BOOL32 THUNK_EnumWindows32( WNDENUMPROC32 func, LPARAM lParam )
172 {
173     DECL_THUNK( thunk, func, CallTo32_2 );
174     return EnumWindows32( (WNDENUMPROC32)&thunk, lParam );
175 }
176
177
178 /**********************************************************************
179  *           THUNK_EnumChildWindows16   (USER.55)
180  */
181 BOOL16 THUNK_EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
182                                  LPARAM lParam )
183 {
184     DECL_THUNK( thunk, func, CallTo16_word_wl );
185     return EnumChildWindows16( parent, (WNDENUMPROC16)&thunk, lParam );
186 }
187
188
189 /**********************************************************************
190  *           THUNK_EnumChildWindows32   (USER32.177)
191  */
192 BOOL32 THUNK_EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
193                                  LPARAM lParam )
194 {
195     DECL_THUNK( thunk, func, CallTo32_2 );
196     return EnumChildWindows32( parent, (WNDENUMPROC32)&thunk, lParam );
197 }
198
199
200 /**********************************************************************
201  *           THUNK_EnumTaskWindows16   (USER.225)
202  */
203 BOOL16 THUNK_EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
204                                 LPARAM lParam )
205 {
206     DECL_THUNK( thunk, func, CallTo16_word_wl );
207     return EnumTaskWindows16( hTask, (WNDENUMPROC16)&thunk, lParam );
208 }
209
210
211 /**********************************************************************
212  *           THUNK_EnumThreadWindows   (USER32.189)
213  */
214 BOOL32 THUNK_EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
215 {
216     DECL_THUNK( thunk, func, CallTo32_2 );
217     return EnumThreadWindows( id, (WNDENUMPROC32)&thunk, lParam );
218 }
219
220
221 /***********************************************************************
222  *           THUNK_EnumProps16   (USER.27)
223  */
224 INT16 THUNK_EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
225 {
226     DECL_THUNK( thunk, func, CallTo16_word_wlw );
227     return EnumProps16( hwnd, (PROPENUMPROC16)&thunk );
228 }
229
230
231 /***********************************************************************
232  *           THUNK_EnumProps32A   (USER32.185)
233  */
234 INT32 THUNK_EnumProps32A( HWND32 hwnd, PROPENUMPROC32A func )
235 {
236     DECL_THUNK( thunk, func, CallTo32_3 );
237     return EnumProps32A( hwnd, (PROPENUMPROC32A)&thunk );
238 }
239
240
241 /***********************************************************************
242  *           THUNK_EnumProps32W   (USER32.188)
243  */
244 INT32 THUNK_EnumProps32W( HWND32 hwnd, PROPENUMPROC32W func )
245 {
246     DECL_THUNK( thunk, func, CallTo32_3 );
247     return EnumProps32W( hwnd, (PROPENUMPROC32W)&thunk );
248 }
249
250
251 /***********************************************************************
252  *           THUNK_EnumPropsEx32A   (USER32.186)
253  */
254 INT32 THUNK_EnumPropsEx32A( HWND32 hwnd, PROPENUMPROCEX32A func, LPARAM lParam)
255 {
256     DECL_THUNK( thunk, func, CallTo32_4 );
257     return EnumPropsEx32A( hwnd, (PROPENUMPROCEX32A)&thunk, lParam );
258 }
259
260
261 /***********************************************************************
262  *           THUNK_EnumPropsEx32W   (USER32.187)
263  */
264 INT32 THUNK_EnumPropsEx32W( HWND32 hwnd, PROPENUMPROCEX32W func, LPARAM lParam)
265 {
266     DECL_THUNK( thunk, func, CallTo32_4 );
267     return EnumPropsEx32W( hwnd, (PROPENUMPROCEX32W)&thunk, lParam );
268 }
269
270
271 /***********************************************************************
272  *           THUNK_GrayString16   (USER.185)
273  */
274 BOOL16 THUNK_GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 func,
275                            LPARAM lParam, INT16 cch, INT16 x, INT16 y,
276                            INT16 cx, INT16 cy )
277 {
278     DECL_THUNK( thunk, func, CallTo16_word_wlw );
279     if (!func)
280         return GrayString( hdc, hbr, NULL, lParam, cch, x, y, cx, cy );
281     else
282         return GrayString( hdc, hbr, (GRAYSTRINGPROC16)&thunk, lParam, cch,
283                            x, y, cx, cy );
284 }
285
286
287 /***********************************************************************
288  *           THUNK_SetWindowsHook16   (USER.121)
289  */
290 FARPROC16 THUNK_SetWindowsHook16( INT16 id, HOOKPROC16 proc )
291 {
292     HINSTANCE16 hInst = FarGetOwner( HIWORD(proc) );
293     HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
294     THUNK *thunk = THUNK_Alloc( (FARPROC16)proc, (RELAY)CallTo16_long_wwl );
295     if (!thunk) return 0;
296     return (FARPROC16)SetWindowsHookEx16( id, (HOOKPROC16)thunk, hInst, hTask);
297 }
298
299
300 /***********************************************************************
301  *           THUNK_UnhookWindowsHook16   (USER.234)
302  */
303 BOOL16 THUNK_UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
304 {
305     BOOL16 ret = FALSE;
306     THUNK *thunk = THUNK_Find( (FARPROC16)proc );
307     if (thunk) ret = UnhookWindowsHook16( id, (HOOKPROC16)thunk );
308     return ret;
309 }
310
311
312 /***********************************************************************
313  *           THUNK_SetWindowsHookEx16   (USER.291)
314  */
315 HHOOK THUNK_SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
316                                 HTASK16 hTask )
317 {
318     THUNK *thunk = THUNK_Alloc( (FARPROC16)proc, (RELAY)CallTo16_long_wwl );
319     if (!thunk) return 0;
320     return SetWindowsHookEx16( id, (HOOKPROC16)thunk, hInst, hTask );
321 }
322
323
324 /***********************************************************************
325  *           THUNK_UnhookWindowHookEx16   (USER.292)
326  */
327 BOOL16 THUNK_UnhookWindowsHookEx16( HHOOK hhook )
328 {
329     THUNK *thunk = (THUNK *)HOOK_GetProc16( hhook );
330     BOOL16 ret = UnhookWindowsHookEx16( hhook );
331     THUNK_Free( thunk );
332     return ret;
333 }
334
335
336 static FARPROC16 defDCHookProc = NULL;
337
338 /***********************************************************************
339  *           THUNK_SetDCHook   (GDI.190)
340  */
341 BOOL16 THUNK_SetDCHook( HDC16 hdc, FARPROC16 proc, DWORD dwHookData )
342 {
343     THUNK *thunk, *oldThunk;
344
345     if (!defDCHookProc)  /* Get DCHook Win16 entry point */
346         defDCHookProc = MODULE_GetEntryPoint( GetModuleHandle("USER"), 362 );
347
348     if (proc != defDCHookProc)
349     {
350         thunk = THUNK_Alloc( proc, (RELAY)CallTo16_word_wwll );
351         if (!thunk) return FALSE;
352     }
353     else thunk = (THUNK *)DCHook;
354
355     /* Free the previous thunk */
356     GetDCHook( hdc, (FARPROC16 *)&oldThunk );
357     if (oldThunk && (oldThunk != (THUNK *)DCHook)) THUNK_Free( oldThunk );
358
359     return SetDCHook( hdc, (FARPROC16)thunk, dwHookData );
360 }
361
362
363 /***********************************************************************
364  *           THUNK_GetDCHook   (GDI.191)
365  */
366 DWORD THUNK_GetDCHook( HDC16 hdc, FARPROC16 *phookProc )
367 {
368     THUNK *thunk = NULL;
369     DWORD ret = GetDCHook( hdc, (FARPROC16 *)&thunk );
370     if (thunk)
371     {
372         if (thunk == (THUNK *)DCHook)
373         {
374             if (!defDCHookProc)  /* Get DCHook Win16 entry point */
375                 defDCHookProc = MODULE_GetEntryPoint( GetModuleHandle("USER"),
376                                                       362 );
377             *phookProc = defDCHookProc;
378         }
379         else *phookProc = thunk->proc;
380     }
381     return ret;
382 }
383
384
385 struct thunkstruct
386 {
387         char    magic[4];
388         DWORD   x1;
389         DWORD   x2;
390 };
391
392 UINT32 ThunkConnect32( struct thunkstruct *ths, LPSTR thunkfun16,
393                        LPSTR module16, LPSTR module32, HMODULE32 hmod32,
394                        DWORD dllinitarg1 )
395 {
396         HINSTANCE16     hmm;
397
398         fprintf(stdnimp,"ThunkConnect32(<struct>,%s,%s,%s,%x,%lx)\n",
399                 thunkfun16,module32,module16,hmod32,dllinitarg1
400         );
401         fprintf(stdnimp,"       magic = %c%c%c%c\n",
402                 ths->magic[0],
403                 ths->magic[1],
404                 ths->magic[2],
405                 ths->magic[3]
406         );
407         fprintf(stdnimp,"       x1 = %lx\n",ths->x1);
408         fprintf(stdnimp,"       x2 = %lx\n",ths->x2);
409         hmm=LoadModule(module16,NULL);
410         return TRUE;
411 }