2 * Emulator and Win95 thunks
4 * Copyright 1996 Alexandre Julliard
5 * Copyright 1997 Marcus Meissner
14 #include "stackframe.h"
19 typedef void (*RELAY
)();
23 typedef struct tagTHUNK
25 BYTE popl_eax
; /* 0x58 popl %eax (return address)*/
26 BYTE pushl_func
; /* 0x68 pushl $proc */
27 FARPROC32 proc WINE_PACKED
;
28 BYTE pushl_eax
; /* 0x50 pushl %eax */
29 BYTE jmp
; /* 0xe9 jmp relay (relative jump)*/
30 RELAY relay WINE_PACKED
;
31 struct tagTHUNK
*next WINE_PACKED
;
36 #define DECL_THUNK(name,proc,relay) \
37 THUNK name = { 0x58, 0x68, (FARPROC32)(proc), 0x50, 0xe9, \
38 (RELAY)((char *)(relay) - (char *)(&(name).next)), NULL }
41 static THUNK
*firstThunk
= NULL
;
43 static LRESULT
THUNK_CallWndProc16( WNDPROC16 proc
, HWND16 hwnd
, UINT16 msg
,
44 WPARAM16 wParam
, LPARAM lParam
);
46 /***********************************************************************
49 BOOL32
THUNK_Init(void)
51 /* Set the window proc calling functions */
52 WINPROC_SetCallWndProc16( THUNK_CallWndProc16
);
53 WINPROC_SetCallWndProc32( (WINPROC_CALLWNDPROC32
)CallTo32_4
);
58 /***********************************************************************
61 static THUNK
*THUNK_Alloc( FARPROC32 func
, RELAY relay
)
63 THUNK
*thunk
= HeapAlloc( GetProcessHeap(), 0, sizeof(*thunk
) );
66 thunk
->popl_eax
= 0x58;
67 thunk
->pushl_func
= 0x68;
69 thunk
->pushl_eax
= 0x50;
71 thunk
->relay
= (RELAY
)((char *)relay
- (char *)(&thunk
->next
));
72 thunk
->next
= firstThunk
;
79 /***********************************************************************
82 static THUNK
*THUNK_Find( FARPROC32 func
)
84 THUNK
*thunk
= firstThunk
;
85 while (thunk
&& (thunk
->proc
!= func
)) thunk
= thunk
->next
;
90 /***********************************************************************
93 static void THUNK_Free( THUNK
*thunk
)
95 if (HEAP_IsInsideHeap( GetProcessHeap(), 0, thunk
))
97 THUNK
**prev
= &firstThunk
;
98 while (*prev
&& (*prev
!= thunk
)) prev
= &(*prev
)->next
;
102 HeapFree( GetProcessHeap(), 0, thunk
);
106 fprintf( stderr
, "THUNK_Free: invalid thunk addr %p\n", thunk
);
110 /***********************************************************************
111 * THUNK_CallWndProc16
113 * Call a 16-bit window procedure
115 static LRESULT
THUNK_CallWndProc16( WNDPROC16 proc
, HWND16 hwnd
, UINT16 msg
,
116 WPARAM16 wParam
, LPARAM lParam
)
118 if ((msg
== WM_CREATE
) || (msg
== WM_NCCREATE
))
120 CREATESTRUCT16
*cs
= (CREATESTRUCT16
*)PTR_SEG_TO_LIN(lParam
);
121 /* Build the CREATESTRUCT on the 16-bit stack. */
122 /* This is really ugly, but some programs (notably the */
123 /* "Undocumented Windows" examples) want it that way. */
124 return CallTo16_long_lllllllwlwwwl( (FARPROC16
)proc
,
125 cs
->dwExStyle
, cs
->lpszClass
, cs
->lpszName
, cs
->style
,
126 MAKELONG( cs
->y
, cs
->x
), MAKELONG( cs
->cy
, cs
->cx
),
127 MAKELONG( cs
->hMenu
, cs
->hwndParent
), cs
->hInstance
,
128 (LONG
)cs
->lpCreateParams
, hwnd
, msg
, wParam
,
129 IF1632_Saved16_ss_sp
- sizeof(CREATESTRUCT16
) );
131 return CallTo16_long_wwwl( (FARPROC16
)proc
, hwnd
, msg
, wParam
, lParam
);
135 /***********************************************************************
136 * THUNK_EnumObjects16 (GDI.71)
138 INT16 WINAPI
THUNK_EnumObjects16( HDC16 hdc
, INT16 nObjType
,
139 GOBJENUMPROC16 func
, LPARAM lParam
)
141 DECL_THUNK( thunk
, func
, CallTo16_word_ll
);
142 return EnumObjects16( hdc
, nObjType
, (GOBJENUMPROC16
)&thunk
, lParam
);
146 /***********************************************************************
147 * THUNK_EnumObjects32 (GDI32.89)
149 INT32 WINAPI
THUNK_EnumObjects32( HDC32 hdc
, INT32 nObjType
,
150 GOBJENUMPROC32 func
, LPARAM lParam
)
152 DECL_THUNK( thunk
, func
, CallTo32_2
);
153 return EnumObjects32( hdc
, nObjType
, (GOBJENUMPROC32
)&thunk
, lParam
);
157 /*************************************************************************
158 * THUNK_EnumFonts16 (GDI.70)
160 INT16 WINAPI
THUNK_EnumFonts16( HDC16 hdc
, LPCSTR lpFaceName
,
161 FONTENUMPROC16 func
, LPARAM lParam
)
163 DECL_THUNK( thunk
, func
, CallTo16_word_llwl
);
164 return EnumFonts16( hdc
, lpFaceName
, (FONTENUMPROC16
)&thunk
, lParam
);
167 /*************************************************************************
168 * THUNK_EnumFonts32A (GDI32.84)
170 INT32 WINAPI
THUNK_EnumFonts32A( HDC32 hdc
, LPCSTR lpFaceName
,
171 FONTENUMPROC32A func
, LPARAM lParam
)
173 DECL_THUNK( thunk
, func
, CallTo32_4
);
174 return EnumFonts32A( hdc
, lpFaceName
, (FONTENUMPROC32A
)&thunk
, lParam
);
177 /*************************************************************************
178 * THUNK_EnumFonts32W (GDI32.85)
180 INT32 WINAPI
THUNK_EnumFonts32W( HDC32 hdc
, LPCWSTR lpFaceName
,
181 FONTENUMPROC32W func
, LPARAM lParam
)
183 DECL_THUNK( thunk
, func
, CallTo32_4
);
184 return EnumFonts32W( hdc
, lpFaceName
, (FONTENUMPROC32W
)&thunk
, lParam
);
187 /******************************************************************
188 * THUNK_EnumMetaFile16 (GDI.175)
190 BOOL16 WINAPI
THUNK_EnumMetaFile16( HDC16 hdc
, HMETAFILE16 hmf
,
191 MFENUMPROC16 func
, LPARAM lParam
)
193 DECL_THUNK( thunk
, func
, CallTo16_word_wllwl
);
194 return EnumMetaFile16( hdc
, hmf
, (MFENUMPROC16
)&thunk
, lParam
);
198 /*************************************************************************
199 * THUNK_EnumFontFamilies16 (GDI.330)
201 INT16 WINAPI
THUNK_EnumFontFamilies16( HDC16 hdc
, LPCSTR lpszFamily
,
202 FONTENUMPROC16 func
, LPARAM lParam
)
204 DECL_THUNK( thunk
, func
, CallTo16_word_llwl
);
205 return EnumFontFamilies16(hdc
, lpszFamily
, (FONTENUMPROC16
)&thunk
, lParam
);
209 /*************************************************************************
210 * THUNK_EnumFontFamilies32A (GDI32.80)
212 INT32 WINAPI
THUNK_EnumFontFamilies32A( HDC32 hdc
, LPCSTR lpszFamily
,
213 FONTENUMPROC32A func
, LPARAM lParam
)
215 DECL_THUNK( thunk
, func
, CallTo32_4
);
216 return EnumFontFamilies32A(hdc
,lpszFamily
,(FONTENUMPROC32A
)&thunk
,lParam
);
220 /*************************************************************************
221 * THUNK_EnumFontFamilies32W (GDI32.83)
223 INT32 WINAPI
THUNK_EnumFontFamilies32W( HDC32 hdc
, LPCWSTR lpszFamily
,
224 FONTENUMPROC32W func
, LPARAM lParam
)
226 DECL_THUNK( thunk
, func
, CallTo32_4
);
227 return EnumFontFamilies32W(hdc
,lpszFamily
,(FONTENUMPROC32W
)&thunk
,lParam
);
230 /*************************************************************************
231 * THUNK_EnumFontFamiliesEx16 (GDI.613)
233 INT16 WINAPI
THUNK_EnumFontFamiliesEx16( HDC16 hdc
, LPLOGFONT16 lpLF
,
234 FONTENUMPROCEX16 func
, LPARAM lParam
,
237 DECL_THUNK( thunk
, func
, CallTo16_word_llwl
);
238 return EnumFontFamiliesEx16( hdc
, lpLF
, (FONTENUMPROCEX16
)&thunk
,
243 /*************************************************************************
244 * THUNK_EnumFontFamiliesEx32A (GDI32.81)
246 INT32 WINAPI
THUNK_EnumFontFamiliesEx32A( HDC32 hdc
, LPLOGFONT32A lpLF
,
247 FONTENUMPROCEX32A func
, LPARAM lParam
,
250 DECL_THUNK( thunk
, func
, CallTo32_4
);
251 return EnumFontFamiliesEx32A( hdc
, lpLF
, (FONTENUMPROCEX32A
)&thunk
,
256 /*************************************************************************
257 * THUNK_EnumFontFamiliesEx32W (GDI32.82)
259 INT32 WINAPI
THUNK_EnumFontFamiliesEx32W( HDC32 hdc
, LPLOGFONT32W lpLF
,
260 FONTENUMPROCEX32W func
, LPARAM lParam
,
263 DECL_THUNK( thunk
, func
, CallTo32_4
);
264 return EnumFontFamiliesEx32W( hdc
, lpLF
, (FONTENUMPROCEX32W
)&thunk
,
269 /**********************************************************************
270 * THUNK_LineDDA16 (GDI.100)
272 void WINAPI
THUNK_LineDDA16( INT16 nXStart
, INT16 nYStart
, INT16 nXEnd
,
273 INT16 nYEnd
, LINEDDAPROC16 func
, LPARAM lParam
)
275 DECL_THUNK( thunk
, func
, CallTo16_word_wwl
);
276 LineDDA16( nXStart
, nYStart
, nXEnd
, nYEnd
, (LINEDDAPROC16
)&thunk
, lParam
);
280 /**********************************************************************
281 * THUNK_LineDDA32 (GDI32.248)
283 BOOL32 WINAPI
THUNK_LineDDA32( INT32 nXStart
, INT32 nYStart
, INT32 nXEnd
,
284 INT32 nYEnd
, LINEDDAPROC32 func
, LPARAM lParam
)
286 DECL_THUNK( thunk
, func
, CallTo32_3
);
287 return LineDDA32( nXStart
, nYStart
, nXEnd
, nYEnd
,
288 (LINEDDAPROC32
)&thunk
, lParam
);
292 /*******************************************************************
293 * THUNK_EnumWindows16 (USER.54)
295 BOOL16 WINAPI
THUNK_EnumWindows16( WNDENUMPROC16 func
, LPARAM lParam
)
297 DECL_THUNK( thunk
, func
, CallTo16_word_wl
);
298 return EnumWindows16( (WNDENUMPROC16
)&thunk
, lParam
);
302 /*******************************************************************
303 * THUNK_EnumWindows32 (USER32.192)
305 BOOL32 WINAPI
THUNK_EnumWindows32( WNDENUMPROC32 func
, LPARAM lParam
)
307 DECL_THUNK( thunk
, func
, CallTo32_2
);
308 return EnumWindows32( (WNDENUMPROC32
)&thunk
, lParam
);
312 /**********************************************************************
313 * THUNK_EnumChildWindows16 (USER.55)
315 BOOL16 WINAPI
THUNK_EnumChildWindows16( HWND16 parent
, WNDENUMPROC16 func
,
318 DECL_THUNK( thunk
, func
, CallTo16_word_wl
);
319 return EnumChildWindows16( parent
, (WNDENUMPROC16
)&thunk
, lParam
);
323 /**********************************************************************
324 * THUNK_EnumChildWindows32 (USER32.177)
326 BOOL32 WINAPI
THUNK_EnumChildWindows32( HWND32 parent
, WNDENUMPROC32 func
,
329 DECL_THUNK( thunk
, func
, CallTo32_2
);
330 return EnumChildWindows32( parent
, (WNDENUMPROC32
)&thunk
, lParam
);
334 /**********************************************************************
335 * THUNK_EnumTaskWindows16 (USER.225)
337 BOOL16 WINAPI
THUNK_EnumTaskWindows16( HTASK16 hTask
, WNDENUMPROC16 func
,
340 DECL_THUNK( thunk
, func
, CallTo16_word_wl
);
341 return EnumTaskWindows16( hTask
, (WNDENUMPROC16
)&thunk
, lParam
);
345 /**********************************************************************
346 * THUNK_EnumThreadWindows (USER32.189)
348 BOOL32 WINAPI
THUNK_EnumThreadWindows( DWORD id
, WNDENUMPROC32 func
,
351 DECL_THUNK( thunk
, func
, CallTo32_2
);
352 return EnumThreadWindows( id
, (WNDENUMPROC32
)&thunk
, lParam
);
356 /***********************************************************************
357 * THUNK_EnumProps16 (USER.27)
359 INT16 WINAPI
THUNK_EnumProps16( HWND16 hwnd
, PROPENUMPROC16 func
)
361 DECL_THUNK( thunk
, func
, CallTo16_word_wlw
);
362 return EnumProps16( hwnd
, (PROPENUMPROC16
)&thunk
);
366 /***********************************************************************
367 * THUNK_EnumProps32A (USER32.185)
369 INT32 WINAPI
THUNK_EnumProps32A( HWND32 hwnd
, PROPENUMPROC32A func
)
371 DECL_THUNK( thunk
, func
, CallTo32_3
);
372 return EnumProps32A( hwnd
, (PROPENUMPROC32A
)&thunk
);
376 /***********************************************************************
377 * THUNK_EnumProps32W (USER32.188)
379 INT32 WINAPI
THUNK_EnumProps32W( HWND32 hwnd
, PROPENUMPROC32W func
)
381 DECL_THUNK( thunk
, func
, CallTo32_3
);
382 return EnumProps32W( hwnd
, (PROPENUMPROC32W
)&thunk
);
386 /***********************************************************************
387 * THUNK_EnumPropsEx32A (USER32.186)
389 INT32 WINAPI
THUNK_EnumPropsEx32A( HWND32 hwnd
, PROPENUMPROCEX32A func
,
392 DECL_THUNK( thunk
, func
, CallTo32_4
);
393 return EnumPropsEx32A( hwnd
, (PROPENUMPROCEX32A
)&thunk
, lParam
);
397 /***********************************************************************
398 * THUNK_EnumPropsEx32W (USER32.187)
400 INT32 WINAPI
THUNK_EnumPropsEx32W( HWND32 hwnd
, PROPENUMPROCEX32W func
,
403 DECL_THUNK( thunk
, func
, CallTo32_4
);
404 return EnumPropsEx32W( hwnd
, (PROPENUMPROCEX32W
)&thunk
, lParam
);
408 /***********************************************************************
409 * THUNK_EnumSystemCodePages32A (KERNEL32.92)
411 BOOL32 WINAPI
THUNK_EnumSystemCodePages32A( CODEPAGE_ENUMPROC32A func
,
414 DECL_THUNK( thunk
, func
, CallTo32_1
);
415 return EnumSystemCodePages32A( (CODEPAGE_ENUMPROC32A
)&thunk
, flags
);
419 /***********************************************************************
420 * THUNK_EnumSystemCodePages32W (KERNEL32.93)
422 BOOL32 WINAPI
THUNK_EnumSystemCodePages32W( CODEPAGE_ENUMPROC32W func
,
425 DECL_THUNK( thunk
, func
, CallTo32_1
);
426 return EnumSystemCodePages32W( (CODEPAGE_ENUMPROC32W
)&thunk
, flags
);
429 /***********************************************************************
430 * THUNK_EnumSystemLocales32A (KERNEL32.92)
432 BOOL32 WINAPI
THUNK_EnumSystemLocales32A( LOCALE_ENUMPROC32A func
, DWORD flags
)
434 DECL_THUNK( thunk
, func
, CallTo32_1
);
435 return EnumSystemLocales32A( (LOCALE_ENUMPROC32A
)&thunk
, flags
);
439 /***********************************************************************
440 * THUNK_EnumSystemLocales32W (KERNEL32.93)
442 BOOL32 WINAPI
THUNK_EnumSystemLocales32W( LOCALE_ENUMPROC32W func
, DWORD flags
)
444 DECL_THUNK( thunk
, func
, CallTo32_1
);
445 return EnumSystemLocales32W( (LOCALE_ENUMPROC32W
)&thunk
, flags
);
448 /***********************************************************************
449 * THUNK_EnumResourceLanguages32W (KERNEL32.87)
451 BOOL32 WINAPI
THUNK_EnumResourceLanguages32W( HMODULE32 hmod
, LPCWSTR type
,
453 ENUMRESLANGPROC32W func
,
456 DECL_THUNK( thunk
, func
, CallTo32_5
);
457 return EnumResourceLanguages32W( hmod
,type
,name
,(ENUMRESLANGPROC32W
)&thunk
, lParam
);
460 /***********************************************************************
461 * THUNK_EnumResourceLanguages32A (KERNEL32.86)
463 BOOL32 WINAPI
THUNK_EnumResourceLanguages32A( HMODULE32 hmod
, LPCSTR type
,
465 ENUMRESLANGPROC32A func
,
468 DECL_THUNK( thunk
, func
, CallTo32_5
);
469 return EnumResourceLanguages32A( hmod
,type
,name
,(ENUMRESLANGPROC32A
)&thunk
, lParam
);
472 /***********************************************************************
473 * THUNK_EnumResourceNames32A (KERNEL32.88)
475 BOOL32 WINAPI
THUNK_EnumResourceNames32A( HMODULE32 hmod
, LPCSTR type
,
476 ENUMRESNAMEPROC32A func
, LONG lParam
)
478 DECL_THUNK( thunk
, func
, CallTo32_4
);
479 return EnumResourceNames32A( hmod
,type
,(ENUMRESNAMEPROC32A
)&thunk
,lParam
);
482 /***********************************************************************
483 * THUNK_EnumResourceNames32W (KERNEL32.89)
485 BOOL32 WINAPI
THUNK_EnumResourceNames32W( HMODULE32 hmod
, LPCWSTR type
,
486 ENUMRESNAMEPROC32W func
, LONG lParam
)
488 DECL_THUNK( thunk
, func
, CallTo32_4
);
489 return EnumResourceNames32W( hmod
,type
,(ENUMRESNAMEPROC32W
)&thunk
, lParam
);
492 /***********************************************************************
493 * THUNK_EnumResourceTypes32A (KERNEL32.90)
495 BOOL32 WINAPI
THUNK_EnumResourceTypes32A( HMODULE32 hmod
,
496 ENUMRESTYPEPROC32A func
, LONG lParam
)
498 DECL_THUNK( thunk
, func
, CallTo32_3
);
499 return EnumResourceTypes32A( hmod
,(ENUMRESTYPEPROC32A
)&thunk
, lParam
);
502 /***********************************************************************
503 * THUNK_EnumResourceTypes32W (KERNEL32.91)
505 BOOL32 WINAPI
THUNK_EnumResourceTypes32W( HMODULE32 hmod
,
506 ENUMRESTYPEPROC32W func
,
509 DECL_THUNK( thunk
, func
, CallTo32_3
);
510 return EnumResourceTypes32W( hmod
,(ENUMRESTYPEPROC32W
)&thunk
, lParam
);
514 /***********************************************************************
515 * THUNK_GrayString16 (USER.185)
517 BOOL16 WINAPI
THUNK_GrayString16( HDC16 hdc
, HBRUSH16 hbr
,
518 GRAYSTRINGPROC16 func
, LPARAM lParam
,
519 INT16 cch
, INT16 x
, INT16 y
,
522 DECL_THUNK( thunk
, func
, CallTo16_word_wlw
);
524 return GrayString16( hdc
, hbr
, NULL
, lParam
, cch
, x
, y
, cx
, cy
);
526 return GrayString16( hdc
, hbr
, (GRAYSTRINGPROC16
)&thunk
, lParam
, cch
,
531 /***********************************************************************
532 * THUNK_GrayString32A (USER32.314)
534 BOOL32 WINAPI
THUNK_GrayString32A( HDC32 hdc
, HBRUSH32 hbr
,
535 GRAYSTRINGPROC32 func
, LPARAM lParam
,
536 INT32 cch
, INT32 x
, INT32 y
,
539 DECL_THUNK( thunk
, func
, CallTo32_3
);
541 return GrayString32A( hdc
, hbr
, NULL
, lParam
, cch
, x
, y
, cx
, cy
);
543 return GrayString32A( hdc
, hbr
, (GRAYSTRINGPROC32
)&thunk
, lParam
, cch
,
548 /***********************************************************************
549 * THUNK_GrayString32W (USER32.315)
551 BOOL32 WINAPI
THUNK_GrayString32W( HDC32 hdc
, HBRUSH32 hbr
,
552 GRAYSTRINGPROC32 func
,
553 LPARAM lParam
, INT32 cch
, INT32 x
, INT32 y
,
556 DECL_THUNK( thunk
, func
, CallTo32_3
);
558 return GrayString32W( hdc
, hbr
, NULL
, lParam
, cch
, x
, y
, cx
, cy
);
560 return GrayString32W( hdc
, hbr
, (GRAYSTRINGPROC32
)&thunk
, lParam
, cch
,
565 /***********************************************************************
566 * THUNK_SetWindowsHook16 (USER.121)
568 FARPROC16 WINAPI
THUNK_SetWindowsHook16( INT16 id
, HOOKPROC16 proc
)
570 HINSTANCE16 hInst
= FarGetOwner( HIWORD(proc
) );
571 HTASK16 hTask
= (id
== WH_MSGFILTER
) ? GetCurrentTask() : 0;
572 THUNK
*thunk
= THUNK_Alloc( (FARPROC16
)proc
, (RELAY
)CallTo16_long_wwl
);
573 if (!thunk
) return 0;
574 return (FARPROC16
)SetWindowsHookEx16( id
, (HOOKPROC16
)thunk
, hInst
, hTask
);
578 /***********************************************************************
579 * THUNK_UnhookWindowsHook16 (USER.234)
581 BOOL16 WINAPI
THUNK_UnhookWindowsHook16( INT16 id
, HOOKPROC16 proc
)
584 THUNK
*thunk
= THUNK_Find( (FARPROC16
)proc
);
585 if (!thunk
) return FALSE
;
586 ret
= UnhookWindowsHook16( id
, (HOOKPROC16
)thunk
);
592 /***********************************************************************
593 * THUNK_SetWindowsHookEx16 (USER.291)
595 HHOOK WINAPI
THUNK_SetWindowsHookEx16( INT16 id
, HOOKPROC16 proc
,
596 HINSTANCE16 hInst
, HTASK16 hTask
)
598 THUNK
*thunk
= THUNK_Alloc( (FARPROC16
)proc
, (RELAY
)CallTo16_long_wwl
);
599 if (!thunk
) return 0;
600 return SetWindowsHookEx16( id
, (HOOKPROC16
)thunk
, hInst
, hTask
);
604 /***********************************************************************
605 * THUNK_UnhookWindowHookEx16 (USER.292)
607 BOOL16 WINAPI
THUNK_UnhookWindowsHookEx16( HHOOK hhook
)
609 THUNK
*thunk
= (THUNK
*)HOOK_GetProc16( hhook
);
610 BOOL16 ret
= UnhookWindowsHookEx16( hhook
);
611 if (thunk
) THUNK_Free( thunk
);
616 /***********************************************************************
617 * THUNK_CreateSystemTimer (SYSTEM.2)
619 WORD WINAPI
THUNK_CreateSystemTimer( WORD rate
, FARPROC16 callback
)
621 THUNK
*thunk
= THUNK_Alloc( callback
, (RELAY
)CallTo16_word_
);
622 if (!thunk
) return 0;
623 return CreateSystemTimer( rate
, (FARPROC16
)thunk
);
627 /***********************************************************************
628 * THUNK_KillSystemTimer (SYSTEM.3)
630 WORD WINAPI
THUNK_KillSystemTimer( WORD timer
)
632 extern WORD
SYSTEM_KillSystemTimer( WORD timer
); /* misc/system.c */
633 extern FARPROC16
SYSTEM_GetTimerProc( WORD timer
); /* misc/system.c */
635 THUNK
*thunk
= (THUNK
*)SYSTEM_GetTimerProc( timer
);
636 WORD ret
= SYSTEM_KillSystemTimer( timer
);
637 if (thunk
) THUNK_Free( thunk
);
642 /***********************************************************************
643 * THUNK_SetUnhandledExceptionFilter (KERNEL32.516)
645 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI
THUNK_SetUnhandledExceptionFilter(
646 LPTOP_LEVEL_EXCEPTION_FILTER filter
)
648 LPTOP_LEVEL_EXCEPTION_FILTER old
;
649 THUNK
*thunk
= THUNK_Alloc( (FARPROC16
)filter
, (RELAY
)CallTo32_1
);
650 if (!thunk
) return NULL
;
651 old
= SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER
)thunk
);
652 if (!old
) return NULL
;
653 thunk
= (THUNK
*)old
;
654 old
= (LPTOP_LEVEL_EXCEPTION_FILTER
)thunk
->proc
;
660 static FARPROC16 defDCHookProc
= NULL
;
662 /***********************************************************************
663 * THUNK_SetDCHook (GDI.190)
665 BOOL16 WINAPI
THUNK_SetDCHook( HDC16 hdc
, FARPROC16 proc
, DWORD dwHookData
)
667 THUNK
*thunk
, *oldThunk
;
669 if (!defDCHookProc
) /* Get DCHook Win16 entry point */
670 defDCHookProc
= MODULE_GetEntryPoint( GetModuleHandle16("USER"), 362 );
672 if (proc
!= defDCHookProc
)
674 thunk
= THUNK_Alloc( proc
, (RELAY
)CallTo16_word_wwll
);
675 if (!thunk
) return FALSE
;
677 else thunk
= (THUNK
*)DCHook
;
679 /* Free the previous thunk */
680 GetDCHook( hdc
, (FARPROC16
*)&oldThunk
);
681 if (oldThunk
&& (oldThunk
!= (THUNK
*)DCHook
)) THUNK_Free( oldThunk
);
683 return SetDCHook( hdc
, (FARPROC16
)thunk
, dwHookData
);
687 /***********************************************************************
688 * THUNK_GetDCHook (GDI.191)
690 DWORD WINAPI
THUNK_GetDCHook( HDC16 hdc
, FARPROC16
*phookProc
)
693 DWORD ret
= GetDCHook( hdc
, (FARPROC16
*)&thunk
);
696 if (thunk
== (THUNK
*)DCHook
)
698 if (!defDCHookProc
) /* Get DCHook Win16 entry point */
699 defDCHookProc
= MODULE_GetEntryPoint(GetModuleHandle16("USER"),
701 *phookProc
= defDCHookProc
;
703 else *phookProc
= thunk
->proc
;
708 /***********************************************************************
710 * Win95 internal thunks *
712 ***********************************************************************/
714 /***********************************************************************
715 * Generates a FT_Prolog call.
717 * 0FB6D1 movzbl edx,cl
718 * 8B1495xxxxxxxx mov edx,[4*edx + xxxxxxxx]
719 * 68xxxxxxxx push FT_Prolog
722 static void _write_ftprolog(LPBYTE start
,DWORD thunkstart
) {
726 *x
++ = 0x0f;*x
++=0xb6;*x
++=0xd1; /* movzbl edx,cl */
727 *x
++ = 0x8B;*x
++=0x14;*x
++=0x95;*(DWORD
*)x
= thunkstart
;
728 x
+=4; /* mov edx, [4*edx + thunkstart] */
729 *x
++ = 0x68; *(DWORD
*)x
= (DWORD
)GetProcAddress32(WIN32_GetModuleHandleA("KERNEL32"),"FT_Prolog");
730 x
+=4; /* push FT_Prolog */
731 *x
++ = 0xC3; /* lret */
732 /* fill rest with 0xCC / int 3 */
735 /***********************************************************************
736 * Generates a QT_Thunk style call.
739 * 8A4DFC mov cl , [ebp-04]
740 * 8B148Dxxxxxxxx mov edx, [4*ecx + (EAX+EDX)]
741 * B8yyyyyyyy mov eax, QT_Thunk
744 static void _write_qtthunk(LPBYTE start
,DWORD thunkstart
) {
748 *x
++ = 0x33;*x
++=0xC9; /* xor ecx,ecx */
749 *x
++ = 0x8A;*x
++=0x4D;*x
++=0xFC; /* movb cl,[ebp-04] */
750 *x
++ = 0x8B;*x
++=0x14;*x
++=0x8D;*(DWORD
*)x
= thunkstart
;
751 x
+=4; /* mov edx, [4*ecx + (EAX+EDX) */
752 *x
++ = 0xB8; *(DWORD
*)x
= (DWORD
)GetProcAddress32(WIN32_GetModuleHandleA("KERNEL32"),"QT_Thunk");
753 x
+=4; /* mov eax , QT_Thunk */
754 *x
++ = 0xFF; *x
++ = 0xE0; /* jmp eax */
755 /* should fill the rest of the 32 bytes with 0xCC */
758 /***********************************************************************
759 * ThunkConnect32 (KERNEL32)
760 * Connects a 32bit and a 16bit thunkbuffer.
776 UINT32 WINAPI
ThunkConnect32( struct thunkstruct
*ths
, LPSTR thunkfun16
,
777 LPSTR module16
, LPSTR module32
, HMODULE32 hmod32
,
782 struct thunkstruct
*ths16
;
784 fprintf(stdnimp
,"ThunkConnect32(<struct>,%s,%s,%s,%x,%lx)\n",
785 thunkfun16
,module32
,module16
,hmod32
,dllinitarg1
787 fprintf(stdnimp
," magic = %c%c%c%c\n",
793 fprintf(stdnimp
," length = %lx\n",ths
->length
);
794 if (lstrncmp32A(ths
->magic
,"SL01",4)&&lstrncmp32A(ths
->magic
,"LS01",4))
796 hmm
=LoadModule16(module16
,NULL
);
799 thkbuf
=(SEGPTR
)WIN32_GetProcAddress16(hmm
,thunkfun16
);
802 ths16
=(struct thunkstruct
*)PTR_SEG_TO_LIN(thkbuf
);
803 if (lstrncmp32A(ths16
->magic
,ths
->magic
,4))
806 if (!lstrncmp32A(ths
->magic
,"SL01",4)) {
807 if (ths16
->length
!= ths
->length
)
809 ths
->x0C
= (DWORD
)ths16
;
811 fprintf(stderr
," ths16 magic is 0x%08lx\n",*(DWORD
*)ths16
->magic
);
812 if (*((DWORD
*)ths16
->magic
) != 0x0000304C)
814 if (!*(WORD
*)(((LPBYTE
)ths16
)+0x12))
818 if (!lstrncmp32A(ths
->magic
,"LS01",4)) {
819 if (ths16
->length
!= ths
->length
)
821 ths
->ptr
= (DWORD
)PTR_SEG_TO_LIN(ths16
->ptr
);
822 /* code offset for QT_Thunk is at 0x1C... */
823 _write_qtthunk (((LPBYTE
)ths
) + ths
->x1C
,ths
->ptr
);
824 /* code offset for FT_Prolog is at 0x20... */
825 _write_ftprolog(((LPBYTE
)ths
) + ths
->x20
,ths
->ptr
);
832 /**********************************************************************
833 * The infamous and undocumented QT_Thunk procedure.
835 * We get arguments in [EBP+8] up to [EBP+38].
836 * We have to set up a frame in the 16 bit stackframe.
837 * saved_ss_sp: bp+0x40
844 extern DWORD IF1632_Saved16_ss_sp
;
845 VOID WINAPI
QT_Thunk(CONTEXT
*context
)
851 fprintf(stderr
,"QT_Thunk(%08lx) ..",EDX_reg(context
));
852 fprintf(stderr
," argsize probably ebp-esp=%ld\n",
853 EBP_reg(context
)-ESP_reg(context
)
855 memcpy(&context16
,context
,sizeof(context16
));
857 curstack
= PTR_SEG_TO_LIN(IF1632_Saved16_ss_sp
);
858 memcpy(curstack
-0x40,(LPBYTE
)EBP_reg(context
),0x40);
859 EBP_reg(&context16
) = LOWORD(IF1632_Saved16_ss_sp
)-0x40;
860 IF1632_Saved16_ss_sp
-= 0x3c;
862 CS_reg(&context16
) = HIWORD(EDX_reg(context
));
863 IP_reg(&context16
) = LOWORD(EDX_reg(context
));
865 ret
= CallTo16_regs_(&context16
);
867 fprintf(stderr
,". returned %08lx\n",ret
);
868 EAX_reg(context
) = ret
;
869 IF1632_Saved16_ss_sp
+= 0x3c;
873 /**********************************************************************
874 * WOWCallback16 (KERNEL32.62)
876 DWORD WINAPI
WOWCallback16(FARPROC16 fproc
,DWORD arg
)
879 fprintf(stderr
,"WOWCallback16(%p,0x%08lx) ",fproc
,arg
);
880 ret
= CallTo16_long_l(fproc
,arg
);
881 fprintf(stderr
,"... returns %ld\n",ret
);
885 /***********************************************************************
886 * _KERNEL32_52 (KERNEL32.52)
887 * FIXME: what does it really do?
889 VOID WINAPI
_KERNEL32_52(DWORD arg1
,CONTEXT
*regs
)
891 fprintf(stderr
,"_KERNE32_52(arg1=%08lx,%08lx)\n",arg1
,EDI_reg(regs
));
893 EAX_reg(regs
) = (DWORD
)WIN32_GetProcAddress16(EDI_reg(regs
),"ThkBuf");
895 fprintf(stderr
," GetProcAddress16(\"ThkBuf\") returns %08lx\n",
900 /***********************************************************************
901 * _KERNEL32_43 (KERNEL32.42)
902 * A thunkbuffer link routine
903 * The thunkbuf looks like:
905 * 00: DWORD length ? don't know exactly
906 * 04: SEGPTR ptr ? where does it point to?
907 * The pointer ptr is written into the first DWORD of 'thunk'.
908 * (probably correct implemented)
910 BOOL32 WINAPI
_KERNEL32_43(LPDWORD thunk
,LPCSTR thkbuf
,DWORD len
,
911 LPCSTR dll16
,LPCSTR dll32
)
917 fprintf(stderr
,"_KERNEL32_43(%p,%s,0x%08lx,%s,%s)\n",thunk
,thkbuf
,len
,dll16
,dll32
);
919 hmod
= LoadLibrary16(dll16
);
921 fprintf(stderr
,"->failed to load 16bit DLL %s, error %d\n",dll16
,hmod
);
924 segaddr
= (DWORD
)WIN32_GetProcAddress16(hmod
,(LPSTR
)thkbuf
);
926 fprintf(stderr
,"->no %s exported from %s!\n",thkbuf
,dll16
);
929 addr
= (LPDWORD
)PTR_SEG_TO_LIN(segaddr
);
930 if (addr
[0] != len
) {
931 fprintf(stderr
,"->thkbuf length mismatch? %ld vs %ld\n",len
,addr
[0]);
936 fprintf(stderr
," addr[1] is %08lx\n",addr
[1]);
937 *(DWORD
*)thunk
= addr
[1];
941 /***********************************************************************
942 * _KERNEL32_45 (KERNEL32.44)
943 * Looks like another 32->16 thunk. Dunno why they need two of them.
944 * calls the win16 address in EAX with the current stack.
946 * FIXME: doesn't seem to work correctly yet...
948 VOID WINAPI
_KERNEL32_45(CONTEXT
*context
)
954 fprintf(stderr
,"KERNEL32_45(%%eax=0x%08lx(%%cx=0x%04lx,%%edx=0x%08lx))\n",
955 (DWORD
)EAX_reg(context
),(DWORD
)CX_reg(context
),(DWORD
)EDX_reg(context
)
957 stacksize
= EBP_reg(context
)-ESP_reg(context
);
958 fprintf(stderr
," stacksize = %ld\n",stacksize
);
960 memcpy(&context16
,context
,sizeof(context16
));
962 curstack
= PTR_SEG_TO_LIN(IF1632_Saved16_ss_sp
);
963 memcpy(curstack
-stacksize
,(LPBYTE
)EBP_reg(context
),stacksize
);
964 fprintf(stderr
,"IF1632_Saved16_ss_sp is 0x%08lx\n",IF1632_Saved16_ss_sp
);
965 EBP_reg(&context16
) = LOWORD(IF1632_Saved16_ss_sp
)-stacksize
;
966 IF1632_Saved16_ss_sp
-= stacksize
;
968 DI_reg(&context16
) = CX_reg(context
);
969 CS_reg(&context16
) = HIWORD(EAX_reg(context
));
970 IP_reg(&context16
) = LOWORD(EAX_reg(context
));
971 /* some more registers spronged locally, but I don't think they are
975 ret
= CallTo16_regs_(&context16
);
977 fprintf(stderr
,". returned %08lx\n",ret
);
978 EAX_reg(context
) = ret
;
979 IF1632_Saved16_ss_sp
+= stacksize
;
983 /***********************************************************************
985 * A thunk setup routine.
986 * Expects a pointer to a preinitialized thunkbuffer in the first argument
988 * 00..03: unknown (pointer, check _41, _43, _46)
991 * 06..23: unknown (space for replacement code, check .90)
993 * 24:>E800000000 call offset 29
994 * 29:>58 pop eax ( target of call )
995 * 2A: 2D25000000 sub eax,0x00000025 ( now points to offset 4 )
996 * 2F: BAxxxxxxxx mov edx,xxxxxxxx
997 * 34: 68yyyyyyyy push KERNEL32.90
1000 * 3A: EB1E jmp +0x20
1001 * 3E ... 59: unknown (space for replacement code?)
1002 * 5A: E8xxxxxxxx call <32bitoffset xxxxxxxx>
1004 * 60: 81EA25xxxxxx sub edx, 0x25xxxxxx
1006 * 67: 68xxxxxxxx push xxxxxxxx
1007 * 6C: 68yyyyyyyy push KERNEL32.89
1010 * This function checks if the code is there, and replaces the yyyyyyyy entries
1011 * by the functionpointers.
1012 * The thunkbuf looks like:
1014 * 00: DWORD length ? don't know exactly
1015 * 04: SEGPTR ptr ? where does it point to?
1016 * The segpointer ptr is written into the first DWORD of 'thunk'.
1017 * (probably correct implemented)
1020 LPVOID WINAPI
_KERNEL32_41(LPBYTE thunk
,LPCSTR thkbuf
,DWORD len
,LPCSTR dll16
,
1023 HMODULE32 hkrnl32
= WIN32_GetModuleHandleA("KERNEL32");
1028 fprintf(stderr
,"KERNEL32_41(%p,%s,%ld,%s,%s)\n",
1029 thunk
,thkbuf
,len
,dll16
,dll32
1032 /* FIXME: add checks for valid code ... */
1033 /* write pointers to kernel32.89 and kernel32.90 (+ordinal base of 1) */
1034 *(DWORD
*)(thunk
+0x35) = (DWORD
)GetProcAddress32(hkrnl32
,(LPSTR
)90);
1035 *(DWORD
*)(thunk
+0x6D) = (DWORD
)GetProcAddress32(hkrnl32
,(LPSTR
)89);
1038 hmod
= LoadLibrary16(dll16
);
1040 fprintf(stderr
,"->failed to load 16bit DLL %s, error %d\n",dll16
,hmod
);
1043 segaddr
= (DWORD
)WIN32_GetProcAddress16(hmod
,(LPSTR
)thkbuf
);
1045 fprintf(stderr
,"->no %s exported from %s!\n",thkbuf
,dll16
);
1048 addr
= (LPDWORD
)PTR_SEG_TO_LIN(segaddr
);
1049 if (addr
[0] != len
) {
1050 fprintf(stderr
,"->thkbuf length mismatch? %ld vs %ld\n",len
,addr
[0]);
1053 addr2
= PTR_SEG_TO_LIN(addr
[1]);
1054 fprintf(stderr
," addr2 is %08lx:%p\n",addr
[1],addr2
);
1056 *(DWORD
*)thunk
= (DWORD
)addr2
;
1060 /***********************************************************************
1062 * Thunk priming? function
1063 * Rewrites the first part of the thunk to use the QT_Thunk interface
1064 * and jumps to the start of that code.
1066 VOID WINAPI
_KERNEL32_90(CONTEXT
*context
)
1068 fprintf(stderr
,"_KERNEL32_90(eax=0x%08lx,edx=0x%08lx,ebp[-4]=0x%02x,target = %08lx, *target =%08lx)\n",
1069 EAX_reg(context
),EDX_reg(context
),((BYTE
*)EBP_reg(context
))[-4],
1070 (*(DWORD
*)(EAX_reg(context
)+EDX_reg(context
)))+4*(((BYTE
*)EBP_reg(context
))[-4]),
1071 *(DWORD
*)((*(DWORD
*)(EAX_reg(context
)+EDX_reg(context
)))+4*(((BYTE
*)EBP_reg(context
))[-4]))
1073 _write_qtthunk((LPBYTE
)EAX_reg(context
),*(DWORD
*)(EAX_reg(context
)+EDX_reg(context
)));
1074 /* we just call the real QT_Thunk right now
1075 * we can bypass the relaycode, for we already have the registercontext
1077 EDX_reg(context
) = *(DWORD
*)((*(DWORD
*)(EAX_reg(context
)+EDX_reg(context
)))+4*(((BYTE
*)EBP_reg(context
))[-4]));
1078 return QT_Thunk(context
);
1081 /***********************************************************************
1083 * Another thunkbuf link routine.
1084 * The start of the thunkbuf looks like this:
1086 * 04: SEGPTR address for thunkbuffer pointer
1088 VOID WINAPI
_KERNEL32_46(LPBYTE thunk
,LPSTR thkbuf
,DWORD len
,LPSTR dll16
,
1095 fprintf(stderr
,"KERNEL32_46(%p,%s,%lx,%s,%s)\n",
1096 thunk
,thkbuf
,len
,dll16
,dll32
1098 hmod
= LoadLibrary16(dll16
);
1100 fprintf(stderr
,"->couldn't load %s, error %d\n",dll16
,hmod
);
1103 segaddr
= (SEGPTR
)WIN32_GetProcAddress16(hmod
,thkbuf
);
1105 fprintf(stderr
,"-> haven't found %s in %s!\n",thkbuf
,dll16
);
1108 addr
= (LPDWORD
)PTR_SEG_TO_LIN(segaddr
);
1109 if (addr
[0] != len
) {
1110 fprintf(stderr
,"-> length of thkbuf differs from expected length! (%ld vs %ld)\n",addr
[0],len
);
1113 *(DWORD
*)PTR_SEG_TO_LIN(addr
[1]) = (DWORD
)thunk
;
1116 /**********************************************************************
1118 * Check if thunking is initialized (ss selector set up etc.)
1120 BOOL32 WINAPI
_KERNEL32_87()
1122 fprintf(stderr
,"KERNEL32_87 stub, returning TRUE\n");
1126 /**********************************************************************
1128 * One of the real thunking functions. This one seems to be for 32<->32
1129 * thunks. It should probably be capable of crossing processboundaries.
1131 * And YES, I've seen nr=48 (somewhere in the Win95 32<->16 OLE coupling)
1133 DWORD WINAPI
_KERNEL32_88(DWORD
*args
)
1136 DWORD flags
= args
[1];
1137 FARPROC32 fun
= (FARPROC32
)args
[2];
1140 fprintf(stderr
,"KERNEL32_88(%ld,0x%08lx,%p,[ ",nr
,flags
,fun
);
1141 for (i
=0;i
<nr
/4;i
++)
1142 fprintf(stderr
,"0x%08lx,",args
[3+i
]);
1143 fprintf(stderr
,"])");
1146 case 0: ret
= CallTo32_0(fun
);
1148 case 4: ret
= CallTo32_1(fun
,args
[3]);
1150 case 8: ret
= CallTo32_2(fun
,args
[3],args
[4]);
1152 case 12: ret
= CallTo32_3(fun
,args
[3],args
[4],args
[5]);
1154 case 16: ret
= CallTo32_4(fun
,args
[3],args
[4],args
[5],args
[6]);
1156 case 20: ret
= CallTo32_5(fun
,args
[3],args
[4],args
[5],args
[6],args
[7]);
1158 case 24: ret
= CallTo32_6(fun
,args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
1160 case 28: ret
= CallTo32_7(fun
,args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
1162 case 32: ret
= CallTo32_8(fun
,args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
1164 case 36: ret
= CallTo32_9(fun
,args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11]);
1166 case 40: ret
= CallTo32_10(fun
,args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12]);
1168 case 44: ret
= CallTo32_11(fun
,args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13]);
1170 case 48: ret
= CallTo32_12(fun
,args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14]);
1173 fprintf(stderr
," unsupported nr of arguments, %ld\n",nr
);
1179 fprintf(stderr
," returning %ld ...\n",ret
);
1183 /**********************************************************************
1184 * KERNEL_619 (KERNEL)
1185 * Seems to store y and z depending on x in some internal lists...
1187 WORD WINAPI
_KERNEL_619(WORD x
,DWORD y
,DWORD z
)
1189 fprintf(stderr
,"KERNEL_619(0x%04x,0x%08lx,0x%08lx)\n",x
,y
,z
);