Fixed some issues found by winapi_check.
[wine/hacks.git] / dlls / kernel / utthunk.c
blobeae510cc6584d768dd0564df63a18a83b5af1140
1 /*
2 * Win32s Universal Thunk API
4 * Copyright 1999 Ulrich Weigand
5 */
7 #include "wine/winbase16.h"
8 #include "ntddk.h"
9 #include "heap.h"
10 #include "module.h"
11 #include "callback.h"
12 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(thunk);
16 #include "pshpack1.h"
18 typedef struct
20 BYTE popl_eax;
21 BYTE pushl;
22 DWORD target;
23 BYTE pushl_eax;
24 BYTE ljmp;
25 DWORD utglue16;
27 } UT16THUNK;
29 typedef struct
31 BYTE popl_eax;
32 BYTE pushl;
33 DWORD target;
34 BYTE pushl_eax;
35 BYTE jmp;
36 DWORD utglue32;
38 } UT32THUNK;
40 #include "poppack.h"
42 typedef struct _UTINFO
44 struct _UTINFO *next;
45 HMODULE hModule;
46 HMODULE16 hModule16;
48 UT16THUNK ut16;
49 UT32THUNK ut32;
51 } UTINFO;
53 static UTINFO *UT_head; /* head of Universal Thunk list */
55 typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
57 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
58 LPSTR lpszInitName, LPSTR lpszProcName,
59 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
60 LPVOID lpBuff );
62 VOID WINAPI UTUnRegister( HMODULE hModule );
64 /* ### start build ### */
65 extern LONG CALLBACK UTTHUNK_CallTo16_long_ll(FARPROC16,LONG,LONG);
66 /* ### stop build ### */
68 /****************************************************************************
69 * UTGlue16 (KERNEL.666) (KERNEL Wine-specific export)
71 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
72 UTGLUEPROC target )
74 INT i;
76 /* Convert arguments to flat pointers */
78 if ( translationList )
79 for ( i = 0; translationList[i]; i++ )
81 LPVOID flatPtr = MapSL( translationList[i] );
82 *(LPVOID *)flatPtr = MapSL( *(SEGPTR *)flatPtr );
85 /* Call 32-bit routine */
87 return target( lpBuff, dwUserDefined );
90 /****************************************************************************
91 * UTGlue32
93 static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
94 LPVOID translationList[] )
96 SEGPTR segBuff, *segptrList = NULL;
97 INT i, nList = 0;
98 DWORD retv;
100 /* Convert arguments to SEGPTRs */
102 if ( translationList )
103 for ( nList = 0; translationList[nList]; nList++ )
106 if ( nList )
108 segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
109 if ( !segptrList )
111 FIXME("Unable to allocate segptrList!" );
112 return 0;
115 for ( i = 0; i < nList; i++ )
116 segptrList[i] = *(SEGPTR *)translationList[i]
117 = MapLS( *(LPVOID *)translationList[i] );
120 segBuff = MapLS( lpBuff );
122 /* Call 16-bit routine */
124 retv = UTTHUNK_CallTo16_long_ll( target, segBuff, dwUserDefined );
126 /* Free temporary selectors */
128 UnMapLS( segBuff );
130 if ( nList )
132 for ( i = 0; i < nList; i++ )
133 UnMapLS( segptrList[i] );
135 HeapFree( GetProcessHeap(), 0, segptrList );
138 return retv;
141 /****************************************************************************
142 * UTAlloc
144 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
145 FARPROC16 target16, FARPROC target32 )
147 static FARPROC16 UTGlue16_Segptr = NULL;
148 UTINFO *ut;
150 if ( !UTGlue16_Segptr )
152 HMODULE16 hModule = GetModuleHandle16( "KERNEL" );
153 UTGlue16_Segptr = GetProcAddress16( hModule, "UTGlue16" );
154 if ( !UTGlue16_Segptr ) return NULL;
157 ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_WINE_SEGPTR, sizeof(UTINFO) );
158 if ( !ut ) return NULL;
160 ut->hModule = hModule;
161 ut->hModule16 = hModule16;
163 ut->ut16.popl_eax = 0x58;
164 ut->ut16.pushl = 0x68;
165 ut->ut16.target = (DWORD)target32;
166 ut->ut16.pushl_eax = 0x50;
167 ut->ut16.ljmp = 0xea;
168 ut->ut16.utglue16 = (DWORD)UTGlue16_Segptr;
170 ut->ut32.popl_eax = 0x58;
171 ut->ut32.pushl = 0x68;
172 ut->ut32.target = (DWORD)target16;
173 ut->ut32.pushl_eax = 0x50;
174 ut->ut32.jmp = 0xe9;
175 ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
177 ut->next = UT_head;
178 UT_head = ut;
180 return ut;
183 /****************************************************************************
184 * UTFree
186 static void UTFree( UTINFO *ut )
188 UTINFO **ptr;
190 for ( ptr = &UT_head; *ptr; ptr = &(*ptr)->next )
191 if ( *ptr == ut )
193 *ptr = ut->next;
194 break;
197 HeapFree( GetProcessHeap(), HEAP_WINE_SEGPTR, ut );
200 /****************************************************************************
201 * UTFind
203 static UTINFO *UTFind( HMODULE hModule )
205 UTINFO *ut;
207 for ( ut = UT_head; ut; ut =ut->next )
208 if ( ut->hModule == hModule )
209 break;
211 return ut;
215 /****************************************************************************
216 * UTRegister (KERNEL32.698)
218 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
219 LPSTR lpszInitName, LPSTR lpszProcName,
220 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
221 LPVOID lpBuff )
223 UTINFO *ut;
224 HMODULE16 hModule16;
225 FARPROC16 target16, init16;
227 /* Load 16-bit DLL and get UTProc16 entry point */
229 if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
230 || (target16 = GetProcAddress16( hModule16, lpszProcName )) == 0 )
231 return FALSE;
233 /* Allocate UTINFO struct */
235 RtlAcquirePebLock();
236 if ( (ut = UTFind( hModule )) != NULL )
237 ut = NULL;
238 else
239 ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
240 RtlReleasePebLock();
242 if ( !ut )
244 FreeLibrary16( hModule16 );
245 return FALSE;
248 /* Call UTInit16 if present */
250 if ( lpszInitName
251 && (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
253 SEGPTR callback = SEGPTR_GET( &ut->ut16 );
254 SEGPTR segBuff = MapLS( lpBuff );
256 if ( !UTTHUNK_CallTo16_long_ll( init16, callback, segBuff ) )
258 UnMapLS( segBuff );
259 UTUnRegister( hModule );
260 return FALSE;
262 UnMapLS( segBuff );
265 /* Return 32-bit thunk */
267 *ppfn32Thunk = (FARPROC) &ut->ut32;
269 return TRUE;
272 /****************************************************************************
273 * UTUnRegister (KERNEL32.699)
275 VOID WINAPI UTUnRegister( HMODULE hModule )
277 UTINFO *ut;
278 HMODULE16 hModule16 = 0;
280 RtlAcquirePebLock();
281 ut = UTFind( hModule );
282 if ( !ut )
284 hModule16 = ut->hModule16;
285 UTFree( ut );
287 RtlReleasePebLock();
289 if ( hModule16 )
290 FreeLibrary16( hModule16 );
293 /****************************************************************************
294 * UTInit16 (KERNEL.493)
296 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
298 FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
299 return 0;