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