2 * Win32s Universal Thunk API
4 * Copyright 1999 Ulrich Weigand
7 #include "wine/winbase16.h"
11 #include "selectors.h"
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(thunk);
44 typedef struct _UTINFO
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,
62 VOID WINAPI UTUnRegister( HMODULE hModule );
64 /* ### start build ### */
65 extern LONG CALLBACK UTTHUNK_CallTo16_long_ll(FARPROC16,LONG,LONG);
66 /* ### stop build ### */
68 /****************************************************************************
71 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
76 /* Convert arguments to flat pointers */
78 if ( translationList )
79 for ( i = 0; translationList[i]; i++ )
81 LPVOID flatPtr = PTR_SEG_TO_LIN( translationList[i] );
82 *(LPVOID *)flatPtr = PTR_SEG_TO_LIN( *(SEGPTR *)flatPtr );
85 /* Call 32-bit routine */
87 return target( lpBuff, dwUserDefined );
90 /****************************************************************************
93 static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
94 LPVOID translationList[] )
96 SEGPTR segBuff, *segptrList = NULL;
100 /* Convert arguments to SEGPTRs */
102 if ( translationList )
103 for ( nList = 0; translationList[nList]; nList++ )
108 segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
111 FIXME("Unable to allocate segptrList!" );
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 */
132 for ( i = 0; i < nList; i++ )
133 UnMapLS( segptrList[i] );
135 HeapFree( GetProcessHeap(), 0, segptrList );
141 /****************************************************************************
144 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
145 FARPROC16 target16, FARPROC target32 )
147 static FARPROC16 UTGlue16_Segptr = NULL;
150 if ( !UTGlue16_Segptr )
152 HMODULE16 hModule = GetModuleHandle16( "WPROCS" );
153 int ordinal = NE_GetOrdinal( hModule, "UTGlue16" );
154 if ( hModule && ordinal )
155 UTGlue16_Segptr = NE_GetEntryPoint( hModule, ordinal );
157 if ( !UTGlue16_Segptr ) return NULL;
160 ut = HeapAlloc( SegptrHeap, HEAP_ZERO_MEMORY, sizeof(UTINFO) );
161 if ( !ut ) return NULL;
163 ut->hModule = hModule;
164 ut->hModule16 = hModule16;
166 ut->ut16.popl_eax = 0x58;
167 ut->ut16.pushl = 0x68;
168 ut->ut16.target = (DWORD)target32;
169 ut->ut16.pushl_eax = 0x50;
170 ut->ut16.ljmp = 0xea;
171 ut->ut16.utglue16 = (DWORD)UTGlue16_Segptr;
173 ut->ut32.popl_eax = 0x58;
174 ut->ut32.pushl = 0x68;
175 ut->ut32.target = (DWORD)target16;
176 ut->ut32.pushl_eax = 0x50;
178 ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
180 ut->next = PROCESS_Current()->UTState;
181 PROCESS_Current()->UTState = ut;
186 /****************************************************************************
189 static void UTFree( UTINFO *ut )
193 for ( ptr = &PROCESS_Current()->UTState; *ptr; ptr = &(*ptr)->next )
200 HeapFree( SegptrHeap, 0, ut );
203 /****************************************************************************
206 static UTINFO *UTFind( HMODULE hModule )
210 for ( ut = PROCESS_Current()->UTState; ut; ut =ut->next )
211 if ( ut->hModule == hModule )
218 /****************************************************************************
219 * UTRegister (KERNEL32.697)
221 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
222 LPSTR lpszInitName, LPSTR lpszProcName,
223 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
228 FARPROC16 target16, init16;
230 /* Load 16-bit DLL and get UTProc16 entry point */
232 if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
233 || (target16 = WIN32_GetProcAddress16( hModule16, lpszProcName )) == 0 )
236 /* Allocate UTINFO struct */
238 EnterCriticalSection( &PROCESS_Current()->crit_section );
239 if ( (ut = UTFind( hModule )) != NULL )
242 ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
243 LeaveCriticalSection( &PROCESS_Current()->crit_section );
247 FreeLibrary16( hModule16 );
251 /* Call UTInit16 if present */
254 && (init16 = WIN32_GetProcAddress16( hModule16, lpszInitName )) != 0 )
256 SEGPTR callback = SEGPTR_GET( &ut->ut16 );
257 SEGPTR segBuff = MapLS( lpBuff );
259 if ( !UTTHUNK_CallTo16_long_ll( init16, callback, segBuff ) )
262 UTUnRegister( hModule );
268 /* Return 32-bit thunk */
270 *ppfn32Thunk = (FARPROC) &ut->ut32;
275 /****************************************************************************
276 * UTUnRegister (KERNEL32.698)
278 VOID WINAPI UTUnRegister( HMODULE hModule )
281 HMODULE16 hModule16 = 0;
283 EnterCriticalSection( &PROCESS_Current()->crit_section );
284 ut = UTFind( hModule );
287 hModule16 = ut->hModule16;
290 LeaveCriticalSection( &PROCESS_Current()->crit_section );
293 FreeLibrary16( hModule16 );
296 /****************************************************************************
297 * UTInit16 (KERNEL.494)
299 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
301 FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );