2 * Win32s Universal Thunk API
4 * Copyright 1999 Ulrich Weigand
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "wine/winbase16.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(thunk);
54 typedef struct _UTINFO
65 static UTINFO *UT_head; /* head of Universal Thunk list */
67 typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
69 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
70 LPSTR lpszInitName, LPSTR lpszProcName,
71 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
74 VOID WINAPI UTUnRegister( HMODULE hModule );
76 /* ### start build ### */
77 extern LONG CALLBACK UTTHUNK_CallTo16_long_ll(FARPROC16,LONG,LONG);
78 /* ### stop build ### */
80 /****************************************************************************
81 * UTGlue16 (KERNEL.666) (KERNEL Wine-specific export)
83 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
88 /* Convert arguments to flat pointers */
90 if ( translationList )
91 for ( i = 0; translationList[i]; i++ )
93 LPVOID flatPtr = MapSL( translationList[i] );
94 *(LPVOID *)flatPtr = MapSL( *(SEGPTR *)flatPtr );
97 /* Call 32-bit routine */
99 return target( lpBuff, dwUserDefined );
102 /****************************************************************************
105 static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
106 LPVOID translationList[] )
108 SEGPTR segBuff, *segptrList = NULL;
112 /* Convert arguments to SEGPTRs */
114 if ( translationList )
115 for ( nList = 0; translationList[nList]; nList++ )
120 segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
123 FIXME("Unable to allocate segptrList!\n" );
127 for ( i = 0; i < nList; i++ )
128 segptrList[i] = *(SEGPTR *)translationList[i]
129 = MapLS( *(LPVOID *)translationList[i] );
132 segBuff = MapLS( lpBuff );
134 /* Call 16-bit routine */
136 retv = UTTHUNK_CallTo16_long_ll( target, segBuff, dwUserDefined );
138 /* Free temporary selectors */
144 for ( i = 0; i < nList; i++ )
145 UnMapLS( segptrList[i] );
147 HeapFree( GetProcessHeap(), 0, segptrList );
153 /****************************************************************************
156 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
157 FARPROC16 target16, FARPROC target32 )
159 static FARPROC16 UTGlue16_Segptr = NULL;
162 if ( !UTGlue16_Segptr )
164 HMODULE16 hModule = GetModuleHandle16( "KERNEL" );
165 UTGlue16_Segptr = GetProcAddress16( hModule, "UTGlue16" );
166 if ( !UTGlue16_Segptr ) return NULL;
169 ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UTINFO) );
170 if ( !ut ) return NULL;
172 ut->hModule = hModule;
173 ut->hModule16 = hModule16;
175 ut->ut16.popl_eax = 0x58;
176 ut->ut16.pushl = 0x68;
177 ut->ut16.target = (DWORD)target32;
178 ut->ut16.pushl_eax = 0x50;
179 ut->ut16.ljmp = 0xea;
180 ut->ut16.utglue16 = (DWORD)UTGlue16_Segptr;
182 ut->ut32.popl_eax = 0x58;
183 ut->ut32.pushl = 0x68;
184 ut->ut32.target = (DWORD)target16;
185 ut->ut32.pushl_eax = 0x50;
187 ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
195 /****************************************************************************
198 static void UTFree( UTINFO *ut )
202 for ( ptr = &UT_head; *ptr; ptr = &(*ptr)->next )
209 HeapFree( GetProcessHeap(), 0, ut );
212 /****************************************************************************
215 static UTINFO *UTFind( HMODULE hModule )
219 for ( ut = UT_head; ut; ut =ut->next )
220 if ( ut->hModule == hModule )
227 /****************************************************************************
228 * UTRegister (KERNEL32.@)
230 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
231 LPSTR lpszInitName, LPSTR lpszProcName,
232 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
237 FARPROC16 target16, init16;
239 /* Load 16-bit DLL and get UTProc16 entry point */
241 if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
242 || (target16 = GetProcAddress16( hModule16, lpszProcName )) == 0 )
245 /* Allocate UTINFO struct */
248 if ( (ut = UTFind( hModule )) != NULL )
251 ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
256 FreeLibrary16( hModule16 );
260 /* Call UTInit16 if present */
263 && (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
265 SEGPTR callback = MapLS( &ut->ut16 );
266 SEGPTR segBuff = MapLS( lpBuff );
268 if ( !UTTHUNK_CallTo16_long_ll( init16, callback, segBuff ) )
272 UTUnRegister( hModule );
279 /* Return 32-bit thunk */
281 *ppfn32Thunk = (FARPROC) &ut->ut32;
286 /****************************************************************************
287 * UTUnRegister (KERNEL32.@)
289 VOID WINAPI UTUnRegister( HMODULE hModule )
292 HMODULE16 hModule16 = 0;
295 ut = UTFind( hModule );
298 hModule16 = ut->hModule16;
304 FreeLibrary16( hModule16 );
307 /****************************************************************************
308 * UTInit (KERNEL.493)
310 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
312 FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );