New files to support load order and partial stubs for elfdlls.
[wine/wine-kai.git] / relay32 / utthunk.c
blob9be4261dcd3f065b916456a723ff4d4ab502d555
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 #pragma pack(1)
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 #pragma pack(4)
42 typedef struct _UTINFO
44 struct _UTINFO *next;
45 HMODULE hModule;
46 HMODULE16 hModule16;
48 UT16THUNK ut16;
49 UT32THUNK ut32;
51 } UTINFO;
53 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
54 LPSTR lpszInitName, LPSTR lpszProcName,
55 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
56 LPVOID lpBuff );
58 VOID WINAPI UTUnRegister( HMODULE hModule );
61 /****************************************************************************
62 * UTGlue16 (WPROCS.*)
64 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR translationList[],
65 DWORD (CALLBACK *target)( LPVOID lpBuff, DWORD dwUserDefined ) )
67 INT i;
69 /* Convert arguments to flat pointers */
71 if ( translationList )
72 for ( i = 0; translationList[i]; i++ )
74 LPVOID flatPtr = PTR_SEG_TO_LIN( translationList[i] );
75 *(LPVOID *)flatPtr = PTR_SEG_TO_LIN( *(SEGPTR *)flatPtr );
78 /* Call 32-bit routine */
80 return target( lpBuff, dwUserDefined );
83 /****************************************************************************
84 * UTGlue32
86 DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
87 LPVOID translationList[] )
89 SEGPTR segBuff, *segptrList = NULL;
90 INT i, nList = 0;
91 DWORD retv;
93 /* Convert arguments to SEGPTRs */
95 if ( translationList )
96 for ( nList = 0; translationList[nList]; nList++ )
99 if ( nList )
101 segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
102 if ( !segptrList )
104 FIXME( thunk, "Unable to allocate segptrList!" );
105 return 0;
108 for ( i = 0; i < nList; i++ )
109 segptrList[i] = *(SEGPTR *)translationList[i]
110 = MapLS( *(LPVOID *)translationList[i] );
113 segBuff = MapLS( lpBuff );
115 /* Call 16-bit routine */
117 retv = Callbacks->CallUTProc( target, segBuff, dwUserDefined );
119 /* Free temporary selectors */
121 UnMapLS( segBuff );
123 if ( nList )
125 for ( i = 0; i < nList; i++ )
126 UnMapLS( segptrList[i] );
128 HeapFree( GetProcessHeap(), 0, segptrList );
131 return retv;
134 /****************************************************************************
135 * UTAlloc
137 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
138 FARPROC16 target16, FARPROC target32 )
140 UTINFO *ut = HeapAlloc( SegptrHeap, HEAP_ZERO_MEMORY, sizeof(UTINFO) );
141 if ( !ut ) return NULL;
143 ut->hModule = hModule;
144 ut->hModule16 = hModule16;
146 ut->ut16.popl_eax = 0x58;
147 ut->ut16.pushl = 0x68;
148 ut->ut16.target = (DWORD)target32;
149 ut->ut16.pushl_eax = 0x50;
150 ut->ut16.ljmp = 0xea;
151 ut->ut16.utglue16 = (DWORD)MODULE_GetWndProcEntry16( "UTGlue16" );
153 ut->ut32.popl_eax = 0x58;
154 ut->ut32.pushl = 0x68;
155 ut->ut32.target = (DWORD)target16;
156 ut->ut32.pushl_eax = 0x50;
157 ut->ut32.jmp = 0xe9;
158 ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
160 ut->next = PROCESS_Current()->UTState;
161 PROCESS_Current()->UTState = ut;
163 return ut;
166 /****************************************************************************
167 * UTFree
169 static void UTFree( UTINFO *ut )
171 UTINFO **ptr;
173 for ( ptr = &PROCESS_Current()->UTState; *ptr; ptr = &(*ptr)->next )
174 if ( *ptr == ut )
176 *ptr = ut->next;
177 break;
180 HeapFree( SegptrHeap, 0, ut );
183 /****************************************************************************
184 * UTFind
186 static UTINFO *UTFind( HMODULE hModule )
188 UTINFO *ut;
190 for ( ut = PROCESS_Current()->UTState; ut; ut =ut->next )
191 if ( ut->hModule == hModule )
192 break;
194 return ut;
198 /****************************************************************************
199 * UTRegister (KERNEL32.697)
201 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
202 LPSTR lpszInitName, LPSTR lpszProcName,
203 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
204 LPVOID lpBuff )
206 UTINFO *ut;
207 HMODULE16 hModule16;
208 FARPROC16 target16, init16;
210 /* Load 16-bit DLL and get UTProc16 entry point */
212 if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
213 || (target16 = WIN32_GetProcAddress16( hModule16, lpszProcName )) == 0 )
214 return FALSE;
216 /* Allocate UTINFO struct */
218 EnterCriticalSection( &PROCESS_Current()->crit_section );
219 if ( (ut = UTFind( hModule )) != NULL )
220 ut = NULL;
221 else
222 ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
223 LeaveCriticalSection( &PROCESS_Current()->crit_section );
225 if ( !ut )
227 FreeLibrary16( hModule16 );
228 return FALSE;
231 /* Call UTInit16 if present */
233 if ( lpszInitName
234 && (init16 = WIN32_GetProcAddress16( hModule16, lpszInitName )) != 0 )
236 SEGPTR callback = SEGPTR_GET( &ut->ut16 );
237 SEGPTR segBuff = MapLS( lpBuff );
239 if ( !Callbacks->CallUTProc( init16, callback, segBuff ) )
241 UnMapLS( segBuff );
242 UTUnRegister( hModule );
243 return FALSE;
245 UnMapLS( segBuff );
248 /* Return 32-bit thunk */
250 *ppfn32Thunk = (FARPROC) &ut->ut32;
252 return TRUE;
255 /****************************************************************************
256 * UTUnRegister (KERNEL32.698)
258 VOID WINAPI UTUnRegister( HMODULE hModule )
260 UTINFO *ut;
261 HMODULE16 hModule16 = 0;
263 EnterCriticalSection( &PROCESS_Current()->crit_section );
264 ut = UTFind( hModule );
265 if ( !ut )
267 hModule16 = ut->hModule16;
268 UTFree( ut );
270 LeaveCriticalSection( &PROCESS_Current()->crit_section );
272 if ( hModule16 )
273 FreeLibrary16( hModule16 );
276 /****************************************************************************
277 * UTInit16 (KERNEL.494)
279 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
281 FIXME( thunk, "(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
282 return 0;