Use the HEAP_WINE_SEGPTR flag to specify allocations on the segptr heap.
[wine/testsucceed.git] / dlls / kernel / utthunk.c
bloba4ff965e63607d3399a98f4217cbf26c00e0b7db
1 /*
2 * Win32s Universal Thunk API
4 * Copyright 1999 Ulrich Weigand
5 */
7 #include "wine/winbase16.h"
8 #include "heap.h"
9 #include "module.h"
10 #include "selectors.h"
11 #include "callback.h"
12 #include "process.h"
13 #include "debugtools.h"
15 DEFAULT_DEBUG_CHANNEL(thunk);
17 #include "pshpack1.h"
19 typedef struct
21 BYTE popl_eax;
22 BYTE pushl;
23 DWORD target;
24 BYTE pushl_eax;
25 BYTE ljmp;
26 DWORD utglue16;
28 } UT16THUNK;
30 typedef struct
32 BYTE popl_eax;
33 BYTE pushl;
34 DWORD target;
35 BYTE pushl_eax;
36 BYTE jmp;
37 DWORD utglue32;
39 } UT32THUNK;
41 #include "poppack.h"
43 typedef struct _UTINFO
45 struct _UTINFO *next;
46 HMODULE hModule;
47 HMODULE16 hModule16;
49 UT16THUNK ut16;
50 UT32THUNK ut32;
52 } UTINFO;
54 typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
56 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
57 LPSTR lpszInitName, LPSTR lpszProcName,
58 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
59 LPVOID lpBuff );
61 VOID WINAPI UTUnRegister( HMODULE hModule );
63 /* ### start build ### */
64 extern LONG CALLBACK UTTHUNK_CallTo16_long_ll(FARPROC16,LONG,LONG);
65 /* ### stop build ### */
67 /****************************************************************************
68 * UTGlue16 (WPROCS.*)
70 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
71 UTGLUEPROC target )
73 INT i;
75 /* Convert arguments to flat pointers */
77 if ( translationList )
78 for ( i = 0; translationList[i]; i++ )
80 LPVOID flatPtr = PTR_SEG_TO_LIN( translationList[i] );
81 *(LPVOID *)flatPtr = PTR_SEG_TO_LIN( *(SEGPTR *)flatPtr );
84 /* Call 32-bit routine */
86 return target( lpBuff, dwUserDefined );
89 /****************************************************************************
90 * UTGlue32
92 static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
93 LPVOID translationList[] )
95 SEGPTR segBuff, *segptrList = NULL;
96 INT i, nList = 0;
97 DWORD retv;
99 /* Convert arguments to SEGPTRs */
101 if ( translationList )
102 for ( nList = 0; translationList[nList]; nList++ )
105 if ( nList )
107 segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
108 if ( !segptrList )
110 FIXME("Unable to allocate segptrList!" );
111 return 0;
114 for ( i = 0; i < nList; i++ )
115 segptrList[i] = *(SEGPTR *)translationList[i]
116 = MapLS( *(LPVOID *)translationList[i] );
119 segBuff = MapLS( lpBuff );
121 /* Call 16-bit routine */
123 retv = UTTHUNK_CallTo16_long_ll( target, segBuff, dwUserDefined );
125 /* Free temporary selectors */
127 UnMapLS( segBuff );
129 if ( nList )
131 for ( i = 0; i < nList; i++ )
132 UnMapLS( segptrList[i] );
134 HeapFree( GetProcessHeap(), 0, segptrList );
137 return retv;
140 /****************************************************************************
141 * UTAlloc
143 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
144 FARPROC16 target16, FARPROC target32 )
146 static FARPROC16 UTGlue16_Segptr = NULL;
147 UTINFO *ut;
149 if ( !UTGlue16_Segptr )
151 HMODULE16 hModule = GetModuleHandle16( "WPROCS" );
152 int ordinal = NE_GetOrdinal( hModule, "UTGlue16" );
153 if ( hModule && ordinal )
154 UTGlue16_Segptr = NE_GetEntryPoint( hModule, ordinal );
156 if ( !UTGlue16_Segptr ) return NULL;
159 ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_WINE_SEGPTR, sizeof(UTINFO) );
160 if ( !ut ) return NULL;
162 ut->hModule = hModule;
163 ut->hModule16 = hModule16;
165 ut->ut16.popl_eax = 0x58;
166 ut->ut16.pushl = 0x68;
167 ut->ut16.target = (DWORD)target32;
168 ut->ut16.pushl_eax = 0x50;
169 ut->ut16.ljmp = 0xea;
170 ut->ut16.utglue16 = (DWORD)UTGlue16_Segptr;
172 ut->ut32.popl_eax = 0x58;
173 ut->ut32.pushl = 0x68;
174 ut->ut32.target = (DWORD)target16;
175 ut->ut32.pushl_eax = 0x50;
176 ut->ut32.jmp = 0xe9;
177 ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
179 ut->next = PROCESS_Current()->UTState;
180 PROCESS_Current()->UTState = ut;
182 return ut;
185 /****************************************************************************
186 * UTFree
188 static void UTFree( UTINFO *ut )
190 UTINFO **ptr;
192 for ( ptr = &PROCESS_Current()->UTState; *ptr; ptr = &(*ptr)->next )
193 if ( *ptr == ut )
195 *ptr = ut->next;
196 break;
199 HeapFree( GetProcessHeap(), HEAP_WINE_SEGPTR, ut );
202 /****************************************************************************
203 * UTFind
205 static UTINFO *UTFind( HMODULE hModule )
207 UTINFO *ut;
209 for ( ut = PROCESS_Current()->UTState; ut; ut =ut->next )
210 if ( ut->hModule == hModule )
211 break;
213 return ut;
217 /****************************************************************************
218 * UTRegister (KERNEL32.697)
220 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
221 LPSTR lpszInitName, LPSTR lpszProcName,
222 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
223 LPVOID lpBuff )
225 UTINFO *ut;
226 HMODULE16 hModule16;
227 FARPROC16 target16, init16;
229 /* Load 16-bit DLL and get UTProc16 entry point */
231 if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
232 || (target16 = GetProcAddress16( hModule16, lpszProcName )) == 0 )
233 return FALSE;
235 /* Allocate UTINFO struct */
237 EnterCriticalSection( &PROCESS_Current()->crit_section );
238 if ( (ut = UTFind( hModule )) != NULL )
239 ut = NULL;
240 else
241 ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
242 LeaveCriticalSection( &PROCESS_Current()->crit_section );
244 if ( !ut )
246 FreeLibrary16( hModule16 );
247 return FALSE;
250 /* Call UTInit16 if present */
252 if ( lpszInitName
253 && (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
255 SEGPTR callback = SEGPTR_GET( &ut->ut16 );
256 SEGPTR segBuff = MapLS( lpBuff );
258 if ( !UTTHUNK_CallTo16_long_ll( init16, callback, segBuff ) )
260 UnMapLS( segBuff );
261 UTUnRegister( hModule );
262 return FALSE;
264 UnMapLS( segBuff );
267 /* Return 32-bit thunk */
269 *ppfn32Thunk = (FARPROC) &ut->ut32;
271 return TRUE;
274 /****************************************************************************
275 * UTUnRegister (KERNEL32.698)
277 VOID WINAPI UTUnRegister( HMODULE hModule )
279 UTINFO *ut;
280 HMODULE16 hModule16 = 0;
282 EnterCriticalSection( &PROCESS_Current()->crit_section );
283 ut = UTFind( hModule );
284 if ( !ut )
286 hModule16 = ut->hModule16;
287 UTFree( ut );
289 LeaveCriticalSection( &PROCESS_Current()->crit_section );
291 if ( hModule16 )
292 FreeLibrary16( hModule16 );
295 /****************************************************************************
296 * UTInit16 (KERNEL.494)
298 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
300 FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
301 return 0;