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