Added support for special treatments (use 2 or more fonts, codepage
[wine.git] / if1632 / thunk.c
blobf598752688f723574590f150d598a503b569cb88
1 /*
2 * Emulator thunks
4 * Copyright 1996, 1997 Alexandre Julliard
5 * Copyright 1998 Ulrich Weigand
6 */
8 #include <string.h>
9 #include "wine/winbase16.h"
10 #include "callback.h"
11 #include "builtin16.h"
12 #include "heap.h"
13 #include "module.h"
14 #include "neexe.h"
15 #include "stackframe.h"
16 #include "selectors.h"
17 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(thunk);
22 /* List of the 16-bit callback functions. This list is used */
23 /* by the build program to generate the file if1632/callto16.S */
25 /* ### start build ### */
26 extern WORD CALLBACK THUNK_CallTo16_word_ (FARPROC16);
27 extern WORD CALLBACK THUNK_CallTo16_word_l (FARPROC16,LONG);
28 extern LONG CALLBACK THUNK_CallTo16_long_l (FARPROC16,LONG);
29 extern WORD CALLBACK THUNK_CallTo16_word_lllw (FARPROC16,LONG,LONG,LONG,WORD);
30 extern WORD CALLBACK THUNK_CallTo16_word_lwww (FARPROC16,LONG,WORD,WORD,WORD);
31 extern LONG CALLBACK THUNK_CallTo16_long_wwwl (FARPROC16,WORD,WORD,WORD,LONG);
32 extern WORD CALLBACK THUNK_CallTo16_word_lwwww(FARPROC16,LONG,WORD,WORD,WORD,WORD);
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);
37 /* ### stop build ### */
39 static THUNK *firstThunk = NULL;
41 CALLOUT_TABLE Callout = { 0 };
44 /***********************************************************************
45 * THUNK_Alloc
47 FARPROC THUNK_Alloc( FARPROC16 func, RELAY relay )
49 HANDLE16 hSeg;
50 NE_MODULE *pModule;
51 THUNK *thunk;
53 /* NULL maps to NULL */
54 if ( !func ) return NULL;
56 /*
57 * If we got an 16-bit built-in API entry point, retrieve the Wine
58 * 32-bit handler for that API routine.
60 * NOTE: For efficiency reasons, we only check whether the selector
61 * of 'func' points to the code segment of a built-in module.
62 * It might be theoretically possible that the offset is such
63 * that 'func' does not point, in fact, to an API entry point.
64 * In this case, however, the pointer is corrupt anyway.
66 hSeg = GlobalHandle16( SELECTOROF( func ) );
67 pModule = NE_GetPtr( FarGetOwner16( hSeg ) );
69 if ( pModule && (pModule->flags & NE_FFLAGS_BUILTIN)
70 && NE_SEG_TABLE(pModule)[0].hSeg == hSeg )
72 FARPROC proc = (FARPROC)((ENTRYPOINT16 *)PTR_SEG_TO_LIN( func ))->target;
74 TRACE( "(%04x:%04x, %p) -> built-in API %p\n",
75 SELECTOROF( func ), OFFSETOF( func ), relay, proc );
76 return proc;
79 /* Otherwise, we need to alloc a thunk */
80 thunk = HeapAlloc( GetProcessHeap(), 0, sizeof(*thunk) );
81 if (thunk)
83 thunk->popl_eax = 0x58;
84 thunk->pushl_func = 0x68;
85 thunk->proc = func;
86 thunk->pushl_eax = 0x50;
87 thunk->jmp = 0xe9;
88 thunk->relay = (RELAY)((char *)relay - (char *)(&thunk->next));
89 thunk->magic = CALLTO16_THUNK_MAGIC;
90 thunk->next = firstThunk;
91 firstThunk = thunk;
94 TRACE( "(%04x:%04x, %p) -> allocated thunk %p\n",
95 SELECTOROF( func ), OFFSETOF( func ), relay, thunk );
96 return (FARPROC)thunk;
99 /***********************************************************************
100 * THUNK_Free
102 void THUNK_Free( FARPROC thunk )
104 THUNK *t = (THUNK*)thunk;
105 if ( !t || IsBadReadPtr( t, sizeof(*t) )
106 || t->magic != CALLTO16_THUNK_MAGIC )
107 return;
109 if (HEAP_IsInsideHeap( GetProcessHeap(), 0, t ))
111 THUNK **prev = &firstThunk;
112 while (*prev && (*prev != t)) prev = &(*prev)->next;
113 if (*prev)
115 *prev = t->next;
116 HeapFree( GetProcessHeap(), 0, t );
117 return;
120 ERR("invalid thunk addr %p\n", thunk );
121 return;
125 /***********************************************************************
126 * THUNK_GetCalloutThunk
128 * Retrieve API entry point with given name from given module.
129 * If module is builtin, return the 32-bit entry point, otherwise
130 * create a 32->16 thunk to the 16-bit entry point, using the
131 * given relay code.
134 static FARPROC THUNK_GetCalloutThunk( NE_MODULE *pModule, LPSTR name, RELAY relay )
136 FARPROC16 proc = WIN32_GetProcAddress16( pModule->self, name );
137 if ( !proc ) return 0;
139 if ( pModule->flags & NE_FFLAGS_BUILTIN )
140 return (FARPROC)((ENTRYPOINT16 *)PTR_SEG_TO_LIN( proc ))->target;
141 else
142 return (FARPROC)THUNK_Alloc( proc, relay );
145 /***********************************************************************
146 * THUNK_InitCallout
148 void THUNK_InitCallout(void)
150 HMODULE hModule;
151 NE_MODULE *pModule;
153 hModule = LoadLibraryA( "user32.dll" );
154 if ( hModule )
156 #define GETADDR( name ) \
157 *(FARPROC *)&Callout.##name = GetProcAddress( hModule, #name )
159 GETADDR( PeekMessageA );
160 GETADDR( GetMessageA );
161 GETADDR( SendMessageA );
162 GETADDR( PostMessageA );
163 GETADDR( PostThreadMessageA );
164 GETADDR( TranslateMessage );
165 GETADDR( DispatchMessageA );
166 GETADDR( RedrawWindow );
167 GETADDR( WaitForInputIdle );
168 GETADDR( MsgWaitForMultipleObjects );
169 GETADDR( WindowFromDC );
170 GETADDR( GetForegroundWindow );
171 GETADDR( IsChild );
172 GETADDR( MessageBoxA );
173 GETADDR( MessageBoxW );
174 #undef GETADDR
177 pModule = NE_GetPtr( LoadLibrary16( "USER.EXE" ) );
178 if ( pModule )
180 #define GETADDR( var, name, thk ) \
181 *(FARPROC *)&Callout.##var = THUNK_GetCalloutThunk( pModule, name, \
182 (RELAY)THUNK_CallTo16_##thk )
184 GETADDR( PostAppMessage16, "PostAppMessage", word_wwwl );
185 GETADDR( FinalUserInit16, "FinalUserInit", word_ );
186 GETADDR( InitThreadInput16, "InitThreadInput", word_ww );
187 GETADDR( UserYield16, "UserYield", word_ );
188 GETADDR( DestroyIcon32, "DestroyIcon32", word_ww );
189 GETADDR( UserSignalProc, "SignalProc32", word_lllw );
191 #undef GETADDR