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