Enable the disabled tests in tests.data or add a comment describing
[wine] / dlls / kernel / utthunk.c
1 /*
2  * Win32s Universal Thunk API
3  *
4  * Copyright 1999 Ulrich Weigand
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22
23 #include "wine/winbase16.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winreg.h"
27 #include "winternl.h"
28 #include "wownt32.h"
29 #include "module.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(thunk);
33
34 #include "pshpack1.h"
35
36 typedef struct
37 {
38     BYTE    popl_eax;
39     BYTE    pushl;
40     DWORD   target;
41     BYTE    pushl_eax;
42     BYTE    ljmp;
43     DWORD   utglue16;
44
45 } UT16THUNK;
46
47 typedef struct
48 {
49     BYTE    popl_eax;
50     BYTE    pushl;
51     DWORD   target;
52     BYTE    pushl_eax;
53     BYTE    jmp;
54     DWORD   utglue32;
55
56 } UT32THUNK;
57
58 #include "poppack.h"
59
60 typedef struct _UTINFO
61 {
62     struct _UTINFO    *next;
63     HMODULE            hModule;
64     HMODULE16          hModule16;
65
66     UT16THUNK          ut16;
67     UT32THUNK          ut32;
68
69 } UTINFO;
70
71 static UTINFO *UT_head; /* head of Universal Thunk list */
72
73 typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
74
75 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
76                         LPSTR lpszInitName, LPSTR lpszProcName,
77                         FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
78                         LPVOID lpBuff );
79
80 VOID WINAPI UTUnRegister( HMODULE hModule );
81
82
83 /****************************************************************************
84  *              UTGlue16 (KERNEL.666) (KERNEL Wine-specific export)
85  */
86 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
87                        UTGLUEPROC target )
88 {
89     INT i;
90
91     /* Convert arguments to flat pointers */
92
93     if ( translationList )
94         for ( i = 0; translationList[i]; i++ )
95         {
96             LPVOID flatPtr = MapSL( translationList[i] );
97             *(LPVOID *)flatPtr = MapSL( *(SEGPTR *)flatPtr );
98         }
99
100     /* Call 32-bit routine */
101
102     return target( lpBuff, dwUserDefined );
103 }
104
105 /****************************************************************************
106  *              UTGlue32
107  */
108 static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
109                               LPVOID translationList[] )
110 {
111     SEGPTR segBuff, *segptrList = NULL;
112     INT i, nList = 0;
113     DWORD retv;
114     WORD args[4];
115
116     /* Convert arguments to SEGPTRs */
117
118     if ( translationList )
119         for ( nList = 0; translationList[nList]; nList++ )
120             ;
121
122     if ( nList )
123     {
124         segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
125         if ( !segptrList )
126         {
127             FIXME("Unable to allocate segptrList!\n" );
128             return 0;
129         }
130
131         for ( i = 0; i < nList; i++ )
132             segptrList[i] = *(SEGPTR *)translationList[i]
133                           = MapLS( *(LPVOID *)translationList[i] );
134     }
135
136     segBuff = MapLS( lpBuff );
137
138     /* Call 16-bit routine */
139
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 );
145
146     /* Free temporary selectors */
147
148     UnMapLS( segBuff );
149
150     if ( nList )
151     {
152         for ( i = 0; i < nList; i++ )
153             UnMapLS( segptrList[i] );
154
155         HeapFree( GetProcessHeap(), 0, segptrList );
156     }
157
158     return retv;
159 }
160
161 /****************************************************************************
162  *              UTAlloc
163  */
164 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
165                         FARPROC16 target16, FARPROC target32 )
166 {
167     static FARPROC16 UTGlue16_Segptr = NULL;
168     UTINFO *ut;
169
170     if ( !UTGlue16_Segptr )
171     {
172         HMODULE16 hModule = GetModuleHandle16( "KERNEL" );
173         UTGlue16_Segptr = GetProcAddress16( hModule, "UTGlue16" );
174         if ( !UTGlue16_Segptr ) return NULL;
175     }
176
177     ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UTINFO) );
178     if ( !ut ) return NULL;
179
180     ut->hModule   = hModule;
181     ut->hModule16 = hModule16;
182
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;
189
190     ut->ut32.popl_eax  = 0x58;
191     ut->ut32.pushl     = 0x68;
192     ut->ut32.target    = (DWORD)target16;
193     ut->ut32.pushl_eax = 0x50;
194     ut->ut32.jmp       = 0xe9;
195     ut->ut32.utglue32  = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
196
197     ut->next = UT_head;
198     UT_head = ut;
199
200     return ut;
201 }
202
203 /****************************************************************************
204  *              UTFree
205  */
206 static void UTFree( UTINFO *ut )
207 {
208     UTINFO **ptr;
209
210     for ( ptr = &UT_head; *ptr; ptr = &(*ptr)->next )
211         if ( *ptr == ut )
212         {
213             *ptr = ut->next;
214             break;
215         }
216
217     HeapFree( GetProcessHeap(), 0, ut );
218 }
219
220 /****************************************************************************
221  *              UTFind
222  */
223 static UTINFO *UTFind( HMODULE hModule )
224 {
225     UTINFO *ut;
226
227     for ( ut = UT_head; ut; ut =ut->next )
228         if ( ut->hModule == hModule )
229             break;
230
231     return ut;
232 }
233
234
235 /****************************************************************************
236  *              UTRegister (KERNEL32.@)
237  */
238 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
239                         LPSTR lpszInitName, LPSTR lpszProcName,
240                         FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
241                         LPVOID lpBuff )
242 {
243     UTINFO *ut;
244     HMODULE16 hModule16;
245     FARPROC16 target16, init16;
246
247     /* Load 16-bit DLL and get UTProc16 entry point */
248
249     if (   (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
250         || (target16  = GetProcAddress16( hModule16, lpszProcName )) == 0 )
251         return FALSE;
252
253     /* Allocate UTINFO struct */
254
255     RtlAcquirePebLock();
256     if ( (ut = UTFind( hModule )) != NULL )
257         ut = NULL;
258     else
259         ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
260     RtlReleasePebLock();
261
262     if ( !ut )
263     {
264         FreeLibrary16( hModule16 );
265         return FALSE;
266     }
267
268     /* Call UTInit16 if present */
269
270     if (     lpszInitName
271          && (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
272     {
273         SEGPTR callback = MapLS( &ut->ut16 );
274         SEGPTR segBuff  = MapLS( lpBuff );
275         WORD args[4];
276         DWORD ret;
277
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 );
283         UnMapLS( segBuff );
284         UnMapLS( callback );
285         if (!ret)
286         {
287             UTUnRegister( hModule );
288             return FALSE;
289         }
290     }
291
292     /* Return 32-bit thunk */
293
294     *ppfn32Thunk = (FARPROC) &ut->ut32;
295
296     return TRUE;
297 }
298
299 /****************************************************************************
300  *              UTUnRegister (KERNEL32.@)
301  */
302 VOID WINAPI UTUnRegister( HMODULE hModule )
303 {
304     UTINFO *ut;
305     HMODULE16 hModule16 = 0;
306
307     RtlAcquirePebLock();
308     ut = UTFind( hModule );
309     if ( !ut )
310     {
311         hModule16 = ut->hModule16;
312         UTFree( ut );
313     }
314     RtlReleasePebLock();
315
316     if ( hModule16 )
317         FreeLibrary16( hModule16 );
318 }
319
320 /****************************************************************************
321  *              UTInit     (KERNEL.493)
322  */
323 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
324 {
325     FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
326     return 0;
327 }