Like the AUTORADIOBUTTON, the parent of a RADIOBUTTON style button
[wine] / win32 / device.c
1 /*
2  * Win32 device functions
3  *
4  * Copyright 1998 Marcus Meissner
5  * Copyright 1998 Ulrich Weigand
6  * Copyright 1998 Patrik Stridvall
7  *
8  */
9
10 #include "config.h"
11
12 #include <errno.h>
13 #include <assert.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #ifdef HAVE_SYS_MMAN_H
19 #include <sys/mman.h>
20 #endif
21 #include <fcntl.h>
22 #include <string.h>
23 #include <stdarg.h>
24 #include <time.h>
25 #include "windef.h"
26 #include "wingdi.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "winerror.h"
31 #include "winversion.h"
32 #include "file.h"
33 #include "process.h"
34 #include "heap.h"
35 #include "winioctl.h"
36 #include "winnt.h"
37 #include "msdos.h"
38 #include "miscemu.h"
39 #include "stackframe.h"
40 #include "server.h"
41 #include "debugtools.h"
42 #include "global.h"
43
44 DEFAULT_DEBUG_CHANNEL(win32);
45
46
47 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, 
48                               LPVOID lpvInBuffer, DWORD cbInBuffer,
49                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
50                               LPDWORD lpcbBytesReturned,
51                               LPOVERLAPPED lpOverlapped);
52 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode, 
53                               LPVOID lpvInBuffer, DWORD cbInBuffer,
54                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
55                               LPDWORD lpcbBytesReturned,
56                               LPOVERLAPPED lpOverlapped);
57 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode, 
58                               LPVOID lpvInBuffer, DWORD cbInBuffer,
59                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
60                               LPDWORD lpcbBytesReturned,
61                               LPOVERLAPPED lpOverlapped);
62
63 static DWORD VxDCall_VMM( DWORD service, CONTEXT86 *context );
64
65 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, 
66                               LPVOID lpvInBuffer, DWORD cbInBuffer,
67                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
68                               LPDWORD lpcbBytesReturned,
69                               LPOVERLAPPED lpOverlapped);
70
71 static DWORD VxDCall_VWin32( DWORD service, CONTEXT86 *context );
72
73 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, 
74                               LPVOID lpvInBuffer, DWORD cbInBuffer,
75                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
76                               LPDWORD lpcbBytesReturned,
77                               LPOVERLAPPED lpOverlapped);
78
79 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode, 
80                               LPVOID lpvInBuffer, DWORD cbInBuffer,
81                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
82                               LPDWORD lpcbBytesReturned,
83                               LPOVERLAPPED lpOverlapped);
84 /*
85  * VxD names are taken from the Win95 DDK
86  */
87
88 struct VxDInfo
89 {
90     LPCSTR  name;
91     WORD    id;
92     DWORD (*vxdcall)(DWORD, CONTEXT86 *);
93     BOOL  (*deviceio)(DWORD, LPVOID, DWORD, 
94                         LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
95 };
96
97 static const struct VxDInfo VxDList[] = 
98 {
99     /* Standard VxD IDs */
100     { "VMM",      0x0001, VxDCall_VMM, NULL },
101     { "DEBUG",    0x0002, NULL, NULL },
102     { "VPICD",    0x0003, NULL, NULL },
103     { "VDMAD",    0x0004, NULL, NULL },
104     { "VTD",      0x0005, NULL, NULL },
105     { "V86MMGR",  0x0006, NULL, NULL },
106     { "PAGESWAP", 0x0007, NULL, NULL },
107     { "PARITY",   0x0008, NULL, NULL },
108     { "REBOOT",   0x0009, NULL, NULL },
109     { "VDD",      0x000A, NULL, NULL },
110     { "VSD",      0x000B, NULL, NULL },
111     { "VMD",      0x000C, NULL, NULL },
112     { "VKD",      0x000D, NULL, NULL },
113     { "VCD",      0x000E, NULL, NULL },
114     { "VPD",      0x000F, NULL, NULL },
115     { "BLOCKDEV", 0x0010, NULL, NULL },
116     { "VMCPD",    0x0011, NULL, NULL },
117     { "EBIOS",    0x0012, NULL, NULL },
118     { "BIOSXLAT", 0x0013, NULL, NULL },
119     { "VNETBIOS", 0x0014, NULL, NULL },
120     { "DOSMGR",   0x0015, NULL, NULL },
121     { "WINLOAD",  0x0016, NULL, NULL },
122     { "SHELL",    0x0017, NULL, NULL },
123     { "VMPOLL",   0x0018, NULL, NULL },
124     { "VPROD",    0x0019, NULL, NULL },
125     { "DOSNET",   0x001A, NULL, NULL },
126     { "VFD",      0x001B, NULL, NULL },
127     { "VDD2",     0x001C, NULL, NULL },
128     { "WINDEBUG", 0x001D, NULL, NULL },
129     { "TSRLOAD",  0x001E, NULL, NULL },
130     { "BIOSHOOK", 0x001F, NULL, NULL },
131     { "INT13",    0x0020, NULL, NULL },
132     { "PAGEFILE", 0x0021, NULL, NULL },
133     { "SCSI",     0x0022, NULL, NULL },
134     { "MCA_POS",  0x0023, NULL, NULL },
135     { "SCSIFD",   0x0024, NULL, NULL },
136     { "VPEND",    0x0025, NULL, NULL },
137     { "VPOWERD",  0x0026, NULL, NULL },
138     { "VXDLDR",   0x0027, NULL, NULL },
139     { "NDIS",     0x0028, NULL, NULL },
140     { "BIOS_EXT", 0x0029, NULL, NULL },
141     { "VWIN32",   0x002A, VxDCall_VWin32, DeviceIo_VWin32 },
142     { "VCOMM",    0x002B, NULL, NULL },
143     { "SPOOLER",  0x002C, NULL, NULL },
144     { "WIN32S",   0x002D, NULL, NULL },
145     { "DEBUGCMD", 0x002E, NULL, NULL },
146
147     { "VNB",      0x0031, NULL, NULL },
148     { "SERVER",   0x0032, NULL, NULL },
149     { "CONFIGMG", 0x0033, NULL, NULL },
150     { "DWCFGMG",  0x0034, NULL, NULL },
151     { "SCSIPORT", 0x0035, NULL, NULL },
152     { "VFBACKUP", 0x0036, NULL, NULL },
153     { "ENABLE",   0x0037, NULL, NULL },
154     { "VCOND",    0x0038, NULL, NULL },
155
156     { "EFAX",     0x003A, NULL, NULL },
157     { "DSVXD",    0x003B, NULL, NULL },
158     { "ISAPNP",   0x003C, NULL, NULL },
159     { "BIOS",     0x003D, NULL, NULL },
160     { "WINSOCK",  0x003E, NULL, NULL },
161     { "WSOCK",    0x003E, NULL, NULL },
162     { "WSIPX",    0x003F, NULL, NULL },
163     { "IFSMgr",   0x0040, NULL, DeviceIo_IFSMgr },
164     { "VCDFSD",   0x0041, NULL, NULL },
165     { "MRCI2",    0x0042, NULL, NULL },
166     { "PCI",      0x0043, NULL, NULL },
167     { "PELOADER", 0x0044, NULL, NULL },
168     { "EISA",     0x0045, NULL, NULL },
169     { "DRAGCLI",  0x0046, NULL, NULL },
170     { "DRAGSRV",  0x0047, NULL, NULL },
171     { "PERF",     0x0048, NULL, NULL },
172     { "AWREDIR",  0x0049, NULL, NULL },
173
174     /* Far East support */
175     { "ETEN",     0x0060, NULL, NULL },
176     { "CHBIOS",   0x0061, NULL, NULL },
177     { "VMSGD",    0x0062, NULL, NULL },
178     { "VPPID",    0x0063, NULL, NULL },
179     { "VIME",     0x0064, NULL, NULL },
180     { "VHBIOSD",  0x0065, NULL, NULL },
181
182     /* Multimedia OEM IDs */
183     { "VTDAPI",   0x0442, NULL, DeviceIo_VTDAPI },
184     { "MMDEVLDR", 0x044A, NULL, DeviceIo_MMDEVLDR },
185
186     /* Network Device IDs */
187     { "VNetSup",  0x0480, NULL, NULL },
188     { "VRedir",   0x0481, NULL, NULL },
189     { "VBrowse",  0x0482, NULL, NULL },
190     { "VSHARE",   0x0483, NULL, NULL },
191     { "IFSMgr",   0x0484, NULL, NULL },
192     { "MEMPROBE", 0x0485, NULL, NULL },
193     { "VFAT",     0x0486, NULL, NULL },
194     { "NWLINK",   0x0487, NULL, NULL },
195     { "VNWLINK",  0x0487, NULL, NULL },
196     { "NWSUP",    0x0487, NULL, NULL },
197     { "VTDI",     0x0488, NULL, NULL },
198     { "VIP",      0x0489, NULL, NULL },
199     { "VTCP",     0x048A, NULL, NULL },
200     { "VCache",   0x048B, NULL, NULL },
201     { "VUDP",     0x048C, NULL, NULL },
202     { "VAsync",   0x048D, NULL, NULL },
203     { "NWREDIR",  0x048E, NULL, NULL },
204     { "STAT80",   0x048F, NULL, NULL },
205     { "SCSIPORT", 0x0490, NULL, NULL },
206     { "FILESEC",  0x0491, NULL, NULL },
207     { "NWSERVER", 0x0492, NULL, NULL },
208     { "SECPROV",  0x0493, NULL, NULL },
209     { "NSCL",     0x0494, NULL, NULL },
210     { "WSTCP",    0x0495, NULL, NULL },
211     { "NDIS2SUP", 0x0496, NULL, NULL },
212     { "MSODISUP", 0x0497, NULL, NULL },
213     { "Splitter", 0x0498, NULL, NULL },
214     { "PPP",      0x0499, NULL, NULL },
215     { "VDHCP",    0x049A, NULL, NULL },
216     { "VNBT",     0x049B, NULL, NULL },
217     { "LOGGER",   0x049D, NULL, NULL },
218     { "EFILTER",  0x049E, NULL, NULL },
219     { "FFILTER",  0x049F, NULL, NULL },
220     { "TFILTER",  0x04A0, NULL, NULL },
221     { "AFILTER",  0x04A1, NULL, NULL },
222     { "IRLAMP",   0x04A2, NULL, NULL },
223
224     { "PCCARD",   0x097C, NULL, DeviceIo_PCCARD },
225
226     /* WINE additions, ids unknown */
227     { "MONODEBG.VXD", 0x4242, NULL, DeviceIo_MONODEBG },
228
229     { NULL,       0,      NULL, NULL }
230 };
231
232 /*
233  * VMM VxDCall service names are (mostly) taken from Stan Mitchell's
234  * "Inside the Windows 95 File System"
235  */
236
237 #define N_VMM_SERVICE 41
238
239 LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
240
241     "PageReserve",            /* 0x0000 */
242     "PageCommit",             /* 0x0001 */
243     "PageDecommit",           /* 0x0002 */
244     "PagerRegister",          /* 0x0003 */
245     "PagerQuery",             /* 0x0004 */
246     "HeapAllocate",           /* 0x0005 */
247     "ContextCreate",          /* 0x0006 */
248     "ContextDestroy",         /* 0x0007 */
249     "PageAttach",             /* 0x0008 */
250     "PageFlush",              /* 0x0009 */
251     "PageFree",               /* 0x000A */
252     "ContextSwitch",          /* 0x000B */
253     "HeapReAllocate",         /* 0x000C */
254     "PageModifyPermissions",  /* 0x000D */
255     "PageQuery",              /* 0x000E */
256     "GetCurrentContext",      /* 0x000F */
257     "HeapFree",               /* 0x0010 */
258     "RegOpenKey",             /* 0x0011 */
259     "RegCreateKey",           /* 0x0012 */
260     "RegCloseKey",            /* 0x0013 */
261     "RegDeleteKey",           /* 0x0014 */
262     "RegSetValue",            /* 0x0015 */
263     "RegDeleteValue",         /* 0x0016 */
264     "RegQueryValue",          /* 0x0017 */
265     "RegEnumKey",             /* 0x0018 */
266     "RegEnumValue",           /* 0x0019 */
267     "RegQueryValueEx",        /* 0x001A */
268     "RegSetValueEx",          /* 0x001B */
269     "RegFlushKey",            /* 0x001C */
270     "RegQueryInfoKey",        /* 0x001D */
271     "GetDemandPageInfo",      /* 0x001E */
272     "BlockOnID",              /* 0x001F */
273     "SignalID",               /* 0x0020 */
274     "RegLoadKey",             /* 0x0021 */
275     "RegUnLoadKey",           /* 0x0022 */
276     "RegSaveKey",             /* 0x0023 */
277     "RegRemapPreDefKey",      /* 0x0024 */
278     "PageChangePager",        /* 0x0025 */
279     "RegQueryMultipleValues", /* 0x0026 */
280     "RegReplaceKey",          /* 0x0027 */
281     "<KERNEL32.101>"          /* 0x0028 -- What does this do??? */
282 };
283
284 /* PageReserve arena values */
285 #define PR_PRIVATE  0x80000400  /* anywhere in private arena */
286 #define PR_SHARED   0x80060000  /* anywhere in shared arena */
287 #define PR_SYSTEM   0x80080000  /* anywhere in system arena */
288
289 /* PageReserve flags */
290 #define PR_FIXED    0x00000008  /* don't move during PageReAllocate */
291 #define PR_4MEG     0x00000001  /* allocate on 4mb boundary */
292 #define PR_STATIC   0x00000010  /* see PageReserve documentation */
293
294 /* PageCommit default pager handle values */
295 #define PD_ZEROINIT 0x00000001  /* swappable zero-initialized pages */
296 #define PD_NOINIT   0x00000002  /* swappable uninitialized pages */
297 #define PD_FIXEDZERO    0x00000003  /* fixed zero-initialized pages */
298 #define PD_FIXED    0x00000004  /* fixed uninitialized pages */
299
300 /* PageCommit flags */
301 #define PC_FIXED    0x00000008  /* pages are permanently locked */
302 #define PC_LOCKED   0x00000080  /* pages are made present and locked*/
303 #define PC_LOCKEDIFDP   0x00000100  /* pages are locked if swap via DOS */
304 #define PC_WRITEABLE    0x00020000  /* make the pages writeable */
305 #define PC_USER     0x00040000  /* make the pages ring 3 accessible */
306 #define PC_INCR     0x40000000  /* increment "pagerdata" each page */
307 #define PC_PRESENT  0x80000000  /* make pages initially present */
308 #define PC_STATIC   0x20000000  /* allow commit in PR_STATIC object */
309 #define PC_DIRTY    0x08000000  /* make pages initially dirty */
310 #define PC_CACHEDIS 0x00100000  /* Allocate uncached pages - new for WDM */
311 #define PC_CACHEWT  0x00080000  /* Allocate write through cache pages - new for WDM */
312 #define PC_PAGEFLUSH 0x00008000 /* Touch device mapped pages on alloc - new for WDM */
313
314 /* PageCommitContig additional flags */
315 #define PCC_ZEROINIT    0x00000001  /* zero-initialize new pages */
316 #define PCC_NOLIN   0x10000000  /* don't map to any linear address */
317
318
319
320 HANDLE DEVICE_Open( LPCSTR filename, DWORD access,
321                       LPSECURITY_ATTRIBUTES sa )
322 {
323     const struct VxDInfo *info;
324
325     for (info = VxDList; info->name; info++)
326         if (!lstrcmpiA( info->name, filename ))
327             return FILE_CreateDevice( info->id | 0x10000, access, sa );
328
329     FIXME( "Unknown VxD %s\n", filename);
330     SetLastError( ERROR_FILE_NOT_FOUND );
331     return HFILE_ERROR;
332 }
333
334 static const struct VxDInfo *DEVICE_GetInfo( HANDLE handle )
335 {
336     struct get_file_info_request *req = get_req_buffer();
337
338     req->handle = handle;
339     if (!server_call( REQ_GET_FILE_INFO ) &&
340         (req->type == FILE_TYPE_UNKNOWN) &&
341         (req->attr & 0x10000))
342     {
343         const struct VxDInfo *info;
344         for (info = VxDList; info->name; info++)
345             if (info->id == LOWORD(req->attr)) return info;
346     }
347     return NULL;
348 }
349
350 /****************************************************************************
351  *              DeviceIoControl (KERNEL32.188)
352  * This is one of those big ugly nasty procedure which can do
353  * a million and one things when it comes to devices. It can also be
354  * used for VxD communication.
355  *
356  * A return value of FALSE indicates that something has gone wrong which
357  * GetLastError can decypher.
358  */
359 BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, 
360                               LPVOID lpvInBuffer, DWORD cbInBuffer,
361                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
362                               LPDWORD lpcbBytesReturned,
363                               LPOVERLAPPED lpOverlapped)
364 {
365         const struct VxDInfo *info;
366
367         TRACE( "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n",
368                hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
369                lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped  );
370
371         if (!(info = DEVICE_GetInfo( hDevice )))
372         {
373                 SetLastError( ERROR_INVALID_PARAMETER );
374                 return FALSE;
375         }
376
377         /* Check if this is a user defined control code for a VxD */
378         if( HIWORD( dwIoControlCode ) == 0 )
379         {
380                 if ( info->deviceio )
381                 {
382                         return info->deviceio( dwIoControlCode, 
383                                         lpvInBuffer, cbInBuffer, 
384                                         lpvOutBuffer, cbOutBuffer, 
385                                         lpcbBytesReturned, lpOverlapped );
386                 }
387                 else
388                 {
389                         /* FIXME: Set appropriate error */
390                         FIXME( "Unimplemented control %ld for VxD device %s\n", 
391                                dwIoControlCode, info->name ? info->name : "???" );
392                 }
393         }
394         else
395         {
396                 switch( dwIoControlCode )
397                 {
398                 case FSCTL_DELETE_REPARSE_POINT:
399                 case FSCTL_DISMOUNT_VOLUME:
400                 case FSCTL_GET_COMPRESSION:
401                 case FSCTL_GET_REPARSE_POINT:
402                 case FSCTL_LOCK_VOLUME:
403                 case FSCTL_QUERY_ALLOCATED_RANGES:
404                 case FSCTL_SET_COMPRESSION:
405                 case FSCTL_SET_REPARSE_POINT:
406                 case FSCTL_SET_SPARSE:
407                 case FSCTL_SET_ZERO_DATA:
408                 case FSCTL_UNLOCK_VOLUME:
409                 case IOCTL_DISK_CHECK_VERIFY:
410                 case IOCTL_DISK_EJECT_MEDIA:
411                 case IOCTL_DISK_FORMAT_TRACKS:
412                 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
413                 case IOCTL_DISK_GET_DRIVE_LAYOUT:
414                 case IOCTL_DISK_GET_MEDIA_TYPES:
415                 case IOCTL_DISK_GET_PARTITION_INFO:
416                 case IOCTL_DISK_LOAD_MEDIA:
417                 case IOCTL_DISK_MEDIA_REMOVAL:
418                 case IOCTL_DISK_PERFORMANCE:
419                 case IOCTL_DISK_REASSIGN_BLOCKS:
420                 case IOCTL_DISK_SET_DRIVE_LAYOUT:
421                 case IOCTL_DISK_SET_PARTITION_INFO:
422                 case IOCTL_DISK_VERIFY:
423                 case IOCTL_SERIAL_LSRMST_INSERT:
424                 case IOCTL_STORAGE_CHECK_VERIFY:
425                 case IOCTL_STORAGE_EJECT_MEDIA:
426                 case IOCTL_STORAGE_GET_MEDIA_TYPES:
427                 case IOCTL_STORAGE_LOAD_MEDIA:
428                 case IOCTL_STORAGE_MEDIA_REMOVAL:
429                         FIXME( "unimplemented dwIoControlCode=%08lx\n", dwIoControlCode);
430                         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
431                         return FALSE;
432                         break;
433                 default:
434                         FIXME( "ignored dwIoControlCode=%08lx\n",dwIoControlCode);
435                         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
436                         return FALSE;
437                         break;
438                 }
439         }
440         return FALSE;
441 }
442  
443 /***********************************************************************
444  *           DeviceIo_VTDAPI
445  */
446 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
447                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
448                               LPDWORD lpcbBytesReturned,
449                               LPOVERLAPPED lpOverlapped)
450 {
451     BOOL retv = TRUE;
452
453     switch (dwIoControlCode)
454     {
455     case 5:
456         if (lpvOutBuffer && (cbOutBuffer>=4))
457             *(DWORD*)lpvOutBuffer = GetTickCount();
458
459         if (lpcbBytesReturned)
460             *lpcbBytesReturned = 4;
461
462         break;
463
464     default:
465         FIXME( "Control %ld not implemented\n", dwIoControlCode);
466         retv = FALSE;
467         break;
468     }
469
470     return retv;
471 }
472
473
474
475
476
477 /***********************************************************************
478  *           VxDCall                   (KERNEL32.[1-9])
479  */
480 void VxDCall( DWORD service, CONTEXT86 *context )
481 {
482     DWORD ret = 0xffffffff; /* FIXME */
483     int i;
484
485     TRACE( "(%08lx, ...)\n", service);
486
487     for (i = 0; VxDList[i].name; i++)
488         if (VxDList[i].id == HIWORD(service))
489             break;
490
491     if (!VxDList[i].name)
492         FIXME( "Unknown VxD (%08lx)\n", service);
493     else if (!VxDList[i].vxdcall)
494         FIXME( "Unimplemented VxD (%08lx)\n", service);
495     else
496         ret = VxDList[i].vxdcall( service, context );
497
498     EAX_reg( context ) = ret;
499 }
500
501
502 /***********************************************************************
503  *           VxDCall_VMM
504  */
505 static DWORD VxDCall_VMM( DWORD service, CONTEXT86 *context )
506 {
507     switch ( LOWORD(service) )
508     {
509     case 0x0011:  /* RegOpenKey */
510     {
511         HKEY    hkey       = (HKEY)  stack32_pop( context );
512         LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
513         LPHKEY  retkey     = (LPHKEY)stack32_pop( context );
514         return RegOpenKeyA( hkey, lpszSubKey, retkey );
515     }
516
517     case 0x0012:  /* RegCreateKey */
518     {
519         HKEY    hkey       = (HKEY)  stack32_pop( context );
520         LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
521         LPHKEY  retkey     = (LPHKEY)stack32_pop( context );
522         return RegCreateKeyA( hkey, lpszSubKey, retkey );
523     }
524
525     case 0x0013:  /* RegCloseKey */
526     {
527         HKEY    hkey       = (HKEY)stack32_pop( context );
528         return RegCloseKey( hkey );
529     }
530
531     case 0x0014:  /* RegDeleteKey */
532     {
533         HKEY    hkey       = (HKEY)  stack32_pop( context );
534         LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
535         return RegDeleteKeyA( hkey, lpszSubKey );
536     }
537
538     case 0x0015:  /* RegSetValue */
539     {
540         HKEY    hkey       = (HKEY)  stack32_pop( context );
541         LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
542         DWORD   dwType     = (DWORD) stack32_pop( context );
543         LPCSTR  lpszData   = (LPCSTR)stack32_pop( context );
544         DWORD   cbData     = (DWORD) stack32_pop( context );
545         return RegSetValueA( hkey, lpszSubKey, dwType, lpszData, cbData );
546     }
547
548     case 0x0016:  /* RegDeleteValue */
549     {
550         HKEY    hkey       = (HKEY) stack32_pop( context );
551         LPSTR   lpszValue  = (LPSTR)stack32_pop( context );
552         return RegDeleteValueA( hkey, lpszValue );
553     }
554
555     case 0x0017:  /* RegQueryValue */
556     {
557         HKEY    hkey       = (HKEY)   stack32_pop( context );
558         LPSTR   lpszSubKey = (LPSTR)  stack32_pop( context );
559         LPSTR   lpszData   = (LPSTR)  stack32_pop( context );
560         LPDWORD lpcbData   = (LPDWORD)stack32_pop( context );
561         return RegQueryValueA( hkey, lpszSubKey, lpszData, lpcbData );
562     }
563
564     case 0x0018:  /* RegEnumKey */
565     {
566         HKEY    hkey       = (HKEY) stack32_pop( context );
567         DWORD   iSubkey    = (DWORD)stack32_pop( context );
568         LPSTR   lpszName   = (LPSTR)stack32_pop( context );
569         DWORD   lpcchName  = (DWORD)stack32_pop( context );
570         return RegEnumKeyA( hkey, iSubkey, lpszName, lpcchName );
571     }
572
573     case 0x0019:  /* RegEnumValue */
574     {
575         HKEY    hkey       = (HKEY)   stack32_pop( context );
576         DWORD   iValue     = (DWORD)  stack32_pop( context );
577         LPSTR   lpszValue  = (LPSTR)  stack32_pop( context );
578         LPDWORD lpcchValue = (LPDWORD)stack32_pop( context );
579         LPDWORD lpReserved = (LPDWORD)stack32_pop( context );
580         LPDWORD lpdwType   = (LPDWORD)stack32_pop( context );
581         LPBYTE  lpbData    = (LPBYTE) stack32_pop( context );
582         LPDWORD lpcbData   = (LPDWORD)stack32_pop( context );
583         return RegEnumValueA( hkey, iValue, lpszValue, lpcchValue, 
584                               lpReserved, lpdwType, lpbData, lpcbData );
585     }
586
587     case 0x001A:  /* RegQueryValueEx */
588     {
589         HKEY    hkey       = (HKEY)   stack32_pop( context );
590         LPSTR   lpszValue  = (LPSTR)  stack32_pop( context );
591         LPDWORD lpReserved = (LPDWORD)stack32_pop( context );
592         LPDWORD lpdwType   = (LPDWORD)stack32_pop( context );
593         LPBYTE  lpbData    = (LPBYTE) stack32_pop( context );
594         LPDWORD lpcbData   = (LPDWORD)stack32_pop( context );
595         return RegQueryValueExA( hkey, lpszValue, lpReserved, 
596                                  lpdwType, lpbData, lpcbData );
597     }
598
599     case 0x001B:  /* RegSetValueEx */
600     {
601         HKEY    hkey       = (HKEY)  stack32_pop( context );
602         LPSTR   lpszValue  = (LPSTR) stack32_pop( context );
603         DWORD   dwReserved = (DWORD) stack32_pop( context );
604         DWORD   dwType     = (DWORD) stack32_pop( context );
605         LPBYTE  lpbData    = (LPBYTE)stack32_pop( context );
606         DWORD   cbData     = (DWORD) stack32_pop( context );
607         return RegSetValueExA( hkey, lpszValue, dwReserved, 
608                                dwType, lpbData, cbData );
609     }
610
611     case 0x001C:  /* RegFlushKey */
612     {
613         HKEY    hkey       = (HKEY)stack32_pop( context );
614         return RegFlushKey( hkey );
615     }
616
617     case 0x001D:  /* RegQueryInfoKey */
618     {
619         /* NOTE: This VxDCall takes only a subset of the parameters that the
620                  corresponding Win32 API call does. The implementation in Win95
621                  ADVAPI32 sets all output parameters not mentioned here to zero. */
622
623         HKEY    hkey              = (HKEY)   stack32_pop( context );
624         LPDWORD lpcSubKeys        = (LPDWORD)stack32_pop( context );
625         LPDWORD lpcchMaxSubKey    = (LPDWORD)stack32_pop( context );
626         LPDWORD lpcValues         = (LPDWORD)stack32_pop( context );
627         LPDWORD lpcchMaxValueName = (LPDWORD)stack32_pop( context );
628         LPDWORD lpcchMaxValueData = (LPDWORD)stack32_pop( context );
629         return RegQueryInfoKeyA( hkey, NULL, NULL, NULL, lpcSubKeys, lpcchMaxSubKey,
630                                  NULL, lpcValues, lpcchMaxValueName, lpcchMaxValueData,
631                                  NULL, NULL );
632     }
633
634     case 0x0021:  /* RegLoadKey */
635     {
636         HKEY    hkey       = (HKEY)  stack32_pop( context );
637         LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
638         LPCSTR  lpszFile   = (LPCSTR)stack32_pop( context );
639         return RegLoadKeyA( hkey, lpszSubKey, lpszFile );
640     }
641
642     case 0x0022:  /* RegUnLoadKey */
643     {
644         HKEY    hkey       = (HKEY)  stack32_pop( context );
645         LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
646         return RegUnLoadKeyA( hkey, lpszSubKey );
647     }
648
649     case 0x0023:  /* RegSaveKey */
650     {
651         HKEY    hkey       = (HKEY)  stack32_pop( context );
652         LPCSTR  lpszFile   = (LPCSTR)stack32_pop( context );
653         LPSECURITY_ATTRIBUTES sa = (LPSECURITY_ATTRIBUTES)stack32_pop( context );
654         return RegSaveKeyA( hkey, lpszFile, sa );
655     }
656
657 #if 0 /* Functions are not yet implemented in misc/registry.c */
658     case 0x0024:  /* RegRemapPreDefKey */
659     case 0x0026:  /* RegQueryMultipleValues */
660 #endif
661
662     case 0x0027:  /* RegReplaceKey */
663     {
664         HKEY    hkey       = (HKEY)  stack32_pop( context );
665         LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
666         LPCSTR  lpszNewFile= (LPCSTR)stack32_pop( context );
667         LPCSTR  lpszOldFile= (LPCSTR)stack32_pop( context );
668         return RegReplaceKeyA( hkey, lpszSubKey, lpszNewFile, lpszOldFile );
669     }
670     case 0x0000: /* PageReserve */
671       {
672         LPVOID address;
673         LPVOID ret;
674         DWORD psize = VIRTUAL_GetPageSize();
675         ULONG page   = (ULONG) stack32_pop( context );
676         ULONG npages = (ULONG) stack32_pop( context );
677         ULONG flags  = (ULONG) stack32_pop( context );
678
679         FIXME("PageReserve: page: %08lx, npages: %08lx, flags: %08lx partial stub!\n",
680               page, npages, flags );
681
682         if ( page == PR_SYSTEM ) {
683           ERR("Can't reserve ring 1 memory\n");
684           return -1;
685         }
686         /* FIXME: This has to be handled seperatly, when we have seperate
687            address-spaces */
688         if ( page == PR_PRIVATE || page == PR_SHARED ) page = 0;
689         /* FIXME: Handle flags in some way */
690         address = (LPVOID )(page * psize); 
691         ret = VirtualAlloc ( address, ( npages * psize ), MEM_RESERVE, 0 );
692         FIXME("PageReserve: returning: %08lx\n", (DWORD )ret );
693         if ( ret == NULL )
694           return -1;
695         else
696           return (DWORD )ret;
697       }
698
699     case 0x0001: /* PageCommit */
700       {
701         LPVOID address;
702         LPVOID ret;
703         DWORD virt_perm;
704         DWORD psize = VIRTUAL_GetPageSize();
705         ULONG page   = (ULONG) stack32_pop( context );
706         ULONG npages = (ULONG) stack32_pop( context );
707         ULONG hpd  = (ULONG) stack32_pop( context );
708         ULONG pagerdata   = (ULONG) stack32_pop( context );
709         ULONG flags  = (ULONG) stack32_pop( context );
710
711         FIXME("PageCommit: page: %08lx, npages: %08lx, hpd: %08lx pagerdata: "
712               "%08lx, flags: %08lx partial stub\n",
713               page, npages, hpd, pagerdata, flags );
714         
715         if ( flags & PC_USER )
716           if ( flags & PC_WRITEABLE )
717             virt_perm = PAGE_EXECUTE_READWRITE;
718           else
719             virt_perm = PAGE_EXECUTE_READ;
720         else
721           virt_perm = PAGE_NOACCESS;
722
723         address = (LPVOID )(page * psize); 
724         ret = VirtualAlloc ( address, ( npages * psize ), MEM_COMMIT, virt_perm );
725         FIXME("PageCommit: Returning: %08lx\n", (DWORD )ret );
726         return (DWORD )ret;
727
728       }
729     case 0x0002: /* PageDecommit */
730       {
731         LPVOID address;
732         BOOL ret;
733         DWORD psize = VIRTUAL_GetPageSize();
734         ULONG page = (ULONG) stack32_pop( context );
735         ULONG npages = (ULONG) stack32_pop( context );
736         ULONG flags = (ULONG) stack32_pop( context );
737
738         FIXME("PageDecommit: page: %08lx, npages: %08lx, flags: %08lx partial stub\n",
739               page, npages, flags );
740         address = (LPVOID )( page * psize );
741         ret = VirtualFree ( address, ( npages * psize ), MEM_DECOMMIT ); 
742         FIXME("PageDecommit: Returning: %s\n", ret ? "TRUE" : "FALSE" );
743         return ret;
744       }
745     case 0x000d: /* PageModifyPermissions */
746       { 
747         DWORD pg_old_perm;
748         DWORD pg_new_perm;
749         DWORD virt_old_perm;
750         DWORD virt_new_perm;
751         MEMORY_BASIC_INFORMATION mbi;
752         LPVOID address;
753         DWORD psize = VIRTUAL_GetPageSize();
754         ULONG page = stack32_pop ( context );
755         ULONG npages = stack32_pop ( context );
756         ULONG permand = stack32_pop ( context );
757         ULONG permor = stack32_pop ( context );
758
759         FIXME("PageModifyPermissions %08lx %08lx %08lx %08lx partial stub\n",
760               page, npages, permand, permor );
761         address = (LPVOID )( page * psize );
762
763         VirtualQuery ( address, &mbi, sizeof ( MEMORY_BASIC_INFORMATION ));
764         virt_old_perm = mbi.Protect;
765
766         switch ( virt_old_perm & mbi.Protect ) {
767         case PAGE_READONLY:
768         case PAGE_EXECUTE:
769         case PAGE_EXECUTE_READ:
770           pg_old_perm = PC_USER;
771           break;
772         case PAGE_READWRITE:
773         case PAGE_WRITECOPY:
774         case PAGE_EXECUTE_READWRITE:
775         case PAGE_EXECUTE_WRITECOPY:
776           pg_old_perm = PC_USER | PC_WRITEABLE;
777           break; 
778         case PAGE_NOACCESS:
779         default:
780           pg_old_perm = 0;
781           break;
782         }       
783         pg_new_perm = pg_old_perm;
784         pg_new_perm &= permand & ~PC_STATIC;
785         pg_new_perm |= permor  & ~PC_STATIC;
786
787         virt_new_perm = ( virt_old_perm )  & ~0xff;
788         if ( pg_new_perm & PC_USER )
789         {
790           if ( pg_new_perm & PC_WRITEABLE )
791             virt_new_perm |= PAGE_EXECUTE_READWRITE;
792           else
793             virt_new_perm |= PAGE_EXECUTE_READ;
794         }
795   
796         if ( ! VirtualProtect ( address, ( npages * psize ), virt_new_perm, &virt_old_perm ) ) {
797           ERR("Can't change page permissions for %08lx\n", (DWORD )address );
798           return 0xffffffff;
799         }
800         FIXME("Returning: %08lx\n", pg_old_perm );
801         return pg_old_perm;
802       }
803     case 0x000a: /* PageFree */
804       {
805         BOOL ret;
806         LPVOID hmem = (LPVOID) stack32_pop( context );
807         DWORD flags = (DWORD ) stack32_pop( context );
808         
809         FIXME("PageFree: hmem: %08lx, flags: %08lx partial stub\n",
810               (DWORD )hmem, flags );
811
812         ret = VirtualFree ( hmem, 0, MEM_RELEASE );
813         EAX_reg( context ) = ret;
814         FIXME("Returning: %d\n", ret );
815
816         return 0;
817       }
818     case 0x001e: /* GetDemandPageInfo */
819       {
820          DWORD dinfo = (DWORD)stack32_pop( context );
821          DWORD flags = (DWORD)stack32_pop( context );   
822
823          /* GetDemandPageInfo is supposed to fill out the struct at
824           * "dinfo" with various low-level memory management information.
825           * Apps are certainly not supposed to call this, although it's
826           * demoed and documented by Pietrek on pages 441-443 of "Windows
827           * 95 System Programming Secrets" if any program needs a real
828           * implementation of this.
829           */
830
831          FIXME("GetDemandPageInfo(%08lx %08lx): stub!\n", dinfo, flags);
832
833          return 0;
834       }
835     default:
836         if (LOWORD(service) < N_VMM_SERVICE)
837             FIXME( "Unimplemented service %s (%08lx)\n",
838                           VMM_Service_Name[LOWORD(service)], service);
839         else
840             FIXME( "Unknown service %08lx\n", service);
841         break;
842     }
843
844     return 0xffffffff;  /* FIXME */
845 }
846
847 /***********************************************************************
848  *           DeviceIo_IFSMgr
849  * NOTES
850  *   The ioctls is used by 'MSNET32.DLL'.
851  *
852  *   I have been unable to uncover any documentation about the ioctls so 
853  *   the implementation of the cases IFS_IOCTL_21 and IFS_IOCTL_2F are
854  *   based on a resonable guesses on information found in the Windows 95 DDK.
855  *   
856  */
857
858 /*
859  * IFSMgr DeviceIO service
860  */
861
862 #define IFS_IOCTL_21                100
863 #define IFS_IOCTL_2F                101
864 #define IFS_IOCTL_GET_RES           102
865 #define IFS_IOCTL_GET_NETPRO_NAME_A 103
866
867 struct win32apireq {
868         unsigned long   ar_proid;
869         unsigned long   ar_eax;         
870         unsigned long   ar_ebx; 
871         unsigned long   ar_ecx; 
872         unsigned long   ar_edx; 
873         unsigned long   ar_esi; 
874         unsigned long   ar_edi;
875         unsigned long   ar_ebp;         
876         unsigned short  ar_error;
877         unsigned short  ar_pad;
878 };
879
880 static void win32apieq_2_CONTEXT(struct win32apireq *pIn,CONTEXT86 *pCxt)
881 {
882         memset(pCxt,0,sizeof(*pCxt));
883
884         pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
885         pCxt->Eax = pIn->ar_eax;
886         pCxt->Ebx = pIn->ar_ebx;
887         pCxt->Ecx = pIn->ar_ecx;
888         pCxt->Edx = pIn->ar_edx;
889         pCxt->Esi = pIn->ar_esi;
890         pCxt->Edi = pIn->ar_edi;
891
892         /* FIXME: Only partial CONTEXT86_CONTROL */
893         pCxt->Ebp = pIn->ar_ebp;
894
895         /* FIXME: pIn->ar_proid ignored */
896         /* FIXME: pIn->ar_error ignored */
897         /* FIXME: pIn->ar_pad ignored */
898 }
899
900 static void CONTEXT_2_win32apieq(CONTEXT86 *pCxt,struct win32apireq *pOut)
901 {
902         memset(pOut,0,sizeof(struct win32apireq));
903
904         pOut->ar_eax = pCxt->Eax;
905         pOut->ar_ebx = pCxt->Ebx;
906         pOut->ar_ecx = pCxt->Ecx;
907         pOut->ar_edx = pCxt->Edx;
908         pOut->ar_esi = pCxt->Esi;
909         pOut->ar_edi = pCxt->Edi;
910
911         /* FIXME: Only partial CONTEXT86_CONTROL */
912         pOut->ar_ebp = pCxt->Ebp;
913
914         /* FIXME: pOut->ar_proid ignored */
915         /* FIXME: pOut->ar_error ignored */
916         /* FIXME: pOut->ar_pad ignored */
917 }
918
919 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
920                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
921                               LPDWORD lpcbBytesReturned,
922                               LPOVERLAPPED lpOverlapped)
923 {
924     BOOL retv = TRUE;
925         TRACE("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
926                         dwIoControlCode,
927                         lpvInBuffer,cbInBuffer,
928                         lpvOutBuffer,cbOutBuffer,
929                         lpcbBytesReturned,
930                         lpOverlapped);
931
932     switch (dwIoControlCode)
933     {
934         case IFS_IOCTL_21:
935         case IFS_IOCTL_2F:{
936                 CONTEXT86 cxt;
937                 struct win32apireq *pIn=(struct win32apireq *) lpvInBuffer;
938                 struct win32apireq *pOut=(struct win32apireq *) lpvOutBuffer;
939
940                 TRACE(
941                         "Control '%s': "
942                         "proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
943                         "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx, ebp=0x%08lx, "
944                         "error=0x%04x, pad=0x%04x\n",
945                         (dwIoControlCode==IFS_IOCTL_21)?"IFS_IOCTL_21":"IFS_IOCTL_2F",
946                         pIn->ar_proid, pIn->ar_eax, pIn->ar_ebx, pIn->ar_ecx,
947                         pIn->ar_edx, pIn->ar_esi, pIn->ar_edi, pIn->ar_ebp,
948                         pIn->ar_error, pIn->ar_pad
949                 );                              
950                 
951                 win32apieq_2_CONTEXT(pIn,&cxt);
952
953                 if(dwIoControlCode==IFS_IOCTL_21)
954                 {
955                         DOS3Call(&cxt); /* Call int 21h */
956                 } else {
957                         INT_Int2fHandler(&cxt); /* Call int 2Fh */
958                 }
959                 
960                 CONTEXT_2_win32apieq(&cxt,pOut);
961                         
962         retv = TRUE;
963         } break;
964         case IFS_IOCTL_GET_RES:{
965         FIXME( "Control 'IFS_IOCTL_GET_RES' not implemented\n");
966         retv = FALSE;
967         } break;
968         case IFS_IOCTL_GET_NETPRO_NAME_A:{
969         FIXME( "Control 'IFS_IOCTL_GET_NETPRO_NAME_A' not implemented\n");
970         retv = FALSE;
971         } break;         
972     default:
973         FIXME( "Control %ld not implemented\n", dwIoControlCode);
974         retv = FALSE;
975     }
976
977     return retv;
978 }
979
980 /********************************************************************************
981  *      VxDCall_VWin32
982  *
983  *  Service numbers taken from page 448 of Pietrek's "Windows 95 System
984  *  Progrmaming Secrets".  Parameters from experimentation on real Win98.
985  *
986  */
987
988 static DWORD VxDCall_VWin32( DWORD service, CONTEXT86 *context )
989 {
990   switch ( LOWORD(service) )
991     {
992     case 0x0000: /* GetVersion */
993     {
994         DWORD vers = VERSION_GetVersion();
995         switch (vers)
996         {
997         case WIN31:
998           return(0x0301);  /* Windows 3.1 */
999           break;
1000
1001         case WIN95:
1002           return(0x0400);  /* Win95 aka 4.0 */
1003           break;
1004
1005         case WIN98:
1006           return(0x040a);  /* Win98 aka 4.10 */
1007           break;
1008
1009         case NT351:
1010         case NT40:
1011           ERR("VxDCall when emulating NT???\n");
1012           break;
1013
1014         default:
1015           WARN("Unknown version %lx\n", vers);
1016           break;
1017         }
1018
1019         return(0x040a); /* default to win98 */
1020     }
1021     break;
1022
1023     case 0x0020: /* Get VMCPD Version */
1024     {
1025         DWORD parm = (DWORD) stack32_pop(context);
1026
1027         FIXME("Get VMCPD Version(%08lx): partial stub!\n", parm);
1028
1029         /* FIXME: This is what Win98 returns, it may
1030          *        not be correct in all situations.
1031          *        It makes Bleem! happy though.
1032          */
1033
1034         return 0x0405;
1035     }
1036
1037     case 0x0029: /* Int31/DPMI dispatch */
1038     {
1039         DWORD callnum = (DWORD) stack32_pop(context);
1040         DWORD parm    = (DWORD) stack32_pop(context);
1041  
1042         TRACE("Int31/DPMI dispatch(%08lx)\n", callnum);
1043
1044         AX_reg(context) = callnum;
1045         CX_reg(context) = parm;  
1046         INT_Int31Handler(context);
1047
1048         return(AX_reg(context));
1049     }
1050     break;
1051
1052     case 0x002a: /* Int41 dispatch - parm = int41 service number */
1053     {
1054         DWORD callnum = (DWORD) stack32_pop(context);
1055
1056         return callnum; /* FIXME: should really call INT_Int41Handler() */
1057     }
1058     break;
1059
1060     default:
1061       FIXME("Unknown VWin32 service %08lx\n", service);
1062       break;
1063     }
1064
1065   return 0xffffffff;
1066 }
1067                          
1068
1069  
1070 /***********************************************************************
1071  *           DeviceIo_VWin32
1072  */
1073
1074 static void DIOCRegs_2_CONTEXT( DIOC_REGISTERS *pIn, CONTEXT86 *pCxt )
1075 {
1076     memset( pCxt, 0, sizeof(*pCxt) );
1077     /* Note: segment registers == 0 means that CTX_SEG_OFF_TO_LIN
1078              will interpret 32-bit register contents as linear pointers */
1079
1080     pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
1081     pCxt->Eax = pIn->reg_EAX;
1082     pCxt->Ebx = pIn->reg_EBX;
1083     pCxt->Ecx = pIn->reg_ECX;
1084     pCxt->Edx = pIn->reg_EDX;
1085     pCxt->Esi = pIn->reg_ESI;
1086     pCxt->Edi = pIn->reg_EDI;
1087
1088     /* FIXME: Only partial CONTEXT86_CONTROL */
1089     pCxt->EFlags = pIn->reg_Flags;
1090 }
1091
1092 static void CONTEXT_2_DIOCRegs( CONTEXT86 *pCxt, DIOC_REGISTERS *pOut )
1093 {
1094     memset( pOut, 0, sizeof(DIOC_REGISTERS) );
1095
1096     pOut->reg_EAX = pCxt->Eax;
1097     pOut->reg_EBX = pCxt->Ebx;
1098     pOut->reg_ECX = pCxt->Ecx;
1099     pOut->reg_EDX = pCxt->Edx;
1100     pOut->reg_ESI = pCxt->Esi;
1101     pOut->reg_EDI = pCxt->Edi;
1102
1103     /* FIXME: Only partial CONTEXT86_CONTROL */
1104     pOut->reg_Flags = pCxt->EFlags;
1105 }
1106
1107
1108 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, 
1109                               LPVOID lpvInBuffer, DWORD cbInBuffer,
1110                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
1111                               LPDWORD lpcbBytesReturned,
1112                               LPOVERLAPPED lpOverlapped)
1113 {
1114     BOOL retv = TRUE;
1115
1116     switch (dwIoControlCode)
1117     {
1118     case VWIN32_DIOC_DOS_IOCTL:
1119     case VWIN32_DIOC_DOS_INT13:
1120     case VWIN32_DIOC_DOS_INT25:
1121     case VWIN32_DIOC_DOS_INT26:
1122         case VWIN32_DIOC_DOS_DRIVEINFO:
1123     {
1124         CONTEXT86 cxt;
1125         DIOC_REGISTERS *pIn  = (DIOC_REGISTERS *)lpvInBuffer;
1126         DIOC_REGISTERS *pOut = (DIOC_REGISTERS *)lpvOutBuffer;
1127
1128         TRACE( "Control '%s': "
1129                "eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
1130                "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx ",
1131                (dwIoControlCode == VWIN32_DIOC_DOS_IOCTL)? "VWIN32_DIOC_DOS_IOCTL" :
1132                (dwIoControlCode == VWIN32_DIOC_DOS_INT13)? "VWIN32_DIOC_DOS_INT13" :
1133                (dwIoControlCode == VWIN32_DIOC_DOS_INT25)? "VWIN32_DIOC_DOS_INT25" :
1134                (dwIoControlCode == VWIN32_DIOC_DOS_INT26)? "VWIN32_DIOC_DOS_INT26" : 
1135                (dwIoControlCode == VWIN32_DIOC_DOS_DRIVEINFO)? "VWIN32_DIOC_DOS_DRIVEINFO" :  "???",
1136                pIn->reg_EAX, pIn->reg_EBX, pIn->reg_ECX,
1137                pIn->reg_EDX, pIn->reg_ESI, pIn->reg_EDI );
1138
1139         DIOCRegs_2_CONTEXT( pIn, &cxt );
1140
1141         switch (dwIoControlCode)
1142         {
1143         case VWIN32_DIOC_DOS_IOCTL: DOS3Call( &cxt ); break; /* Call int 21h */
1144         case VWIN32_DIOC_DOS_INT13: INT_Int13Handler( &cxt ); break;
1145         case VWIN32_DIOC_DOS_INT25: INT_Int25Handler( &cxt ); break;
1146         case VWIN32_DIOC_DOS_INT26: INT_Int26Handler( &cxt ); break;
1147                 case VWIN32_DIOC_DOS_DRIVEINFO: DOS3Call( &cxt ); break; /* Call int 21h 730x */
1148         }
1149
1150         CONTEXT_2_DIOCRegs( &cxt, pOut );
1151     }
1152     break;
1153
1154     case VWIN32_DIOC_SIMCTRLC:
1155         FIXME( "Control VWIN32_DIOC_SIMCTRLC not implemented\n");
1156         retv = FALSE;
1157         break;
1158
1159     default:
1160         FIXME( "Unknown Control %ld\n", dwIoControlCode);
1161         retv = FALSE;
1162         break;
1163     }
1164
1165     return retv;
1166 }
1167
1168 /* this is the main multimedia device loader */
1169 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode, 
1170                               LPVOID lpvInBuffer, DWORD cbInBuffer,
1171                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
1172                               LPDWORD lpcbBytesReturned,
1173                               LPOVERLAPPED lpOverlapped)
1174 {
1175         FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
1176             dwIoControlCode,
1177             lpvInBuffer,cbInBuffer,
1178             lpvOutBuffer,cbOutBuffer,
1179             lpcbBytesReturned,
1180             lpOverlapped
1181         );
1182         switch (dwIoControlCode) {
1183         case 5:
1184                 /* Hmm. */
1185                 *(DWORD*)lpvOutBuffer=0;
1186                 *lpcbBytesReturned=4;
1187                 return TRUE;
1188         }
1189         return FALSE;
1190 }
1191 /* this is used by some Origin games */
1192 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode, 
1193                               LPVOID lpvInBuffer, DWORD cbInBuffer,
1194                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
1195                               LPDWORD lpcbBytesReturned,
1196                               LPOVERLAPPED lpOverlapped)
1197 {
1198         switch (dwIoControlCode) {
1199         case 1: /* version */
1200                 *(LPDWORD)lpvOutBuffer = 0x20004; /* WC SecretOps */
1201                 break;
1202         case 9: /* debug output */
1203                 ERR("MONODEBG: %s\n",debugstr_a(lpvInBuffer));
1204                 break;
1205         default:
1206                 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
1207                         dwIoControlCode,
1208                         lpvInBuffer,cbInBuffer,
1209                         lpvOutBuffer,cbOutBuffer,
1210                         lpcbBytesReturned,
1211                         lpOverlapped
1212                 );
1213                 break;
1214         }
1215         return TRUE;
1216 }
1217 /* pccard */
1218 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode, 
1219                               LPVOID lpvInBuffer, DWORD cbInBuffer,
1220                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
1221                               LPDWORD lpcbBytesReturned,
1222                               LPOVERLAPPED lpOverlapped)
1223 {
1224         switch (dwIoControlCode) {
1225         case 0x0000: /* PCCARD_Get_Version */
1226         case 0x0001: /* PCCARD_Card_Services */
1227         default:
1228                 FIXME( "(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
1229                         dwIoControlCode,
1230                         lpvInBuffer,cbInBuffer,
1231                         lpvOutBuffer,cbOutBuffer,
1232                         lpcbBytesReturned,
1233                         lpOverlapped
1234                 );
1235                 break;
1236         }
1237         return FALSE;
1238 }
1239
1240 /***********************************************************************
1241  *              OpenVxDHandle
1242  */
1243 DWORD   WINAPI  OpenVxDHandle(DWORD pmt)
1244 {
1245         FIXME( "(0x%08lx) stub!\n", pmt);
1246         return 0;
1247 }