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