Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 1 | /* |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 2 | * Emulator thunks |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 3 | * |
Alexandre Julliard | 491502b | 1997-11-01 19:08:16 +0000 | [diff] [blame] | 4 | * Copyright 1996, 1997 Alexandre Julliard |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 5 | * Copyright 1998 Ulrich Weigand |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 6 | */ |
| 7 | |
Marcus Meissner | 317af32 | 1999-02-17 13:51:06 +0000 | [diff] [blame] | 8 | #include <string.h> |
| 9 | #include "wine/winbase16.h" |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 10 | #include "callback.h" |
Ulrich Weigand | b4860a8 | 1999-07-24 10:15:55 +0000 | [diff] [blame] | 11 | #include "builtin16.h" |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 12 | #include "heap.h" |
Alexandre Julliard | d5041fc | 2000-07-25 16:42:25 +0000 | [diff] [blame] | 13 | #include "module.h" |
Ulrich Weigand | e6cc6fd | 1999-05-08 09:56:00 +0000 | [diff] [blame] | 14 | #include "neexe.h" |
Alexandre Julliard | 84c70f5 | 1997-05-09 08:40:27 +0000 | [diff] [blame] | 15 | #include "stackframe.h" |
Alexandre Julliard | 916f975 | 2000-02-26 16:51:13 +0000 | [diff] [blame] | 16 | #include "selectors.h" |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 17 | #include "debugtools.h" |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 18 | |
Alexandre Julliard | d5041fc | 2000-07-25 16:42:25 +0000 | [diff] [blame] | 19 | DEFAULT_DEBUG_CHANNEL(thunk); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 20 | |
Alexandre Julliard | 491502b | 1997-11-01 19:08:16 +0000 | [diff] [blame] | 21 | |
| 22 | /* List of the 16-bit callback functions. This list is used */ |
| 23 | /* by the build program to generate the file if1632/callto16.S */ |
| 24 | |
| 25 | /* ### start build ### */ |
Ulrich Weigand | 22d2c52 | 1999-07-23 19:27:36 +0000 | [diff] [blame] | 26 | extern WORD CALLBACK THUNK_CallTo16_word_ (FARPROC16); |
Ulrich Weigand | 22d2c52 | 1999-07-23 19:27:36 +0000 | [diff] [blame] | 27 | extern WORD CALLBACK THUNK_CallTo16_word_l (FARPROC16,LONG); |
| 28 | extern LONG CALLBACK THUNK_CallTo16_long_l (FARPROC16,LONG); |
Ulrich Weigand | 979000e | 1999-12-05 02:48:53 +0000 | [diff] [blame] | 29 | extern WORD CALLBACK THUNK_CallTo16_word_lllw (FARPROC16,LONG,LONG,LONG,WORD); |
Ulrich Weigand | 22d2c52 | 1999-07-23 19:27:36 +0000 | [diff] [blame] | 30 | extern WORD CALLBACK THUNK_CallTo16_word_lwww (FARPROC16,LONG,WORD,WORD,WORD); |
Ulrich Weigand | 22d2c52 | 1999-07-23 19:27:36 +0000 | [diff] [blame] | 31 | extern LONG CALLBACK THUNK_CallTo16_long_wwwl (FARPROC16,WORD,WORD,WORD,LONG); |
Ulrich Weigand | 22d2c52 | 1999-07-23 19:27:36 +0000 | [diff] [blame] | 32 | extern WORD CALLBACK THUNK_CallTo16_word_lwwww(FARPROC16,LONG,WORD,WORD,WORD,WORD); |
Alexandre Julliard | 198746d | 2000-08-14 14:29:22 +0000 | [diff] [blame] | 33 | extern WORD CALLBACK THUNK_CallTo16_word_w (FARPROC16,WORD); |
| 34 | extern WORD CALLBACK THUNK_CallTo16_word_wlww (FARPROC16,WORD,LONG,WORD,WORD); |
| 35 | extern WORD CALLBACK THUNK_CallTo16_word_ww (FARPROC16,WORD,WORD); |
| 36 | extern WORD CALLBACK THUNK_CallTo16_word_wwwl (FARPROC16,WORD,WORD,WORD,LONG); |
Alexandre Julliard | 491502b | 1997-11-01 19:08:16 +0000 | [diff] [blame] | 37 | /* ### stop build ### */ |
| 38 | |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 39 | static THUNK *firstThunk = NULL; |
| 40 | |
Patrik Stridvall | a9f6a9d | 2000-10-24 02:22:16 +0000 | [diff] [blame] | 41 | CALLOUT_TABLE Callout = { |
| 42 | /* PeekMessageA */ NULL, |
| 43 | /* GetMessageA */ NULL, |
| 44 | /* SendMessageA */ NULL, |
| 45 | /* PostMessageA */ NULL, |
Patrik Stridvall | a9f6a9d | 2000-10-24 02:22:16 +0000 | [diff] [blame] | 46 | /* TranslateMessage */ NULL, |
| 47 | /* DispatchMessageA */ NULL, |
| 48 | /* RedrawWindow */ NULL, |
| 49 | /* UserSignalProc */ NULL, |
| 50 | /* FinalUserInit16 */ NULL, |
| 51 | /* InitThreadInput16 */ NULL, |
| 52 | /* UserYield16) */ NULL, |
| 53 | /* DestroyIcon32 */ NULL, |
| 54 | /* WaitForInputIdle */ NULL, |
| 55 | /* MsgWaitForMultipleObjects */ NULL, |
| 56 | /* WindowFromDC */ NULL, |
| 57 | /* MessageBoxA */ NULL, |
| 58 | /* MessageBoxW */ NULL |
| 59 | }; |
Alexandre Julliard | 84c70f5 | 1997-05-09 08:40:27 +0000 | [diff] [blame] | 60 | |
| 61 | /*********************************************************************** |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 62 | * THUNK_Alloc |
| 63 | */ |
Huw D M Davies | 304d9a4 | 1999-09-13 15:15:45 +0000 | [diff] [blame] | 64 | FARPROC THUNK_Alloc( FARPROC16 func, RELAY relay ) |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 65 | { |
Ulrich Weigand | 2dec1ba | 1999-09-20 18:43:52 +0000 | [diff] [blame] | 66 | HANDLE16 hSeg; |
| 67 | NE_MODULE *pModule; |
| 68 | THUNK *thunk; |
| 69 | |
| 70 | /* NULL maps to NULL */ |
| 71 | if ( !func ) return NULL; |
| 72 | |
| 73 | /* |
| 74 | * If we got an 16-bit built-in API entry point, retrieve the Wine |
| 75 | * 32-bit handler for that API routine. |
| 76 | * |
| 77 | * NOTE: For efficiency reasons, we only check whether the selector |
| 78 | * of 'func' points to the code segment of a built-in module. |
| 79 | * It might be theoretically possible that the offset is such |
| 80 | * that 'func' does not point, in fact, to an API entry point. |
| 81 | * In this case, however, the pointer is corrupt anyway. |
| 82 | */ |
| 83 | hSeg = GlobalHandle16( SELECTOROF( func ) ); |
| 84 | pModule = NE_GetPtr( FarGetOwner16( hSeg ) ); |
| 85 | |
| 86 | if ( pModule && (pModule->flags & NE_FFLAGS_BUILTIN) |
| 87 | && NE_SEG_TABLE(pModule)[0].hSeg == hSeg ) |
| 88 | { |
| 89 | FARPROC proc = (FARPROC)((ENTRYPOINT16 *)PTR_SEG_TO_LIN( func ))->target; |
| 90 | |
Dimitrie O. Paun | dd03cc1 | 1999-12-08 03:56:23 +0000 | [diff] [blame] | 91 | TRACE( "(%04x:%04x, %p) -> built-in API %p\n", |
| 92 | SELECTOROF( func ), OFFSETOF( func ), relay, proc ); |
Ulrich Weigand | 2dec1ba | 1999-09-20 18:43:52 +0000 | [diff] [blame] | 93 | return proc; |
| 94 | } |
| 95 | |
| 96 | /* Otherwise, we need to alloc a thunk */ |
Alexandre Julliard | 90476d6 | 2000-02-16 22:47:24 +0000 | [diff] [blame] | 97 | thunk = HeapAlloc( GetProcessHeap(), 0, sizeof(*thunk) ); |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 98 | if (thunk) |
| 99 | { |
| 100 | thunk->popl_eax = 0x58; |
| 101 | thunk->pushl_func = 0x68; |
| 102 | thunk->proc = func; |
| 103 | thunk->pushl_eax = 0x50; |
| 104 | thunk->jmp = 0xe9; |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 105 | thunk->relay = (RELAY)((char *)relay - (char *)(&thunk->next)); |
Huw D M Davies | 304d9a4 | 1999-09-13 15:15:45 +0000 | [diff] [blame] | 106 | thunk->magic = CALLTO16_THUNK_MAGIC; |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 107 | thunk->next = firstThunk; |
| 108 | firstThunk = thunk; |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 109 | } |
Ulrich Weigand | 2dec1ba | 1999-09-20 18:43:52 +0000 | [diff] [blame] | 110 | |
Dimitrie O. Paun | dd03cc1 | 1999-12-08 03:56:23 +0000 | [diff] [blame] | 111 | TRACE( "(%04x:%04x, %p) -> allocated thunk %p\n", |
| 112 | SELECTOROF( func ), OFFSETOF( func ), relay, thunk ); |
Huw D M Davies | 304d9a4 | 1999-09-13 15:15:45 +0000 | [diff] [blame] | 113 | return (FARPROC)thunk; |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 114 | } |
| 115 | |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 116 | /*********************************************************************** |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 117 | * THUNK_Free |
| 118 | */ |
Huw D M Davies | 304d9a4 | 1999-09-13 15:15:45 +0000 | [diff] [blame] | 119 | void THUNK_Free( FARPROC thunk ) |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 120 | { |
Huw D M Davies | 304d9a4 | 1999-09-13 15:15:45 +0000 | [diff] [blame] | 121 | THUNK *t = (THUNK*)thunk; |
Ulrich Weigand | 2dec1ba | 1999-09-20 18:43:52 +0000 | [diff] [blame] | 122 | if ( !t || IsBadReadPtr( t, sizeof(*t) ) |
| 123 | || t->magic != CALLTO16_THUNK_MAGIC ) |
Huw D M Davies | 304d9a4 | 1999-09-13 15:15:45 +0000 | [diff] [blame] | 124 | return; |
| 125 | |
Alexandre Julliard | 90476d6 | 2000-02-16 22:47:24 +0000 | [diff] [blame] | 126 | if (HEAP_IsInsideHeap( GetProcessHeap(), 0, t )) |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 127 | { |
| 128 | THUNK **prev = &firstThunk; |
Huw D M Davies | 304d9a4 | 1999-09-13 15:15:45 +0000 | [diff] [blame] | 129 | while (*prev && (*prev != t)) prev = &(*prev)->next; |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 130 | if (*prev) |
| 131 | { |
Huw D M Davies | 304d9a4 | 1999-09-13 15:15:45 +0000 | [diff] [blame] | 132 | *prev = t->next; |
Alexandre Julliard | 90476d6 | 2000-02-16 22:47:24 +0000 | [diff] [blame] | 133 | HeapFree( GetProcessHeap(), 0, t ); |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 134 | return; |
| 135 | } |
| 136 | } |
Dimitrie O. Paun | dd03cc1 | 1999-12-08 03:56:23 +0000 | [diff] [blame] | 137 | ERR("invalid thunk addr %p\n", thunk ); |
Huw D M Davies | 304d9a4 | 1999-09-13 15:15:45 +0000 | [diff] [blame] | 138 | return; |
Alexandre Julliard | f1aa303 | 1996-08-05 17:42:43 +0000 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | |
| 142 | /*********************************************************************** |
Ulrich Weigand | b4860a8 | 1999-07-24 10:15:55 +0000 | [diff] [blame] | 143 | * THUNK_GetCalloutThunk |
| 144 | * |
| 145 | * Retrieve API entry point with given name from given module. |
| 146 | * If module is builtin, return the 32-bit entry point, otherwise |
| 147 | * create a 32->16 thunk to the 16-bit entry point, using the |
| 148 | * given relay code. |
| 149 | * |
| 150 | */ |
| 151 | static FARPROC THUNK_GetCalloutThunk( NE_MODULE *pModule, LPSTR name, RELAY relay ) |
| 152 | { |
| 153 | FARPROC16 proc = WIN32_GetProcAddress16( pModule->self, name ); |
| 154 | if ( !proc ) return 0; |
| 155 | |
| 156 | if ( pModule->flags & NE_FFLAGS_BUILTIN ) |
| 157 | return (FARPROC)((ENTRYPOINT16 *)PTR_SEG_TO_LIN( proc ))->target; |
| 158 | else |
| 159 | return (FARPROC)THUNK_Alloc( proc, relay ); |
| 160 | } |
| 161 | |
| 162 | /*********************************************************************** |
Ulrich Weigand | 61439d2 | 1998-12-24 15:12:20 +0000 | [diff] [blame] | 163 | * THUNK_InitCallout |
| 164 | */ |
| 165 | void THUNK_InitCallout(void) |
| 166 | { |
Ulrich Weigand | e6cc6fd | 1999-05-08 09:56:00 +0000 | [diff] [blame] | 167 | HMODULE hModule; |
Ulrich Weigand | e6cc6fd | 1999-05-08 09:56:00 +0000 | [diff] [blame] | 168 | NE_MODULE *pModule; |
| 169 | |
Alexandre Julliard | 4e951ea | 2000-11-08 22:47:53 +0000 | [diff] [blame] | 170 | hModule = GetModuleHandleA( "user32.dll" ); |
Ulrich Weigand | b4860a8 | 1999-07-24 10:15:55 +0000 | [diff] [blame] | 171 | if ( hModule ) |
Ulrich Weigand | 61439d2 | 1998-12-24 15:12:20 +0000 | [diff] [blame] | 172 | { |
Alexandre Julliard | d6c0d86 | 2000-03-24 21:38:30 +0000 | [diff] [blame] | 173 | #define GETADDR( name ) \ |
Dimitrie O. Paun | 334a42f | 2000-10-29 18:07:04 +0000 | [diff] [blame] | 174 | *(FARPROC *)&Callout.name = GetProcAddress( hModule, #name ) |
Ulrich Weigand | 61439d2 | 1998-12-24 15:12:20 +0000 | [diff] [blame] | 175 | |
Alexandre Julliard | d6c0d86 | 2000-03-24 21:38:30 +0000 | [diff] [blame] | 176 | GETADDR( PeekMessageA ); |
Alexandre Julliard | d6c0d86 | 2000-03-24 21:38:30 +0000 | [diff] [blame] | 177 | GETADDR( GetMessageA ); |
Alexandre Julliard | d6c0d86 | 2000-03-24 21:38:30 +0000 | [diff] [blame] | 178 | GETADDR( SendMessageA ); |
Alexandre Julliard | d6c0d86 | 2000-03-24 21:38:30 +0000 | [diff] [blame] | 179 | GETADDR( PostMessageA ); |
Alexandre Julliard | d6c0d86 | 2000-03-24 21:38:30 +0000 | [diff] [blame] | 180 | GETADDR( TranslateMessage ); |
Alexandre Julliard | d6c0d86 | 2000-03-24 21:38:30 +0000 | [diff] [blame] | 181 | GETADDR( DispatchMessageA ); |
| 182 | GETADDR( RedrawWindow ); |
| 183 | GETADDR( WaitForInputIdle ); |
Alexandre Julliard | 946a444 | 2000-07-30 13:50:27 +0000 | [diff] [blame] | 184 | GETADDR( MsgWaitForMultipleObjects ); |
| 185 | GETADDR( WindowFromDC ); |
Alexandre Julliard | d6c0d86 | 2000-03-24 21:38:30 +0000 | [diff] [blame] | 186 | GETADDR( MessageBoxA ); |
| 187 | GETADDR( MessageBoxW ); |
Ulrich Weigand | 61439d2 | 1998-12-24 15:12:20 +0000 | [diff] [blame] | 188 | #undef GETADDR |
| 189 | } |
Alexandre Julliard | 4e951ea | 2000-11-08 22:47:53 +0000 | [diff] [blame] | 190 | else WARN("no 32-bit USER\n"); |
Ulrich Weigand | 61439d2 | 1998-12-24 15:12:20 +0000 | [diff] [blame] | 191 | |
Alexandre Julliard | 4e951ea | 2000-11-08 22:47:53 +0000 | [diff] [blame] | 192 | pModule = NE_GetPtr( GetModuleHandle16( "USER.EXE" ) ); |
Ulrich Weigand | b4860a8 | 1999-07-24 10:15:55 +0000 | [diff] [blame] | 193 | if ( pModule ) |
Ulrich Weigand | 61439d2 | 1998-12-24 15:12:20 +0000 | [diff] [blame] | 194 | { |
| 195 | #define GETADDR( var, name, thk ) \ |
Dimitrie O. Paun | 334a42f | 2000-10-29 18:07:04 +0000 | [diff] [blame] | 196 | *(FARPROC *)&Callout.var = THUNK_GetCalloutThunk( pModule, name, \ |
| 197 | (RELAY)THUNK_CallTo16_##thk ) |
Ulrich Weigand | 61439d2 | 1998-12-24 15:12:20 +0000 | [diff] [blame] | 198 | |
Ulrich Weigand | 98c3053 | 1999-07-27 17:10:06 +0000 | [diff] [blame] | 199 | GETADDR( FinalUserInit16, "FinalUserInit", word_ ); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 200 | GETADDR( InitThreadInput16, "InitThreadInput", word_ww ); |
| 201 | GETADDR( UserYield16, "UserYield", word_ ); |
Ulrich Weigand | e562453 | 1999-03-10 14:06:53 +0000 | [diff] [blame] | 202 | GETADDR( DestroyIcon32, "DestroyIcon32", word_ww ); |
Ulrich Weigand | 979000e | 1999-12-05 02:48:53 +0000 | [diff] [blame] | 203 | GETADDR( UserSignalProc, "SignalProc32", word_lllw ); |
Ulrich Weigand | 61439d2 | 1998-12-24 15:12:20 +0000 | [diff] [blame] | 204 | #undef GETADDR |
| 205 | } |
Alexandre Julliard | 4e951ea | 2000-11-08 22:47:53 +0000 | [diff] [blame] | 206 | else WARN("no 16-bit USER\n"); |
Ulrich Weigand | 61439d2 | 1998-12-24 15:12:20 +0000 | [diff] [blame] | 207 | } |