Fixed the displaying of the FOURCC codes in _dump_pixelformat.
[wine] / dlls / kernel / wowthunk.c
1 /*
2  * Win32 WOW Generic Thunk API
3  *
4  * Copyright 1999 Ulrich Weigand 
5  */
6
7 #include "wine/winbase16.h"
8 #include "winbase.h"
9 #include "wownt32.h"
10 #include "file.h"
11 #include "heap.h"
12 #include "miscemu.h"
13 #include "syslevel.h"
14 #include "stackframe.h"
15 #include "builtin16.h"
16 #include "debugtools.h"
17
18 DEFAULT_DEBUG_CHANNEL(thunk);
19
20 /*
21  *  32-bit WOW routines (in WOW32, but actually forwarded to KERNEL32)
22  */
23
24 /**********************************************************************
25  *           WOWGetDescriptor        (WOW32.1) (KERNEL32.70)
26  */
27 BOOL WINAPI WOWGetDescriptor( SEGPTR segptr, LPLDT_ENTRY ldtent )
28 {
29     return GetThreadSelectorEntry( GetCurrentThread(), 
30                                    segptr >> 16, ldtent );
31 }
32
33 /**********************************************************************
34  *           WOWGetVDMPointer        (WOW32.5) (KERNEL32.56)
35  */
36 LPVOID WINAPI WOWGetVDMPointer( DWORD vp, DWORD dwBytes, BOOL fProtectedMode )
37 {
38     /* FIXME: add size check too */
39
40     if ( fProtectedMode )
41         return PTR_SEG_TO_LIN( vp );
42     else
43         return DOSMEM_MapRealToLinear( vp );
44 }
45
46 /**********************************************************************
47  *           WOWGetVDMPointerFix     (WOW32.6) (KERNEL32.68)
48  */
49 LPVOID WINAPI WOWGetVDMPointerFix( DWORD vp, DWORD dwBytes, BOOL fProtectedMode )
50 {
51     /* 
52      * Hmmm. According to the docu, we should call:
53      *
54      *          GlobalFix16( SELECTOROF(vp) );
55      *
56      * But this is unnecessary under Wine, as we never move global
57      * memory segments in linear memory anyway. 
58      *
59      * (I'm not so sure what we are *supposed* to do if 
60      *  fProtectedMode is TRUE, anyway ...)
61      */
62
63     return WOWGetVDMPointer( vp, dwBytes, fProtectedMode );
64 }
65
66 /**********************************************************************
67  *           WOWGetVDMPointerUnFix   (WOW32.7) (KERNEL32.69)
68  */
69 VOID WINAPI WOWGetVDMPointerUnfix( DWORD vp )
70 {
71     /*
72      * See above why we don't call:
73      *
74      * GlobalUnfix16( SELECTOROF(vp) );
75      *
76      */
77 }
78
79 /**********************************************************************
80  *           WOWGlobalAlloc16        (WOW32.8) (KERNEL32.59)
81  */
82 WORD WINAPI WOWGlobalAlloc16( WORD wFlags, DWORD cb )
83 {
84     return (WORD)GlobalAlloc16( wFlags, cb );
85 }
86
87 /**********************************************************************
88  *           WOWGlobalFree16         (WOW32.10) (KERNEL32.62)
89  */
90 WORD WINAPI WOWGlobalFree16( WORD hMem )
91 {
92     return (WORD)GlobalFree16( (HGLOBAL16)hMem );
93 }
94
95 /**********************************************************************
96  *           WOWGlobalLock16         (WOW32.11) (KERNEL32.60)
97  */
98 DWORD WINAPI WOWGlobalLock16( WORD hMem )
99 {
100     return (DWORD)WIN16_GlobalLock16( (HGLOBAL16)hMem );
101 }
102
103 /**********************************************************************
104  *           WOWGlobalUnlock16       (WOW32.13) (KERNEL32.61)
105  */
106 BOOL WINAPI WOWGlobalUnlock16( WORD hMem )
107 {
108     return (BOOL)GlobalUnlock16( (HGLOBAL16)hMem );
109 }
110
111 /**********************************************************************
112  *           WOWGlobalAllocLock16    (WOW32.9) (KERNEL32.63)
113  */
114 DWORD WINAPI WOWGlobalAllocLock16( WORD wFlags, DWORD cb, WORD *phMem )
115 {
116     WORD hMem = WOWGlobalAlloc16( wFlags, cb );
117     if (phMem) *phMem = hMem;
118
119     return WOWGlobalLock16( hMem );
120 }
121
122 /**********************************************************************
123  *           WOWGlobalLockSize16     (WOW32.12) (KERNEL32.65)
124  */
125 DWORD WINAPI WOWGlobalLockSize16( WORD hMem, PDWORD pcb )
126 {
127     if ( pcb ) 
128         *pcb = GlobalSize16( (HGLOBAL16)hMem );
129
130     return WOWGlobalLock16( hMem );
131 }
132
133 /**********************************************************************
134  *           WOWGlobalUnlockFree16   (WOW32.14) (KERNEL32.64)
135  */
136 WORD WINAPI WOWGlobalUnlockFree16( DWORD vpMem )
137 {
138     if ( !WOWGlobalUnlock16( HIWORD(vpMem) ) )
139         return FALSE;
140
141     return WOWGlobalFree16( HIWORD(vpMem) );
142 }
143
144
145 /**********************************************************************
146  *           WOWYield16              (WOW32.17) (KERNEL32.66)
147  */
148 VOID WINAPI WOWYield16( void )
149 {
150     /*
151      * This does the right thing for both Win16 and Win32 tasks.  
152      * More or less, at least :-/
153      */
154     Yield16();
155 }
156
157 /**********************************************************************
158  *           WOWDirectedYield16       (WOW32.4) (KERNEL32.67)
159  */
160 VOID WINAPI WOWDirectedYield16( WORD htask16 )
161 {
162     /*
163      * Argh.  Our scheduler doesn't like DirectedYield by Win32
164      * tasks at all.  So we do hope that this routine is indeed 
165      * only ever called by Win16 tasks that have thunked up ...
166      */
167     DirectedYield16( (HTASK16)htask16 );
168 }
169
170
171 /***********************************************************************
172  *           WOWHandle32              (WOW32.16) (KERNEL32.57)
173  */
174 HANDLE WINAPI WOWHandle32( WORD handle, WOW_HANDLE_TYPE type )
175 {
176     switch ( type )
177     {
178     case WOW_TYPE_HWND:
179     case WOW_TYPE_HMENU:
180     case WOW_TYPE_HDWP:
181     case WOW_TYPE_HDROP:
182     case WOW_TYPE_HDC:
183     case WOW_TYPE_HFONT:
184     case WOW_TYPE_HMETAFILE:
185     case WOW_TYPE_HRGN:
186     case WOW_TYPE_HBITMAP:
187     case WOW_TYPE_HBRUSH:
188     case WOW_TYPE_HPALETTE:
189     case WOW_TYPE_HPEN:
190     case WOW_TYPE_HACCEL:
191     case WOW_TYPE_HTASK:
192     case WOW_TYPE_FULLHWND:
193         return (HANDLE)handle;
194
195     default:
196         ERR( "handle 0x%04x of unknown type %d\n", handle, type );
197         return (HANDLE)handle;
198     }
199 }
200
201 /***********************************************************************
202  *           WOWHandle16              (WOW32.15) (KERNEL32.58)
203  */
204 WORD WINAPI WOWHandle16( HANDLE handle, WOW_HANDLE_TYPE type )
205 {
206     if ( HIWORD(handle ) )
207         ERR( "handle 0x%08x of type %d has non-zero HIWORD\n", handle, type );
208
209     switch ( type )
210     {
211     case WOW_TYPE_HWND:
212     case WOW_TYPE_HMENU:
213     case WOW_TYPE_HDWP:
214     case WOW_TYPE_HDROP:
215     case WOW_TYPE_HDC:
216     case WOW_TYPE_HFONT:
217     case WOW_TYPE_HMETAFILE:
218     case WOW_TYPE_HRGN:
219     case WOW_TYPE_HBITMAP:
220     case WOW_TYPE_HBRUSH:
221     case WOW_TYPE_HPALETTE:
222     case WOW_TYPE_HPEN:
223     case WOW_TYPE_HACCEL:
224     case WOW_TYPE_HTASK:
225     case WOW_TYPE_FULLHWND:
226         return LOWORD(handle);
227
228     default:
229         ERR( "handle 0x%08x of unknown type %d\n", handle, type );
230         return LOWORD(handle);
231     }
232 }
233
234 /**********************************************************************
235  *           WOWCallback16            (WOW32.2) (KERNEL32.54)
236  */
237 DWORD WINAPI WOWCallback16( DWORD vpfn16, DWORD dwParam )
238 {
239     DWORD ret;
240
241     if ( !WOWCallback16Ex( vpfn16, WCB16_PASCAL, 
242                            sizeof(DWORD), &dwParam, &ret ) )
243         ret = 0L;
244
245     return ret;
246 }
247
248 /**********************************************************************
249  *           WOWCallback16Ex         (WOW32.3) (KERNEL32.55)
250  */
251 BOOL WINAPI WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
252                              DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode )
253 {
254     DWORD ret;
255
256     /*
257      * Arguments must be prepared in the correct order by the caller
258      * (both for PASCAL and CDECL calling convention), so we simply
259      * copy them to the 16-bit stack ... 
260      */
261     memcpy( (LPBYTE)CURRENT_STACK16 - cbArgs, (LPBYTE)pArgs, cbArgs );
262
263
264     /*
265      * Actually, we should take care whether the called routine cleans up
266      * its stack or not.  Fortunately, our CallTo16 core doesn't rely on 
267      * the callee to do so; after the routine has returned, the 16-bit 
268      * stack pointer is always reset to the position it had before. 
269      */
270
271     ret = CallTo16Long( (FARPROC16)vpfn16, cbArgs );
272
273     if ( pdwRetCode )
274         *pdwRetCode = ret;
275
276     return TRUE;  /* success */
277 }
278
279
280
281 /*
282  *  16-bit WOW routines (in KERNEL)
283  */
284
285 /**********************************************************************
286  *           GetVDMPointer32W16      (KERNEL.516)
287  */
288 DWORD WINAPI GetVDMPointer32W16( SEGPTR vp, UINT16 fMode )
289 {
290     return (DWORD)WOWGetVDMPointer( vp, 0, (DWORD)fMode );
291 }
292
293 /***********************************************************************
294  *           LoadLibraryEx32W16      (KERNEL.513)
295  */
296 DWORD WINAPI LoadLibraryEx32W16( LPCSTR lpszLibFile, DWORD hFile, DWORD dwFlags )
297 {
298     HMODULE hModule;
299     DOS_FULL_NAME full_name; 
300
301     /* if the file can not be found, call LoadLibraryExA anyway, since it might be
302        a buildin module. This case is handled in MODULE_LoadLibraryExA */
303
304     if ( ! DIR_SearchPath ( NULL, lpszLibFile, ".DLL", &full_name, FALSE ) ) {
305       strcpy ( full_name.short_name, lpszLibFile );
306     }
307
308     SYSLEVEL_ReleaseWin16Lock();
309     hModule = LoadLibraryExA( full_name.short_name, (HANDLE)hFile, dwFlags );
310     SYSLEVEL_RestoreWin16Lock();
311
312     return (DWORD)hModule;
313 }
314
315 /***********************************************************************
316  *           GetProcAddress32W16     (KERNEL.515)
317  */
318 DWORD WINAPI GetProcAddress32W16( DWORD hModule, LPCSTR lpszProc )
319 {
320     return (DWORD)GetProcAddress( (HMODULE)hModule, lpszProc );
321 }
322
323 /***********************************************************************
324  *           FreeLibrary32W16        (KERNEL.514)
325  */
326 DWORD WINAPI FreeLibrary32W16( DWORD hLibModule )
327 {
328     BOOL retv;
329
330     SYSLEVEL_ReleaseWin16Lock();
331     retv = FreeLibrary( (HMODULE)hLibModule );
332     SYSLEVEL_RestoreWin16Lock();
333
334     return (DWORD)retv;
335 }
336
337
338 /**********************************************************************
339  *           WOW_CallProc32W
340  */
341 static DWORD WOW_CallProc32W16( BOOL Ex )
342 {
343     DWORD nrofargs, argconvmask;
344     FARPROC proc32;
345     DWORD *args, ret;
346     VA_LIST16 valist;
347     int i;
348     int aix;
349
350     SYSLEVEL_ReleaseWin16Lock();
351
352     VA_START16( valist );
353     nrofargs    = VA_ARG16( valist, DWORD );
354     argconvmask = VA_ARG16( valist, DWORD );
355     proc32      = VA_ARG16( valist, FARPROC );
356     TRACE("(%ld,%ld,%p, Ex%d args[",nrofargs,argconvmask,proc32,Ex);
357     args = (DWORD*)HeapAlloc( GetProcessHeap(), 0, sizeof(DWORD)*nrofargs );
358     if(args == NULL) proc32 = NULL; /* maybe we should WARN here? */
359     /* CallProcEx doesn't need its args reversed */
360     for (i=0;i<nrofargs;i++) {
361             if (Ex) {
362                aix = i;
363             } else {
364                aix = nrofargs - i - 1;
365             }
366             if (argconvmask & (1<<i))
367             {
368                 SEGPTR ptr = VA_ARG16( valist, SEGPTR );
369                 if (args) args[aix] = (DWORD)PTR_SEG_TO_LIN(ptr);
370                 if (TRACE_ON(thunk)) DPRINTF("%08lx(%p),",ptr,PTR_SEG_TO_LIN(ptr));
371             }
372             else
373             {
374                 DWORD arg = VA_ARG16( valist, DWORD );
375                 if (args) args[aix] = arg;
376                 if (TRACE_ON(thunk)) DPRINTF("%ld,", arg);
377             }
378     }
379     if (TRACE_ON(thunk)) DPRINTF("])\n");
380     VA_END16( valist );
381
382     /*
383      * FIXME:  If ( nrofargs & CPEX_DEST_CDECL ) != 0, we should call a
384      *         32-bit CDECL routine ...
385      */
386
387     if (!proc32) ret = 0;
388     else switch (nrofargs)
389     {
390     case 0: ret = proc32();
391             break;
392     case 1: ret = proc32(args[0]);
393             break;
394     case 2: ret = proc32(args[0],args[1]);
395             break;
396     case 3: ret = proc32(args[0],args[1],args[2]);
397             break;
398     case 4: ret = proc32(args[0],args[1],args[2],args[3]);
399             break;
400     case 5: ret = proc32(args[0],args[1],args[2],args[3],args[4]);
401             break;
402     case 6: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5]);
403             break;
404     case 7: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
405             break;
406     case 8: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
407             break;
408     case 9: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
409             break;
410     case 10:ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
411             break;
412     case 11:ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
413             break;
414     default:
415             /* FIXME: should go up to 32  arguments */
416             ERR("Unsupported number of arguments %ld, please report.\n",nrofargs);
417             ret = 0;
418             break;
419     }
420
421     /* POP nrofargs DWORD arguments and 3 DWORD parameters */
422     if (!Ex) stack16_pop( (3 + nrofargs) * sizeof(DWORD) );
423
424     TRACE("returns %08lx\n",ret);
425     HeapFree( GetProcessHeap(), 0, args );
426
427     SYSLEVEL_RestoreWin16Lock();
428
429     return ret;
430 }
431
432 /**********************************************************************
433  *           CallProc32W16           (KERNEL.517)
434  *
435  * DWORD PASCAL CallProc32W( DWORD p1, ... , DWORD lpProcAddress,
436  *                           DWORD fAddressConvert, DWORD cParams );
437  */
438 DWORD WINAPI CallProc32W16( void )
439 {
440     return WOW_CallProc32W16( FALSE );
441 }
442
443 /**********************************************************************
444  *           CallProcEx32W16         (KERNEL.518)
445  *
446  * DWORD CallProcEx32W( DWORD cParams, DWORD fAddressConvert, 
447  *                      DWORD lpProcAddress, DWORD p1, ... );
448  */
449 DWORD WINAPI CallProcEx32W16( void )
450 {
451     return WOW_CallProc32W16( TRUE );
452 }
453
454
455 /**********************************************************************
456  *           WOW16Call               (KERNEL.501)
457  *
458  * FIXME!!!
459  *
460  */
461 DWORD WINAPI WOW16Call(WORD x,WORD y,WORD z) 
462 {
463         int     i;
464         DWORD   calladdr;
465         VA_LIST16 args;
466         FIXME("(0x%04x,0x%04x,%d),calling (",x,y,z);
467
468         VA_START16(args);
469         for (i=0;i<x/2;i++) {
470                 WORD    a = VA_ARG16(args,WORD);
471                 DPRINTF("%04x ",a);
472         }
473         calladdr = VA_ARG16(args,DWORD);
474         VA_END16(args);
475         stack16_pop( x + sizeof(DWORD) );
476         DPRINTF(") calling address was 0x%08lx\n",calladdr);
477         return 0;
478 }
479
480