Added DebugBreak.
[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 <errno.h>
11 #include <assert.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/mman.h>
17 #include <fcntl.h>
18 #include <string.h>
19 #include <stdarg.h>
20 #include <time.h>
21 #include "winbase.h"
22 #include "winreg.h"
23 #include "winerror.h"
24 #include "file.h"
25 #include "process.h"
26 #include "mmsystem.h"
27 #include "heap.h"
28 #include "winioctl.h"
29 #include "winnt.h"
30 #include "msdos.h"
31 #include "miscemu.h"
32 #include "server.h"
33 #include "debugtools.h"
34
35 DEFAULT_DEBUG_CHANNEL(win32)
36
37
38 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, 
39                               LPVOID lpvInBuffer, DWORD cbInBuffer,
40                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
41                               LPDWORD lpcbBytesReturned,
42                               LPOVERLAPPED lpOverlapped);
43 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode, 
44                               LPVOID lpvInBuffer, DWORD cbInBuffer,
45                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
46                               LPDWORD lpcbBytesReturned,
47                               LPOVERLAPPED lpOverlapped);
48 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode, 
49                               LPVOID lpvInBuffer, DWORD cbInBuffer,
50                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
51                               LPDWORD lpcbBytesReturned,
52                               LPOVERLAPPED lpOverlapped);
53
54 static DWORD VxDCall_VMM( DWORD service, va_list args );
55
56 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, 
57                               LPVOID lpvInBuffer, DWORD cbInBuffer,
58                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
59                               LPDWORD lpcbBytesReturned,
60                               LPOVERLAPPED lpOverlapped);
61
62 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, 
63                               LPVOID lpvInBuffer, DWORD cbInBuffer,
64                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
65                               LPDWORD lpcbBytesReturned,
66                               LPOVERLAPPED lpOverlapped);
67
68 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode, 
69                               LPVOID lpvInBuffer, DWORD cbInBuffer,
70                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
71                               LPDWORD lpcbBytesReturned,
72                               LPOVERLAPPED lpOverlapped);
73 /*
74  * VxD names are taken from the Win95 DDK
75  */
76
77 struct VxDInfo
78 {
79     LPCSTR  name;
80     WORD    id;
81     DWORD (*vxdcall)(DWORD, va_list);
82     BOOL  (*deviceio)(DWORD, LPVOID, DWORD, 
83                         LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
84 };
85
86 static const struct VxDInfo VxDList[] = 
87 {
88     /* Standard VxD IDs */
89     { "VMM",      0x0001, VxDCall_VMM, NULL },
90     { "DEBUG",    0x0002, NULL, NULL },
91     { "VPICD",    0x0003, NULL, NULL },
92     { "VDMAD",    0x0004, NULL, NULL },
93     { "VTD",      0x0005, NULL, NULL },
94     { "V86MMGR",  0x0006, NULL, NULL },
95     { "PAGESWAP", 0x0007, NULL, NULL },
96     { "PARITY",   0x0008, NULL, NULL },
97     { "REBOOT",   0x0009, NULL, NULL },
98     { "VDD",      0x000A, NULL, NULL },
99     { "VSD",      0x000B, NULL, NULL },
100     { "VMD",      0x000C, NULL, NULL },
101     { "VKD",      0x000D, NULL, NULL },
102     { "VCD",      0x000E, NULL, NULL },
103     { "VPD",      0x000F, NULL, NULL },
104     { "BLOCKDEV", 0x0010, NULL, NULL },
105     { "VMCPD",    0x0011, NULL, NULL },
106     { "EBIOS",    0x0012, NULL, NULL },
107     { "BIOSXLAT", 0x0013, NULL, NULL },
108     { "VNETBIOS", 0x0014, NULL, NULL },
109     { "DOSMGR",   0x0015, NULL, NULL },
110     { "WINLOAD",  0x0016, NULL, NULL },
111     { "SHELL",    0x0017, NULL, NULL },
112     { "VMPOLL",   0x0018, NULL, NULL },
113     { "VPROD",    0x0019, NULL, NULL },
114     { "DOSNET",   0x001A, NULL, NULL },
115     { "VFD",      0x001B, NULL, NULL },
116     { "VDD2",     0x001C, NULL, NULL },
117     { "WINDEBUG", 0x001D, NULL, NULL },
118     { "TSRLOAD",  0x001E, NULL, NULL },
119     { "BIOSHOOK", 0x001F, NULL, NULL },
120     { "INT13",    0x0020, NULL, NULL },
121     { "PAGEFILE", 0x0021, NULL, NULL },
122     { "SCSI",     0x0022, NULL, NULL },
123     { "MCA_POS",  0x0023, NULL, NULL },
124     { "SCSIFD",   0x0024, NULL, NULL },
125     { "VPEND",    0x0025, NULL, NULL },
126     { "VPOWERD",  0x0026, NULL, NULL },
127     { "VXDLDR",   0x0027, NULL, NULL },
128     { "NDIS",     0x0028, NULL, NULL },
129     { "BIOS_EXT", 0x0029, NULL, NULL },
130     { "VWIN32",   0x002A, NULL, DeviceIo_VWin32 },
131     { "VCOMM",    0x002B, NULL, NULL },
132     { "SPOOLER",  0x002C, NULL, NULL },
133     { "WIN32S",   0x002D, NULL, NULL },
134     { "DEBUGCMD", 0x002E, NULL, NULL },
135
136     { "VNB",      0x0031, NULL, NULL },
137     { "SERVER",   0x0032, NULL, NULL },
138     { "CONFIGMG", 0x0033, NULL, NULL },
139     { "DWCFGMG",  0x0034, NULL, NULL },
140     { "SCSIPORT", 0x0035, NULL, NULL },
141     { "VFBACKUP", 0x0036, NULL, NULL },
142     { "ENABLE",   0x0037, NULL, NULL },
143     { "VCOND",    0x0038, NULL, NULL },
144
145     { "EFAX",     0x003A, NULL, NULL },
146     { "DSVXD",    0x003B, NULL, NULL },
147     { "ISAPNP",   0x003C, NULL, NULL },
148     { "BIOS",     0x003D, NULL, NULL },
149     { "WINSOCK",  0x003E, NULL, NULL },
150     { "WSOCK",    0x003E, NULL, NULL },
151     { "WSIPX",    0x003F, NULL, NULL },
152     { "IFSMgr",   0x0040, NULL, DeviceIo_IFSMgr },
153     { "VCDFSD",   0x0041, NULL, NULL },
154     { "MRCI2",    0x0042, NULL, NULL },
155     { "PCI",      0x0043, NULL, NULL },
156     { "PELOADER", 0x0044, NULL, NULL },
157     { "EISA",     0x0045, NULL, NULL },
158     { "DRAGCLI",  0x0046, NULL, NULL },
159     { "DRAGSRV",  0x0047, NULL, NULL },
160     { "PERF",     0x0048, NULL, NULL },
161     { "AWREDIR",  0x0049, NULL, NULL },
162
163     /* Far East support */
164     { "ETEN",     0x0060, NULL, NULL },
165     { "CHBIOS",   0x0061, NULL, NULL },
166     { "VMSGD",    0x0062, NULL, NULL },
167     { "VPPID",    0x0063, NULL, NULL },
168     { "VIME",     0x0064, NULL, NULL },
169     { "VHBIOSD",  0x0065, NULL, NULL },
170
171     /* Multimedia OEM IDs */
172     { "VTDAPI",   0x0442, NULL, DeviceIo_VTDAPI },
173     { "MMDEVLDR", 0x044A, NULL, DeviceIo_MMDEVLDR },
174
175     /* Network Device IDs */
176     { "VNetSup",  0x0480, NULL, NULL },
177     { "VRedir",   0x0481, NULL, NULL },
178     { "VBrowse",  0x0482, NULL, NULL },
179     { "VSHARE",   0x0483, NULL, NULL },
180     { "IFSMgr",   0x0484, NULL, NULL },
181     { "MEMPROBE", 0x0485, NULL, NULL },
182     { "VFAT",     0x0486, NULL, NULL },
183     { "NWLINK",   0x0487, NULL, NULL },
184     { "VNWLINK",  0x0487, NULL, NULL },
185     { "NWSUP",    0x0487, NULL, NULL },
186     { "VTDI",     0x0488, NULL, NULL },
187     { "VIP",      0x0489, NULL, NULL },
188     { "VTCP",     0x048A, NULL, NULL },
189     { "VCache",   0x048B, NULL, NULL },
190     { "VUDP",     0x048C, NULL, NULL },
191     { "VAsync",   0x048D, NULL, NULL },
192     { "NWREDIR",  0x048E, NULL, NULL },
193     { "STAT80",   0x048F, NULL, NULL },
194     { "SCSIPORT", 0x0490, NULL, NULL },
195     { "FILESEC",  0x0491, NULL, NULL },
196     { "NWSERVER", 0x0492, NULL, NULL },
197     { "SECPROV",  0x0493, NULL, NULL },
198     { "NSCL",     0x0494, NULL, NULL },
199     { "WSTCP",    0x0495, NULL, NULL },
200     { "NDIS2SUP", 0x0496, NULL, NULL },
201     { "MSODISUP", 0x0497, NULL, NULL },
202     { "Splitter", 0x0498, NULL, NULL },
203     { "PPP",      0x0499, NULL, NULL },
204     { "VDHCP",    0x049A, NULL, NULL },
205     { "VNBT",     0x049B, NULL, NULL },
206     { "LOGGER",   0x049D, NULL, NULL },
207     { "EFILTER",  0x049E, NULL, NULL },
208     { "FFILTER",  0x049F, NULL, NULL },
209     { "TFILTER",  0x04A0, NULL, NULL },
210     { "AFILTER",  0x04A1, NULL, NULL },
211     { "IRLAMP",   0x04A2, NULL, NULL },
212
213     { "PCCARD",   0x097C, NULL, DeviceIo_PCCARD },
214
215     /* WINE additions, ids unknown */
216     { "MONODEBG.VXD", 0x4242, NULL, DeviceIo_MONODEBG },
217
218     { NULL,       0,      NULL, NULL }
219 };
220
221 /*
222  * VMM VxDCall service names are (mostly) taken from Stan Mitchell's
223  * "Inside the Windows 95 File System"
224  */
225
226 #define N_VMM_SERVICE 41
227
228 LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
229
230     "PageReserve",            /* 0x0000 */
231     "PageCommit",             /* 0x0001 */
232     "PageDecommit",           /* 0x0002 */
233     "PagerRegister",          /* 0x0003 */
234     "PagerQuery",             /* 0x0004 */
235     "HeapAllocate",           /* 0x0005 */
236     "ContextCreate",          /* 0x0006 */
237     "ContextDestroy",         /* 0x0007 */
238     "PageAttach",             /* 0x0008 */
239     "PageFlush",              /* 0x0009 */
240     "PageFree",               /* 0x000A */
241     "ContextSwitch",          /* 0x000B */
242     "HeapReAllocate",         /* 0x000C */
243     "PageModifyPerm",         /* 0x000D */
244     "PageQuery",              /* 0x000E */
245     "GetCurrentContext",      /* 0x000F */
246     "HeapFree",               /* 0x0010 */
247     "RegOpenKey",             /* 0x0011 */
248     "RegCreateKey",           /* 0x0012 */
249     "RegCloseKey",            /* 0x0013 */
250     "RegDeleteKey",           /* 0x0014 */
251     "RegSetValue",            /* 0x0015 */
252     "RegDeleteValue",         /* 0x0016 */
253     "RegQueryValue",          /* 0x0017 */
254     "RegEnumKey",             /* 0x0018 */
255     "RegEnumValue",           /* 0x0019 */
256     "RegQueryValueEx",        /* 0x001A */
257     "RegSetValueEx",          /* 0x001B */
258     "RegFlushKey",            /* 0x001C */
259     "RegQueryInfoKey",        /* 0x001D */
260     "GetDemandPageInfo",      /* 0x001E */
261     "BlockOnID",              /* 0x001F */
262     "SignalID",               /* 0x0020 */
263     "RegLoadKey",             /* 0x0021 */
264     "RegUnLoadKey",           /* 0x0022 */
265     "RegSaveKey",             /* 0x0023 */
266     "RegRemapPreDefKey",      /* 0x0024 */
267     "PageChangePager",        /* 0x0025 */
268     "RegQueryMultipleValues", /* 0x0026 */
269     "RegReplaceKey",          /* 0x0027 */
270     "<KERNEL32.101>"          /* 0x0028 -- What does this do??? */
271 };
272
273 HANDLE DEVICE_Open( LPCSTR filename, DWORD access,
274                       LPSECURITY_ATTRIBUTES sa )
275 {
276     const struct VxDInfo *info;
277
278     for (info = VxDList; info->name; info++)
279         if (!lstrcmpiA( info->name, filename ))
280             return FILE_CreateDevice( info->id | 0x10000, access, sa );
281
282     FIXME( "Unknown VxD %s\n", filename);
283     return FILE_CreateDevice( 0x10000, access, sa );
284 }
285
286 static const struct VxDInfo *DEVICE_GetInfo( HANDLE handle )
287 {
288     struct get_file_info_request req;
289     struct get_file_info_reply reply;
290
291     req.handle = handle;
292     CLIENT_SendRequest( REQ_GET_FILE_INFO, -1, 1, &req, sizeof(req) );
293     if (!CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) &&
294         (reply.type == FILE_TYPE_UNKNOWN) &&
295         (reply.attr & 0x10000))
296     {
297         const struct VxDInfo *info;
298
299         for (info = VxDList; info->name; info++)
300             if (info->id == LOWORD(reply.attr)) break;
301         return info;
302     }
303     return NULL;
304 }
305
306 /****************************************************************************
307  *              DeviceIoControl (KERNEL32.188)
308  * This is one of those big ugly nasty procedure which can do
309  * a million and one things when it comes to devices. It can also be
310  * used for VxD communication.
311  *
312  * A return value of FALSE indicates that something has gone wrong which
313  * GetLastError can decypher.
314  */
315 BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, 
316                               LPVOID lpvInBuffer, DWORD cbInBuffer,
317                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
318                               LPDWORD lpcbBytesReturned,
319                               LPOVERLAPPED lpOverlapped)
320 {
321         const struct VxDInfo *info;
322
323         TRACE( "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n",
324                hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
325                lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped  );
326
327         if (!(info = DEVICE_GetInfo( hDevice )))
328         {
329                 SetLastError( ERROR_INVALID_PARAMETER );
330                 return FALSE;
331         }
332
333         /* Check if this is a user defined control code for a VxD */
334         if( HIWORD( dwIoControlCode ) == 0 )
335         {
336                 if ( info->deviceio )
337                 {
338                         return info->deviceio( dwIoControlCode, 
339                                         lpvInBuffer, cbInBuffer, 
340                                         lpvOutBuffer, cbOutBuffer, 
341                                         lpcbBytesReturned, lpOverlapped );
342                 }
343                 else
344                 {
345                         /* FIXME: Set appropriate error */
346                         FIXME( "Unimplemented control %ld for VxD device %s\n", 
347                                dwIoControlCode, info->name ? info->name : "???" );
348                 }
349         }
350         else
351         {
352                 switch( dwIoControlCode )
353                 {
354                 case FSCTL_DELETE_REPARSE_POINT:
355                 case FSCTL_DISMOUNT_VOLUME:
356                 case FSCTL_GET_COMPRESSION:
357                 case FSCTL_GET_REPARSE_POINT:
358                 case FSCTL_LOCK_VOLUME:
359                 case FSCTL_QUERY_ALLOCATED_RANGES:
360                 case FSCTL_SET_COMPRESSION:
361                 case FSCTL_SET_REPARSE_POINT:
362                 case FSCTL_SET_SPARSE:
363                 case FSCTL_SET_ZERO_DATA:
364                 case FSCTL_UNLOCK_VOLUME:
365                 case IOCTL_DISK_CHECK_VERIFY:
366                 case IOCTL_DISK_EJECT_MEDIA:
367                 case IOCTL_DISK_FORMAT_TRACKS:
368                 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
369                 case IOCTL_DISK_GET_DRIVE_LAYOUT:
370                 case IOCTL_DISK_GET_MEDIA_TYPES:
371                 case IOCTL_DISK_GET_PARTITION_INFO:
372                 case IOCTL_DISK_LOAD_MEDIA:
373                 case IOCTL_DISK_MEDIA_REMOVAL:
374                 case IOCTL_DISK_PERFORMANCE:
375                 case IOCTL_DISK_REASSIGN_BLOCKS:
376                 case IOCTL_DISK_SET_DRIVE_LAYOUT:
377                 case IOCTL_DISK_SET_PARTITION_INFO:
378                 case IOCTL_DISK_VERIFY:
379                 case IOCTL_SERIAL_LSRMST_INSERT:
380                 case IOCTL_STORAGE_CHECK_VERIFY:
381                 case IOCTL_STORAGE_EJECT_MEDIA:
382                 case IOCTL_STORAGE_GET_MEDIA_TYPES:
383                 case IOCTL_STORAGE_LOAD_MEDIA:
384                 case IOCTL_STORAGE_MEDIA_REMOVAL:
385                         FIXME( "unimplemented dwIoControlCode=%08lx\n", dwIoControlCode);
386                         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
387                         return FALSE;
388                         break;
389                 default:
390                         FIXME( "ignored dwIoControlCode=%08lx\n",dwIoControlCode);
391                         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
392                         return FALSE;
393                         break;
394                 }
395         }
396         return FALSE;
397 }
398  
399 /***********************************************************************
400  *           DeviceIo_VTDAPI
401  */
402 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
403                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
404                               LPDWORD lpcbBytesReturned,
405                               LPOVERLAPPED lpOverlapped)
406 {
407     BOOL retv = TRUE;
408
409     switch (dwIoControlCode)
410     {
411     case 5:
412         if (lpvOutBuffer && (cbOutBuffer>=4))
413             *(DWORD*)lpvOutBuffer = timeGetTime();
414
415         if (lpcbBytesReturned)
416             *lpcbBytesReturned = 4;
417
418         break;
419
420     default:
421         FIXME( "Control %ld not implemented\n", dwIoControlCode);
422         retv = FALSE;
423         break;
424     }
425
426     return retv;
427 }
428
429
430
431
432
433 /***********************************************************************
434  *           VxDCall                   (KERNEL32.[1-9])
435  */
436 static DWORD VxDCall( DWORD service, ... )
437 {
438     DWORD ret = 0xffffffff; /* FIXME */
439     int i;
440
441     TRACE( "(%08lx, ...)\n", service);
442
443     for (i = 0; VxDList[i].name; i++)
444         if (VxDList[i].id == HIWORD(service))
445             break;
446
447     if (!VxDList[i].name)
448         FIXME( "Unknown VxD (%08lx)\n", service);
449     else if (!VxDList[i].vxdcall)
450         FIXME( "Unimplemented VxD (%08lx)\n", service);
451     else
452     {
453         va_list args;
454         va_start( args, service );
455         ret = VxDList[i].vxdcall( service, args );
456         va_end( args );
457     }
458     return ret;
459 }
460
461 DWORD WINAPI VxDCall0( DWORD service )
462 {
463     return VxDCall( service );
464 }
465
466 DWORD WINAPI VxDCall1( DWORD service, DWORD arg1 )
467 {
468     return VxDCall( service, arg1 );
469 }
470
471 DWORD WINAPI VxDCall2( DWORD service, DWORD arg1, DWORD arg2 )
472 {
473     return VxDCall( service, arg1, arg2 );
474 }
475
476 DWORD WINAPI VxDCall3( DWORD service, DWORD arg1, DWORD arg2, DWORD arg3 )
477 {
478     return VxDCall( service, arg1, arg2, arg3 );
479 }
480
481 DWORD WINAPI VxDCall4( DWORD service, DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4 )
482 {
483     return VxDCall( service, arg1, arg2, arg3, arg4 );
484 }
485
486 DWORD WINAPI VxDCall5( DWORD service, DWORD arg1, DWORD arg2, DWORD arg3,
487                        DWORD arg4, DWORD arg5 )
488 {
489     return VxDCall( service, arg1, arg2, arg3, arg4, arg5 );
490 }
491
492 DWORD WINAPI VxDCall6( DWORD service, DWORD arg1, DWORD arg2, DWORD arg3,
493                        DWORD arg4, DWORD arg5, DWORD arg6 )
494 {
495     return VxDCall( service, arg1, arg2, arg3, arg4, arg5, arg6 );
496 }
497
498 DWORD WINAPI VxDCall7( DWORD service, DWORD arg1, DWORD arg2, DWORD arg3,
499                        DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7 )
500 {
501     return VxDCall( service, arg1, arg2, arg3, arg4, arg5, arg6, arg7 );
502 }
503
504 DWORD WINAPI VxDCall8( DWORD service, DWORD arg1, DWORD arg2, DWORD arg3,
505                        DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8 )
506 {
507     return VxDCall( service, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 );
508 }
509
510 /***********************************************************************
511  *           VxDCall_VMM
512  */
513 static DWORD VxDCall_VMM( DWORD service, va_list args )
514 {
515     switch ( LOWORD(service) )
516     {
517     case 0x0011:  /* RegOpenKey */
518     {
519         HKEY    hkey       = va_arg( args, HKEY );
520         LPCSTR  lpszSubKey = va_arg( args, LPCSTR );
521         LPHKEY  retkey     = va_arg( args, LPHKEY );
522         return RegOpenKeyA( hkey, lpszSubKey, retkey );
523     }
524
525     case 0x0012:  /* RegCreateKey */
526     {
527         HKEY    hkey       = va_arg( args, HKEY );
528         LPCSTR  lpszSubKey = va_arg( args, LPCSTR );
529         LPHKEY  retkey     = va_arg( args, LPHKEY );
530         return RegCreateKeyA( hkey, lpszSubKey, retkey );
531     }
532
533     case 0x0013:  /* RegCloseKey */
534     {
535         HKEY    hkey       = va_arg( args, HKEY );
536         return RegCloseKey( hkey );
537     }
538
539     case 0x0014:  /* RegDeleteKey */
540     {
541         HKEY    hkey       = va_arg( args, HKEY );
542         LPCSTR  lpszSubKey = va_arg( args, LPCSTR );
543         return RegDeleteKeyA( hkey, lpszSubKey );
544     }
545
546     case 0x0015:  /* RegSetValue */
547     {
548         HKEY    hkey       = va_arg( args, HKEY );
549         LPCSTR  lpszSubKey = va_arg( args, LPCSTR );
550         DWORD   dwType     = va_arg( args, DWORD );
551         LPCSTR  lpszData   = va_arg( args, LPCSTR );
552         DWORD   cbData     = va_arg( args, DWORD );
553         return RegSetValueA( hkey, lpszSubKey, dwType, lpszData, cbData );
554     }
555
556     case 0x0016:  /* RegDeleteValue */
557     {
558         HKEY    hkey       = va_arg( args, HKEY );
559         LPSTR   lpszValue  = va_arg( args, LPSTR );
560         return RegDeleteValueA( hkey, lpszValue );
561     }
562
563     case 0x0017:  /* RegQueryValue */
564     {
565         HKEY    hkey       = va_arg( args, HKEY );
566         LPSTR   lpszSubKey = va_arg( args, LPSTR );
567         LPSTR   lpszData   = va_arg( args, LPSTR );
568         LPDWORD lpcbData   = va_arg( args, LPDWORD );
569         return RegQueryValueA( hkey, lpszSubKey, lpszData, lpcbData );
570     }
571
572     case 0x0018:  /* RegEnumKey */
573     {
574         HKEY    hkey       = va_arg( args, HKEY );
575         DWORD   iSubkey    = va_arg( args, DWORD );
576         LPSTR   lpszName   = va_arg( args, LPSTR );
577         DWORD   lpcchName  = va_arg( args, DWORD );
578         return RegEnumKeyA( hkey, iSubkey, lpszName, lpcchName );
579     }
580
581     case 0x0019:  /* RegEnumValue */
582     {
583         HKEY    hkey       = va_arg( args, HKEY );
584         DWORD   iValue     = va_arg( args, DWORD );
585         LPSTR   lpszValue  = va_arg( args, LPSTR );
586         LPDWORD lpcchValue = va_arg( args, LPDWORD );
587         LPDWORD lpReserved = va_arg( args, LPDWORD );
588         LPDWORD lpdwType   = va_arg( args, LPDWORD );
589         LPBYTE  lpbData    = va_arg( args, LPBYTE );
590         LPDWORD lpcbData   = va_arg( args, LPDWORD );
591         return RegEnumValueA( hkey, iValue, lpszValue, lpcchValue, 
592                               lpReserved, lpdwType, lpbData, lpcbData );
593     }
594
595     case 0x001A:  /* RegQueryValueEx */
596     {
597         HKEY    hkey       = va_arg( args, HKEY );
598         LPSTR   lpszValue  = va_arg( args, LPSTR );
599         LPDWORD lpReserved = va_arg( args, LPDWORD );
600         LPDWORD lpdwType   = va_arg( args, LPDWORD );
601         LPBYTE  lpbData    = va_arg( args, LPBYTE );
602         LPDWORD lpcbData   = va_arg( args, LPDWORD );
603         return RegQueryValueExA( hkey, lpszValue, lpReserved, 
604                                  lpdwType, lpbData, lpcbData );
605     }
606
607     case 0x001B:  /* RegSetValueEx */
608     {
609         HKEY    hkey       = va_arg( args, HKEY );
610         LPSTR   lpszValue  = va_arg( args, LPSTR );
611         DWORD   dwReserved = va_arg( args, DWORD );
612         DWORD   dwType     = va_arg( args, DWORD );
613         LPBYTE  lpbData    = va_arg( args, LPBYTE );
614         DWORD   cbData     = va_arg( args, DWORD );
615         return RegSetValueExA( hkey, lpszValue, dwReserved, 
616                                dwType, lpbData, cbData );
617     }
618
619     case 0x001C:  /* RegFlushKey */
620     {
621         HKEY    hkey       = va_arg( args, HKEY );
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              = va_arg( args, HKEY );
632         LPDWORD lpcSubKeys        = va_arg( args, LPDWORD );
633         LPDWORD lpcchMaxSubKey    = va_arg( args, LPDWORD );
634         LPDWORD lpcValues         = va_arg( args, LPDWORD );
635         LPDWORD lpcchMaxValueName = va_arg( args, LPDWORD );
636         LPDWORD lpcchMaxValueData = va_arg( args, LPDWORD );
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       = va_arg( args, HKEY );
645         LPCSTR  lpszSubKey = va_arg( args, LPCSTR );
646         LPCSTR  lpszFile   = va_arg( args, LPCSTR );
647         return RegLoadKeyA( hkey, lpszSubKey, lpszFile );
648     }
649
650     case 0x0022:  /* RegUnLoadKey */
651     {
652         HKEY    hkey       = va_arg( args, HKEY );
653         LPCSTR  lpszSubKey = va_arg( args, LPCSTR );
654         return RegUnLoadKeyA( hkey, lpszSubKey );
655     }
656
657     case 0x0023:  /* RegSaveKey */
658     {
659         HKEY    hkey       = va_arg( args, HKEY );
660         LPCSTR  lpszFile   = va_arg( args, LPCSTR );
661         LPSECURITY_ATTRIBUTES sa = va_arg( args, LPSECURITY_ATTRIBUTES );
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       = va_arg( args, HKEY );
673         LPCSTR  lpszSubKey = va_arg( args, LPCSTR );
674         LPCSTR  lpszNewFile= va_arg( args, LPCSTR );
675         LPCSTR  lpszOldFile= va_arg( args, LPCSTR );
676         return RegReplaceKeyA( hkey, lpszSubKey, lpszNewFile, lpszOldFile );
677     }
678
679     default:
680         if (LOWORD(service) < N_VMM_SERVICE)
681             FIXME( "Unimplemented service %s (%08lx)\n",
682                           VMM_Service_Name[LOWORD(service)], service);
683         else
684             FIXME( "Unknown service %08lx\n", service);
685         break;
686     }
687
688     return 0xffffffff;  /* FIXME */
689 }
690
691 /***********************************************************************
692  *           DeviceIo_IFSMgr
693  * NOTES
694  *   The ioctls is used by 'MSNET32.DLL'.
695  *
696  *   I have been unable to uncover any documentation about the ioctls so 
697  *   the implementation of the cases IFS_IOCTL_21 and IFS_IOCTL_2F are
698  *   based on a resonable guesses on information found in the Windows 95 DDK.
699  *   
700  */
701
702 /*
703  * IFSMgr DeviceIO service
704  */
705
706 #define IFS_IOCTL_21                100
707 #define IFS_IOCTL_2F                101
708 #define IFS_IOCTL_GET_RES           102
709 #define IFS_IOCTL_GET_NETPRO_NAME_A 103
710
711 struct win32apireq {
712         unsigned long   ar_proid;
713         unsigned long   ar_eax;         
714         unsigned long   ar_ebx; 
715         unsigned long   ar_ecx; 
716         unsigned long   ar_edx; 
717         unsigned long   ar_esi; 
718         unsigned long   ar_edi;
719         unsigned long   ar_ebp;         
720         unsigned short  ar_error;
721         unsigned short  ar_pad;
722 };
723
724 static void win32apieq_2_CONTEXT(struct win32apireq *pIn,CONTEXT *pCxt)
725 {
726         memset(pCxt,0,sizeof(CONTEXT));
727
728         pCxt->ContextFlags=CONTEXT_INTEGER|CONTEXT_CONTROL;
729         pCxt->Eax = pIn->ar_eax;
730         pCxt->Ebx = pIn->ar_ebx;
731         pCxt->Ecx = pIn->ar_ecx;
732         pCxt->Edx = pIn->ar_edx;
733         pCxt->Esi = pIn->ar_esi;
734         pCxt->Edi = pIn->ar_edi;
735
736         /* FIXME: Only partial CONTEXT_CONTROL */
737         pCxt->Ebp = pIn->ar_ebp;
738
739         /* FIXME: pIn->ar_proid ignored */
740         /* FIXME: pIn->ar_error ignored */
741         /* FIXME: pIn->ar_pad ignored */
742 }
743
744 static void CONTEXT_2_win32apieq(CONTEXT *pCxt,struct win32apireq *pOut)
745 {
746         memset(pOut,0,sizeof(struct win32apireq));
747
748         pOut->ar_eax = pCxt->Eax;
749         pOut->ar_ebx = pCxt->Ebx;
750         pOut->ar_ecx = pCxt->Ecx;
751         pOut->ar_edx = pCxt->Edx;
752         pOut->ar_esi = pCxt->Esi;
753         pOut->ar_edi = pCxt->Edi;
754
755         /* FIXME: Only partial CONTEXT_CONTROL */
756         pOut->ar_ebp = pCxt->Ebp;
757
758         /* FIXME: pOut->ar_proid ignored */
759         /* FIXME: pOut->ar_error ignored */
760         /* FIXME: pOut->ar_pad ignored */
761 }
762
763 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
764                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
765                               LPDWORD lpcbBytesReturned,
766                               LPOVERLAPPED lpOverlapped)
767 {
768     BOOL retv = TRUE;
769         TRACE("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
770                         dwIoControlCode,
771                         lpvInBuffer,cbInBuffer,
772                         lpvOutBuffer,cbOutBuffer,
773                         lpcbBytesReturned,
774                         lpOverlapped);
775
776     switch (dwIoControlCode)
777     {
778         case IFS_IOCTL_21:
779         case IFS_IOCTL_2F:{
780                 CONTEXT cxt;
781                 struct win32apireq *pIn=(struct win32apireq *) lpvInBuffer;
782                 struct win32apireq *pOut=(struct win32apireq *) lpvOutBuffer;
783
784                 TRACE(
785                         "Control '%s': "
786                         "proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
787                         "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx, ebp=0x%08lx, "
788                         "error=0x%04x, pad=0x%04x\n",
789                         (dwIoControlCode==IFS_IOCTL_21)?"IFS_IOCTL_21":"IFS_IOCTL_2F",
790                         pIn->ar_proid, pIn->ar_eax, pIn->ar_ebx, pIn->ar_ecx,
791                         pIn->ar_edx, pIn->ar_esi, pIn->ar_edi, pIn->ar_ebp,
792                         pIn->ar_error, pIn->ar_pad
793                 );                              
794                 
795                 win32apieq_2_CONTEXT(pIn,&cxt);
796
797                 if(dwIoControlCode==IFS_IOCTL_21)
798                 {
799                         DOS3Call(&cxt); /* Call int 21h */
800                 } else {
801                         INT_Int2fHandler(&cxt); /* Call int 2Fh */
802                 }
803                 
804                 CONTEXT_2_win32apieq(&cxt,pOut);
805                         
806         retv = TRUE;
807         } break;
808         case IFS_IOCTL_GET_RES:{
809         FIXME( "Control 'IFS_IOCTL_GET_RES' not implemented\n");
810         retv = FALSE;
811         } break;
812         case IFS_IOCTL_GET_NETPRO_NAME_A:{
813         FIXME( "Control 'IFS_IOCTL_GET_NETPRO_NAME_A' not implemented\n");
814         retv = FALSE;
815         } break;         
816     default:
817         FIXME( "Control %ld not implemented\n", dwIoControlCode);
818         retv = FALSE;
819     }
820
821     return retv;
822 }
823
824  
825 /***********************************************************************
826  *           DeviceIo_VWin32
827  */
828
829 static void DIOCRegs_2_CONTEXT( DIOC_REGISTERS *pIn, CONTEXT *pCxt )
830 {
831     memset( pCxt, 0, sizeof(CONTEXT) );
832     /* Note: segment registers == 0 means that CTX_SEG_OFF_TO_LIN
833              will interpret 32-bit register contents as linear pointers */
834
835     pCxt->ContextFlags=CONTEXT_INTEGER|CONTEXT_CONTROL;
836     pCxt->Eax = pIn->reg_EAX;
837     pCxt->Ebx = pIn->reg_EBX;
838     pCxt->Ecx = pIn->reg_ECX;
839     pCxt->Edx = pIn->reg_EDX;
840     pCxt->Esi = pIn->reg_ESI;
841     pCxt->Edi = pIn->reg_EDI;
842
843     /* FIXME: Only partial CONTEXT_CONTROL */
844     pCxt->EFlags = pIn->reg_Flags;
845 }
846
847 static void CONTEXT_2_DIOCRegs( CONTEXT *pCxt, DIOC_REGISTERS *pOut )
848 {
849     memset( pOut, 0, sizeof(DIOC_REGISTERS) );
850
851     pOut->reg_EAX = pCxt->Eax;
852     pOut->reg_EBX = pCxt->Ebx;
853     pOut->reg_ECX = pCxt->Ecx;
854     pOut->reg_EDX = pCxt->Edx;
855     pOut->reg_ESI = pCxt->Esi;
856     pOut->reg_EDI = pCxt->Edi;
857
858     /* FIXME: Only partial CONTEXT_CONTROL */
859     pOut->reg_Flags = pCxt->EFlags;
860 }
861
862
863 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, 
864                               LPVOID lpvInBuffer, DWORD cbInBuffer,
865                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
866                               LPDWORD lpcbBytesReturned,
867                               LPOVERLAPPED lpOverlapped)
868 {
869     BOOL retv = TRUE;
870
871     switch (dwIoControlCode)
872     {
873     case VWIN32_DIOC_DOS_IOCTL:
874     case VWIN32_DIOC_DOS_INT13:
875     case VWIN32_DIOC_DOS_INT25:
876     case VWIN32_DIOC_DOS_INT26:
877     {
878         CONTEXT cxt;
879         DIOC_REGISTERS *pIn  = (DIOC_REGISTERS *)lpvInBuffer;
880         DIOC_REGISTERS *pOut = (DIOC_REGISTERS *)lpvOutBuffer;
881
882         TRACE( "Control '%s': "
883                "eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
884                "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx ",
885                (dwIoControlCode == VWIN32_DIOC_DOS_IOCTL)? "VWIN32_DIOC_DOS_IOCTL" :
886                (dwIoControlCode == VWIN32_DIOC_DOS_INT13)? "VWIN32_DIOC_DOS_INT13" :
887                (dwIoControlCode == VWIN32_DIOC_DOS_INT25)? "VWIN32_DIOC_DOS_INT25" :
888                (dwIoControlCode == VWIN32_DIOC_DOS_INT26)? "VWIN32_DIOC_DOS_INT26" : "???",
889                pIn->reg_EAX, pIn->reg_EBX, pIn->reg_ECX,
890                pIn->reg_EDX, pIn->reg_ESI, pIn->reg_EDI );
891
892         DIOCRegs_2_CONTEXT( pIn, &cxt );
893
894         switch (dwIoControlCode)
895         {
896         case VWIN32_DIOC_DOS_IOCTL: DOS3Call( &cxt ); break; /* Call int 21h */
897         case VWIN32_DIOC_DOS_INT13: INT_Int13Handler( &cxt ); break;
898         case VWIN32_DIOC_DOS_INT25: INT_Int25Handler( &cxt ); break;
899         case VWIN32_DIOC_DOS_INT26: INT_Int26Handler( &cxt ); break;
900         }
901
902         CONTEXT_2_DIOCRegs( &cxt, pOut );
903     }
904     break;
905
906     case VWIN32_DIOC_SIMCTRLC:
907         FIXME( "Control VWIN32_DIOC_SIMCTRLC not implemented\n");
908         retv = FALSE;
909         break;
910
911     default:
912         FIXME( "Unknown Control %ld\n", dwIoControlCode);
913         retv = FALSE;
914         break;
915     }
916
917     return retv;
918 }
919
920 /* this is the main multimedia device loader */
921 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode, 
922                               LPVOID lpvInBuffer, DWORD cbInBuffer,
923                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
924                               LPDWORD lpcbBytesReturned,
925                               LPOVERLAPPED lpOverlapped)
926 {
927         FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
928             dwIoControlCode,
929             lpvInBuffer,cbInBuffer,
930             lpvOutBuffer,cbOutBuffer,
931             lpcbBytesReturned,
932             lpOverlapped
933         );
934         switch (dwIoControlCode) {
935         case 5:
936                 /* Hmm. */
937                 *(DWORD*)lpvOutBuffer=0;
938                 *lpcbBytesReturned=4;
939                 return TRUE;
940         }
941         return FALSE;
942 }
943 /* this is used by some Origin games */
944 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode, 
945                               LPVOID lpvInBuffer, DWORD cbInBuffer,
946                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
947                               LPDWORD lpcbBytesReturned,
948                               LPOVERLAPPED lpOverlapped)
949 {
950         switch (dwIoControlCode) {
951         case 1: /* version */
952                 *(LPDWORD)lpvOutBuffer = 0x20004; /* WC SecretOps */
953                 break;
954         case 9: /* debug output */
955                 fprintf(stderr,"MONODEBG: %s\n",debugstr_a(lpvInBuffer));
956                 break;
957         default:
958                 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
959                         dwIoControlCode,
960                         lpvInBuffer,cbInBuffer,
961                         lpvOutBuffer,cbOutBuffer,
962                         lpcbBytesReturned,
963                         lpOverlapped
964                 );
965                 break;
966         }
967         return TRUE;
968 }
969 /* pccard */
970 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode, 
971                               LPVOID lpvInBuffer, DWORD cbInBuffer,
972                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
973                               LPDWORD lpcbBytesReturned,
974                               LPOVERLAPPED lpOverlapped)
975 {
976         switch (dwIoControlCode) {
977         case 0x0000: /* PCCARD_Get_Version */
978         case 0x0001: /* PCCARD_Card_Services */
979         default:
980                 FIXME( "(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
981                         dwIoControlCode,
982                         lpvInBuffer,cbInBuffer,
983                         lpvOutBuffer,cbOutBuffer,
984                         lpcbBytesReturned,
985                         lpOverlapped
986                 );
987                 break;
988         }
989         return FALSE;
990 }
991
992 DWORD   WINAPI  OpenVxDHandle(DWORD pmt)
993 {
994         FIXME( "(0x%08lx) stub!\n", pmt);
995         return 0;
996 }