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