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