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