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