New debug scheme with explicit debug channels declaration.
[wine.git] / relay32 / utthunk.c
blob139ba3343c5ee0fedb104086473b40619875a276
1 /*
2 * Win32s Universal Thunk API
4 * Copyright 1999 Ulrich Weigand
5 */
7 #include "windef.h"
8 #include "heap.h"
9 #include "module.h"
10 #include "selectors.h"
11 #include "callback.h"
12 #include "process.h"
13 #include "debug.h"
14 #include "debugstr.h"
16 DEFAULT_DEBUG_CHANNEL(thunk)
18 #pragma pack(1)
20 typedef struct
22 BYTE popl_eax;
23 BYTE pushl;
24 DWORD target;
25 BYTE pushl_eax;
26 BYTE ljmp;
27 DWORD utglue16;
29 } UT16THUNK;
31 typedef struct
33 BYTE popl_eax;
34 BYTE pushl;
35 DWORD target;
36 BYTE pushl_eax;
37 BYTE jmp;
38 DWORD utglue32;
40 } UT32THUNK;
42 #pragma pack(4)
44 typedef struct _UTINFO
46 struct _UTINFO *next;
47 HMODULE hModule;
48 HMODULE16 hModule16;
50 UT16THUNK ut16;
51 UT32THUNK ut32;
53 } UTINFO;
55 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
56 LPSTR lpszInitName, LPSTR lpszProcName,
57 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
58 LPVOID lpBuff );
60 VOID WINAPI UTUnRegister( HMODULE hModule );
63 /****************************************************************************
64 * UTGlue16 (WPROCS.*)
66 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR translationList[],
67 DWORD (CALLBACK *target)( LPVOID lpBuff, DWORD dwUserDefined ) )
69 INT i;
71 /* Convert arguments to flat pointers */
73 if ( translationList )
74 for ( i = 0; translationList[i]; i++ )
76 LPVOID flatPtr = PTR_SEG_TO_LIN( translationList[i] );
77 *(LPVOID *)flatPtr = PTR_SEG_TO_LIN( *(SEGPTR *)flatPtr );
80 /* Call 32-bit routine */
82 return target( lpBuff, dwUserDefined );
85 /****************************************************************************
86 * UTGlue32
88 DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
89 LPVOID translationList[] )
91 SEGPTR segBuff, *segptrList = NULL;
92 INT i, nList = 0;
93 DWORD retv;
95 /* Convert arguments to SEGPTRs */
97 if ( translationList )
98 for ( nList = 0; translationList[nList]; nList++ )
101 if ( nList )
103 segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
104 if ( !segptrList )
106 FIXME( thunk, "Unable to allocate segptrList!" );
107 return 0;
110 for ( i = 0; i < nList; i++ )
111 segptrList[i] = *(SEGPTR *)translationList[i]
112 = MapLS( *(LPVOID *)translationList[i] );
115 segBuff = MapLS( lpBuff );
117 /* Call 16-bit routine */
119 retv = Callbacks->CallUTProc( target, segBuff, dwUserDefined );
121 /* Free temporary selectors */
123 UnMapLS( segBuff );
125 if ( nList )
127 for ( i = 0; i < nList; i++ )
128 UnMapLS( segptrList[i] );
130 HeapFree( GetProcessHeap(), 0, segptrList );
133 return retv;
136 /****************************************************************************
137 * UTAlloc
139 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
140 FARPROC16 target16, FARPROC target32 )
142 UTINFO *ut = HeapAlloc( SegptrHeap, HEAP_ZERO_MEMORY, sizeof(UTINFO) );
143 if ( !ut ) return NULL;
145 ut->hModule = hModule;
146 ut->hModule16 = hModule16;
148 ut->ut16.popl_eax = 0x58;
149 ut->ut16.pushl = 0x68;
150 ut->ut16.target = (DWORD)target32;
151 ut->ut16.pushl_eax = 0x50;
152 ut->ut16.ljmp = 0xea;
153 ut->ut16.utglue16 = (DWORD)MODULE_GetWndProcEntry16( "UTGlue16" );
155 ut->ut32.popl_eax = 0x58;
156 ut->ut32.pushl = 0x68;
157 ut->ut32.target = (DWORD)target16;
158 ut->ut32.pushl_eax = 0x50;
159 ut->ut32.jmp = 0xe9;
160 ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
162 ut->next = PROCESS_Current()->UTState;
163 PROCESS_Current()->UTState = ut;
165 return ut;
168 /****************************************************************************
169 * UTFree
171 static void UTFree( UTINFO *ut )
173 UTINFO **ptr;
175 for ( ptr = &PROCESS_Current()->UTState; *ptr; ptr = &(*ptr)->next )
176 if ( *ptr == ut )
178 *ptr = ut->next;
179 break;
182 HeapFree( SegptrHeap, 0, ut );
185 /****************************************************************************
186 * UTFind
188 static UTINFO *UTFind( HMODULE hModule )
190 UTINFO *ut;
192 for ( ut = PROCESS_Current()->UTState; ut; ut =ut->next )
193 if ( ut->hModule == hModule )
194 break;
196 return ut;
200 /****************************************************************************
201 * UTRegister (KERNEL32.697)
203 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
204 LPSTR lpszInitName, LPSTR lpszProcName,
205 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
206 LPVOID lpBuff )
208 UTINFO *ut;
209 HMODULE16 hModule16;
210 FARPROC16 target16, init16;
212 /* Load 16-bit DLL and get UTProc16 entry point */
214 if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
215 || (target16 = WIN32_GetProcAddress16( hModule16, lpszProcName )) == 0 )
216 return FALSE;
218 /* Allocate UTINFO struct */
220 EnterCriticalSection( &PROCESS_Current()->crit_section );
221 if ( (ut = UTFind( hModule )) != NULL )
222 ut = NULL;
223 else
224 ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
225 LeaveCriticalSection( &PROCESS_Current()->crit_section );
227 if ( !ut )
229 FreeLibrary16( hModule16 );
230 return FALSE;
233 /* Call UTInit16 if present */
235 if ( lpszInitName
236 && (init16 = WIN32_GetProcAddress16( hModule16, lpszInitName )) != 0 )
238 SEGPTR callback = SEGPTR_GET( &ut->ut16 );
239 SEGPTR segBuff = MapLS( lpBuff );
241 if ( !Callbacks->CallUTProc( init16, callback, segBuff ) )
243 UnMapLS( segBuff );
244 UTUnRegister( hModule );
245 return FALSE;
247 UnMapLS( segBuff );
250 /* Return 32-bit thunk */
252 *ppfn32Thunk = (FARPROC) &ut->ut32;
254 return TRUE;
257 /****************************************************************************
258 * UTUnRegister (KERNEL32.698)
260 VOID WINAPI UTUnRegister( HMODULE hModule )
262 UTINFO *ut;
263 HMODULE16 hModule16 = 0;
265 EnterCriticalSection( &PROCESS_Current()->crit_section );
266 ut = UTFind( hModule );
267 if ( !ut )
269 hModule16 = ut->hModule16;
270 UTFree( ut );
272 LeaveCriticalSection( &PROCESS_Current()->crit_section );
274 if ( hModule16 )
275 FreeLibrary16( hModule16 );
278 /****************************************************************************
279 * UTInit16 (KERNEL.494)
281 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
283 FIXME( thunk, "(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
284 return 0;