Make WINE_GET_SONAME work on NetBSD.
[wine/wine64.git] / dlls / kernel / utthunk.c
blob50f0d29fa6d9e393a6d52fc1d33a4b5d03c7200f
1 /*
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"
22 #include "winternl.h"
23 #include "wownt32.h"
24 #include "module.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(thunk);
29 #include "pshpack1.h"
31 typedef struct
33 BYTE popl_eax;
34 BYTE pushl;
35 DWORD target;
36 BYTE pushl_eax;
37 BYTE ljmp;
38 DWORD utglue16;
40 } UT16THUNK;
42 typedef struct
44 BYTE popl_eax;
45 BYTE pushl;
46 DWORD target;
47 BYTE pushl_eax;
48 BYTE jmp;
49 DWORD utglue32;
51 } UT32THUNK;
53 #include "poppack.h"
55 typedef struct _UTINFO
57 struct _UTINFO *next;
58 HMODULE hModule;
59 HMODULE16 hModule16;
61 UT16THUNK ut16;
62 UT32THUNK ut32;
64 } UTINFO;
66 static UTINFO *UT_head; /* head of Universal Thunk list */
68 typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
70 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
71 LPSTR lpszInitName, LPSTR lpszProcName,
72 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
73 LPVOID lpBuff );
75 VOID WINAPI UTUnRegister( HMODULE hModule );
78 /****************************************************************************
79 * UTGlue16 (KERNEL.666) (KERNEL Wine-specific export)
81 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
82 UTGLUEPROC target )
84 INT i;
86 /* Convert arguments to flat pointers */
88 if ( translationList )
89 for ( i = 0; translationList[i]; i++ )
91 LPVOID flatPtr = MapSL( translationList[i] );
92 *(LPVOID *)flatPtr = MapSL( *(SEGPTR *)flatPtr );
95 /* Call 32-bit routine */
97 return target( lpBuff, dwUserDefined );
100 /****************************************************************************
101 * UTGlue32
103 static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
104 LPVOID translationList[] )
106 SEGPTR segBuff, *segptrList = NULL;
107 INT i, nList = 0;
108 DWORD retv;
109 WORD args[4];
111 /* Convert arguments to SEGPTRs */
113 if ( translationList )
114 for ( nList = 0; translationList[nList]; nList++ )
117 if ( nList )
119 segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
120 if ( !segptrList )
122 FIXME("Unable to allocate segptrList!\n" );
123 return 0;
126 for ( i = 0; i < nList; i++ )
127 segptrList[i] = *(SEGPTR *)translationList[i]
128 = MapLS( *(LPVOID *)translationList[i] );
131 segBuff = MapLS( lpBuff );
133 /* Call 16-bit routine */
135 args[3] = SELECTOROF(segBuff);
136 args[2] = OFFSETOF(segBuff);
137 args[1] = HIWORD(dwUserDefined);
138 args[0] = LOWORD(dwUserDefined);
139 WOWCallback16Ex( (DWORD)target, WCB16_PASCAL, sizeof(args), args, &retv );
141 /* Free temporary selectors */
143 UnMapLS( segBuff );
145 if ( nList )
147 for ( i = 0; i < nList; i++ )
148 UnMapLS( segptrList[i] );
150 HeapFree( GetProcessHeap(), 0, segptrList );
153 return retv;
156 /****************************************************************************
157 * UTAlloc
159 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
160 FARPROC16 target16, FARPROC target32 )
162 static FARPROC16 UTGlue16_Segptr = NULL;
163 UTINFO *ut;
165 if ( !UTGlue16_Segptr )
167 HMODULE16 hModule = GetModuleHandle16( "KERNEL" );
168 UTGlue16_Segptr = GetProcAddress16( hModule, "UTGlue16" );
169 if ( !UTGlue16_Segptr ) return NULL;
172 ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UTINFO) );
173 if ( !ut ) return NULL;
175 ut->hModule = hModule;
176 ut->hModule16 = hModule16;
178 ut->ut16.popl_eax = 0x58;
179 ut->ut16.pushl = 0x68;
180 ut->ut16.target = (DWORD)target32;
181 ut->ut16.pushl_eax = 0x50;
182 ut->ut16.ljmp = 0xea;
183 ut->ut16.utglue16 = (DWORD)UTGlue16_Segptr;
185 ut->ut32.popl_eax = 0x58;
186 ut->ut32.pushl = 0x68;
187 ut->ut32.target = (DWORD)target16;
188 ut->ut32.pushl_eax = 0x50;
189 ut->ut32.jmp = 0xe9;
190 ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
192 ut->next = UT_head;
193 UT_head = ut;
195 return ut;
198 /****************************************************************************
199 * UTFree
201 static void UTFree( UTINFO *ut )
203 UTINFO **ptr;
205 for ( ptr = &UT_head; *ptr; ptr = &(*ptr)->next )
206 if ( *ptr == ut )
208 *ptr = ut->next;
209 break;
212 HeapFree( GetProcessHeap(), 0, ut );
215 /****************************************************************************
216 * UTFind
218 static UTINFO *UTFind( HMODULE hModule )
220 UTINFO *ut;
222 for ( ut = UT_head; ut; ut =ut->next )
223 if ( ut->hModule == hModule )
224 break;
226 return ut;
230 /****************************************************************************
231 * UTRegister (KERNEL32.@)
233 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
234 LPSTR lpszInitName, LPSTR lpszProcName,
235 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
236 LPVOID lpBuff )
238 UTINFO *ut;
239 HMODULE16 hModule16;
240 FARPROC16 target16, init16;
242 /* Load 16-bit DLL and get UTProc16 entry point */
244 if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
245 || (target16 = GetProcAddress16( hModule16, lpszProcName )) == 0 )
246 return FALSE;
248 /* Allocate UTINFO struct */
250 RtlAcquirePebLock();
251 if ( (ut = UTFind( hModule )) != NULL )
252 ut = NULL;
253 else
254 ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
255 RtlReleasePebLock();
257 if ( !ut )
259 FreeLibrary16( hModule16 );
260 return FALSE;
263 /* Call UTInit16 if present */
265 if ( lpszInitName
266 && (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
268 SEGPTR callback = MapLS( &ut->ut16 );
269 SEGPTR segBuff = MapLS( lpBuff );
270 WORD args[4];
271 DWORD ret;
273 args[3] = SELECTOROF(callback);
274 args[2] = OFFSETOF(callback);
275 args[1] = SELECTOROF(segBuff);
276 args[0] = OFFSETOF(segBuff);
277 WOWCallback16Ex( (DWORD)init16, WCB16_PASCAL, sizeof(args), args, &ret );
278 UnMapLS( segBuff );
279 UnMapLS( callback );
280 if (!ret)
282 UTUnRegister( hModule );
283 return FALSE;
287 /* Return 32-bit thunk */
289 *ppfn32Thunk = (FARPROC) &ut->ut32;
291 return TRUE;
294 /****************************************************************************
295 * UTUnRegister (KERNEL32.@)
297 VOID WINAPI UTUnRegister( HMODULE hModule )
299 UTINFO *ut;
300 HMODULE16 hModule16 = 0;
302 RtlAcquirePebLock();
303 ut = UTFind( hModule );
304 if ( !ut )
306 hModule16 = ut->hModule16;
307 UTFree( ut );
309 RtlReleasePebLock();
311 if ( hModule16 )
312 FreeLibrary16( hModule16 );
315 /****************************************************************************
316 * UTInit (KERNEL.493)
318 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
320 FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
321 return 0;