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
23 #include "wine/winbase16.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(thunk);
60 typedef struct _UTINFO
71 static UTINFO *UT_head; /* head of Universal Thunk list */
73 typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
75 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
76 LPSTR lpszInitName, LPSTR lpszProcName,
77 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
80 VOID WINAPI UTUnRegister( HMODULE hModule );
83 /****************************************************************************
84 * UTGlue16 (KERNEL.666) (KERNEL Wine-specific export)
86 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
91 /* Convert arguments to flat pointers */
93 if ( translationList )
94 for ( i = 0; translationList[i]; i++ )
96 LPVOID flatPtr = MapSL( translationList[i] );
97 *(LPVOID *)flatPtr = MapSL( *(SEGPTR *)flatPtr );
100 /* Call 32-bit routine */
102 return target( lpBuff, dwUserDefined );
105 /****************************************************************************
108 static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
109 LPVOID translationList[] )
111 SEGPTR segBuff, *segptrList = NULL;
116 /* Convert arguments to SEGPTRs */
118 if ( translationList )
119 for ( nList = 0; translationList[nList]; nList++ )
124 segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
127 FIXME("Unable to allocate segptrList!\n" );
131 for ( i = 0; i < nList; i++ )
132 segptrList[i] = *(SEGPTR *)translationList[i]
133 = MapLS( *(LPVOID *)translationList[i] );
136 segBuff = MapLS( lpBuff );
138 /* Call 16-bit routine */
140 args[3] = SELECTOROF(segBuff);
141 args[2] = OFFSETOF(segBuff);
142 args[1] = HIWORD(dwUserDefined);
143 args[0] = LOWORD(dwUserDefined);
144 WOWCallback16Ex( (DWORD)target, WCB16_PASCAL, sizeof(args), args, &retv );
146 /* Free temporary selectors */
152 for ( i = 0; i < nList; i++ )
153 UnMapLS( segptrList[i] );
155 HeapFree( GetProcessHeap(), 0, segptrList );
161 /****************************************************************************
164 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
165 FARPROC16 target16, FARPROC target32 )
167 static FARPROC16 UTGlue16_Segptr = NULL;
170 if ( !UTGlue16_Segptr )
172 HMODULE16 hModule = GetModuleHandle16( "KERNEL" );
173 UTGlue16_Segptr = GetProcAddress16( hModule, "UTGlue16" );
174 if ( !UTGlue16_Segptr ) return NULL;
177 ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UTINFO) );
178 if ( !ut ) return NULL;
180 ut->hModule = hModule;
181 ut->hModule16 = hModule16;
183 ut->ut16.popl_eax = 0x58;
184 ut->ut16.pushl = 0x68;
185 ut->ut16.target = (DWORD)target32;
186 ut->ut16.pushl_eax = 0x50;
187 ut->ut16.ljmp = 0xea;
188 ut->ut16.utglue16 = (DWORD)UTGlue16_Segptr;
190 ut->ut32.popl_eax = 0x58;
191 ut->ut32.pushl = 0x68;
192 ut->ut32.target = (DWORD)target16;
193 ut->ut32.pushl_eax = 0x50;
195 ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
203 /****************************************************************************
206 static void UTFree( UTINFO *ut )
210 for ( ptr = &UT_head; *ptr; ptr = &(*ptr)->next )
217 HeapFree( GetProcessHeap(), 0, ut );
220 /****************************************************************************
223 static UTINFO *UTFind( HMODULE hModule )
227 for ( ut = UT_head; ut; ut =ut->next )
228 if ( ut->hModule == hModule )
235 /****************************************************************************
236 * UTRegister (KERNEL32.@)
238 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
239 LPSTR lpszInitName, LPSTR lpszProcName,
240 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
245 FARPROC16 target16, init16;
247 /* Load 16-bit DLL and get UTProc16 entry point */
249 if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
250 || (target16 = GetProcAddress16( hModule16, lpszProcName )) == 0 )
253 /* Allocate UTINFO struct */
256 if ( (ut = UTFind( hModule )) != NULL )
259 ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
264 FreeLibrary16( hModule16 );
268 /* Call UTInit16 if present */
271 && (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
273 SEGPTR callback = MapLS( &ut->ut16 );
274 SEGPTR segBuff = MapLS( lpBuff );
278 args[3] = SELECTOROF(callback);
279 args[2] = OFFSETOF(callback);
280 args[1] = SELECTOROF(segBuff);
281 args[0] = OFFSETOF(segBuff);
282 WOWCallback16Ex( (DWORD)init16, WCB16_PASCAL, sizeof(args), args, &ret );
287 UTUnRegister( hModule );
292 /* Return 32-bit thunk */
294 *ppfn32Thunk = (FARPROC) &ut->ut32;
299 /****************************************************************************
300 * UTUnRegister (KERNEL32.@)
302 VOID WINAPI UTUnRegister( HMODULE hModule )
305 HMODULE16 hModule16 = 0;
308 ut = UTFind( hModule );
311 hModule16 = ut->hModule16;
317 FreeLibrary16( hModule16 );
320 /****************************************************************************
321 * UTInit (KERNEL.493)
323 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
325 FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );