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