Release 980927
[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 <time.h>
20 #include "windows.h"
21 #include "winbase.h"
22 #include "winerror.h"
23 #include "file.h"
24 #include "process.h"
25 #include "mmsystem.h"
26 #include "heap.h"
27 #include "debug.h"
28 #include "winioctl.h"
29 #include "stackframe.h"
30 #include "winnt.h"
31 #include "msdos.h"
32 #include "miscemu.h"
33
34 static void DEVICE_Destroy(K32OBJ *dev);
35 const K32OBJ_OPS DEVICE_Ops =
36 {
37     NULL,               /* signaled */
38     NULL,               /* satisfied */
39     NULL,               /* add_wait */
40     NULL,               /* remove_wait */
41     NULL,               /* read */
42     NULL,               /* write */
43     DEVICE_Destroy      /* destroy */
44 };
45
46 /* The device object */
47 typedef struct
48 {
49     K32OBJ    header;
50
51     struct VxDInfo *info;
52     char     *devname;
53     int       mode;
54
55 } DEVICE_OBJECT;
56
57
58 static BOOL32 DeviceIo_VTDAPI(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
59                               LPVOID lpvInBuffer, DWORD cbInBuffer,
60                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
61                               LPDWORD lpcbBytesReturned,
62                               LPOVERLAPPED lpOverlapped);
63
64 static BOOL32 VxDCall_VMM( DWORD *retv, DWORD service, CONTEXT *context );
65
66 static BOOL32 VxDCall_IFSMgr( DWORD *retv, DWORD service, CONTEXT *context );
67
68 static BOOL32 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
69                               LPVOID lpvInBuffer, DWORD cbInBuffer,
70                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
71                               LPDWORD lpcbBytesReturned,
72                               LPOVERLAPPED lpOverlapped);
73
74 /*
75  * VxD names are taken from the Win95 DDK
76  */
77
78 struct VxDInfo
79 {
80     LPCSTR  name;
81     WORD    id;
82     BOOL32  (*vxdcall)(DWORD *, DWORD, CONTEXT *);
83     BOOL32  (*deviceio)(DEVICE_OBJECT *, DWORD, LPVOID, DWORD, 
84                         LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
85 }   
86     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, NULL },
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, VxDCall_IFSMgr, 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
174     /* Network Device IDs */
175     { "VNetSup",  0x0480, NULL, NULL },
176     { "VRedir",   0x0481, NULL, NULL },
177     { "VBrowse",  0x0482, NULL, NULL },
178     { "VSHARE",   0x0483, NULL, NULL },
179     { "IFSMgr",   0x0484, NULL, NULL },
180     { "MEMPROBE", 0x0485, NULL, NULL },
181     { "VFAT",     0x0486, NULL, NULL },
182     { "NWLINK",   0x0487, NULL, NULL },
183     { "VNWLINK",  0x0487, NULL, NULL },
184     { "NWSUP",    0x0487, NULL, NULL },
185     { "VTDI",     0x0488, NULL, NULL },
186     { "VIP",      0x0489, NULL, NULL },
187     { "VTCP",     0x048A, NULL, NULL },
188     { "VCache",   0x048B, NULL, NULL },
189     { "VUDP",     0x048C, NULL, NULL },
190     { "VAsync",   0x048D, NULL, NULL },
191     { "NWREDIR",  0x048E, NULL, NULL },
192     { "STAT80",   0x048F, NULL, NULL },
193     { "SCSIPORT", 0x0490, NULL, NULL },
194     { "FILESEC",  0x0491, NULL, NULL },
195     { "NWSERVER", 0x0492, NULL, NULL },
196     { "SECPROV",  0x0493, NULL, NULL },
197     { "NSCL",     0x0494, NULL, NULL },
198     { "WSTCP",    0x0495, NULL, NULL },
199     { "NDIS2SUP", 0x0496, NULL, NULL },
200     { "MSODISUP", 0x0497, NULL, NULL },
201     { "Splitter", 0x0498, NULL, NULL },
202     { "PPP",      0x0499, NULL, NULL },
203     { "VDHCP",    0x049A, NULL, NULL },
204     { "VNBT",     0x049B, NULL, NULL },
205     { "LOGGER",   0x049D, NULL, NULL },
206     { "EFILTER",  0x049E, NULL, NULL },
207     { "FFILTER",  0x049F, NULL, NULL },
208     { "TFILTER",  0x04A0, NULL, NULL },
209     { "AFILTER",  0x04A1, NULL, NULL },
210     { "IRLAMP",   0x04A2, NULL, NULL },
211
212     { NULL,       0,      NULL, NULL }
213 };
214
215 /*
216  * VMM VxDCall service names are (mostly) taken from Stan Mitchell's
217  * "Inside the Windows 95 File System"
218  */
219
220 #define N_VMM_SERVICE 41
221
222 LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
223
224     "PageReserve",            /* 0x0000 */
225     "PageCommit",             /* 0x0001 */
226     "PageDecommit",           /* 0x0002 */
227     "PagerRegister",          /* 0x0003 */
228     "PagerQuery",             /* 0x0004 */
229     "HeapAllocate",           /* 0x0005 */
230     "ContextCreate",          /* 0x0006 */
231     "ContextDestroy",         /* 0x0007 */
232     "PageAttach",             /* 0x0008 */
233     "PageFlush",              /* 0x0009 */
234     "PageFree",               /* 0x000A */
235     "ContextSwitch",          /* 0x000B */
236     "HeapReAllocate",         /* 0x000C */
237     "PageModifyPerm",         /* 0x000D */
238     "PageQuery",              /* 0x000E */
239     "GetCurrentContext",      /* 0x000F */
240     "HeapFree",               /* 0x0010 */
241     "RegOpenKey",             /* 0x0011 */
242     "RegCreateKey",           /* 0x0012 */
243     "RegCloseKey",            /* 0x0013 */
244     "RegDeleteKey",           /* 0x0014 */
245     "RegSetValue",            /* 0x0015 */
246     "RegDeleteValue",         /* 0x0016 */
247     "RegQueryValue",          /* 0x0017 */
248     "RegEnumKey",             /* 0x0018 */
249     "RegEnumValue",           /* 0x0019 */
250     "RegQueryValueEx",        /* 0x001A */
251     "RegSetValueEx",          /* 0x001B */
252     "RegFlushKey",            /* 0x001C */
253     "RegQueryInfoKey",        /* 0x001D */
254     "GetDemandPageInfo",      /* 0x001E */
255     "BlockOnID",              /* 0x001F */
256     "SignalID",               /* 0x0020 */
257     "RegLoadKey",             /* 0x0021 */
258     "RegUnLoadKey",           /* 0x0022 */
259     "RegSaveKey",             /* 0x0023 */
260     "RegRemapPreDefKey",      /* 0x0024 */
261     "PageChangePager",        /* 0x0025 */
262     "RegQueryMultipleValues", /* 0x0026 */
263     "RegReplaceKey",          /* 0x0027 */
264     "<KERNEL32.101>"          /* 0x0028 -- What does this do??? */
265 };
266
267
268 /*
269  * IFSMgr VxDCall service
270  */
271
272 #define N_IFSMGR_SERVICE 118
273
274 LPCSTR IFSMgr_Service_Name[N_IFSMGR_SERVICE] =
275
276     "Get_Version",                 /* 0x0000 */
277     "RegisterMount",               /* 0x0001 */
278     "RegisterNet",                 /* 0x0002 */
279     "RegisterMailSlot",            /* 0x0003 */
280     "Attach",                      /* 0x0004 */
281     "Detach",                      /* 0x0005 */
282     "Get_NetTime",                 /* 0x0006 */
283     "Get_DOSTime",                 /* 0x0007 */
284     "SetupConnection",             /* 0x0008 */
285     "DerefConnection",             /* 0x0009 */
286     "ServerDOSCall",               /* 0x000A */
287     "CompleteAsync",               /* 0x000B */
288     "RegisterHeap",                /* 0x000C */
289     "GetHeap",                     /* 0x000D */
290     "RetHeap",                     /* 0x000E */
291     "CheckHeap",                   /* 0x000F */
292     "CheckHeapItem",               /* 0x0010 */
293     "FillHeapSpare",               /* 0x0011 */
294     "Block",                       /* 0x0012 */
295     "Wakeup",                      /* 0x0013 */
296     "Yield",                       /* 0x0014 */
297     "SchedEvent",                  /* 0x0015 */
298     "QueueEvent",                  /* 0x0016 */
299     "KillEvent",                   /* 0x0017 */
300     "FreeIOReq",                   /* 0x0018 */
301     "MakeMailSlot",                /* 0x0019 */
302     "DeleteMailSlot",              /* 0x001A */
303     "WriteMailSlot",               /* 0x001B */
304     "PopUp",                       /* 0x001C */
305     "printf",                      /* 0x001D */
306     "AssertFailed",                /* 0x001E */
307     "LogEntry",                    /* 0x001F */
308     "DebugMenu",                   /* 0x0020 */
309     "DebugVars",                   /* 0x0021 */
310     "GetDebugString",              /* 0x0022 */
311     "GetDebugHexNum",              /* 0x0023 */
312     "NetFunction",                 /* 0x0024 */
313     "DoDelAllUses",                /* 0x0025 */
314     "SetErrString",                /* 0x0026 */
315     "GetErrString",                /* 0x0027 */
316     "SetReqHook",                  /* 0x0028 */
317     "SetPathHook",                 /* 0x0029 */
318     "UseAdd",                      /* 0x002A */
319     "UseDel",                      /* 0x002B */
320     "InitUseAdd",                  /* 0x002C */
321     "ChangeDir",                   /* 0x002D */
322     "DelAllUses",                  /* 0x002E */
323     "CDROM_Attach",                /* 0x002F */
324     "CDROM_Detach",                /* 0x0030 */
325     "Win32DupHandle",              /* 0x0031 */
326     "Ring0_FileIO",                /* 0x0032 */
327     "Win32_Get_Ring0_Handle",      /* 0x0033 */
328     "Get_Drive_Info",              /* 0x0034 */
329     "Ring0GetDriveInfo",           /* 0x0035 */
330     "BlockNoEvents",               /* 0x0036 */
331     "NetToDosTime",                /* 0x0037 */
332     "DosToNetTime",                /* 0x0038 */
333     "DosToWin32Time",              /* 0x0039 */
334     "Win32ToDosTime",              /* 0x003A */
335     "NetToWin32Time",              /* 0x003B */
336     "Win32ToNetTime",              /* 0x003C */
337     "MetaMatch",                   /* 0x003D */
338     "TransMatch",                  /* 0x003E */
339     "CallProvider",                /* 0x003F */
340     "UniToBCS",                    /* 0x0040 */
341     "UniToBCSPath",                /* 0x0041 */
342     "BCSToUni",                    /* 0x0042 */
343     "UniToUpper",                  /* 0x0043 */
344     "UniCharToOEM",                /* 0x0044 */
345     "CreateBasis",                 /* 0x0045 */
346     "MatchBasisName",              /* 0x0046 */
347     "AppendBasisTail",             /* 0x0047 */
348     "FcbToShort",                  /* 0x0048 */
349     "ShortToFcb",                  /* 0x0049 */
350     "ParsePath",                   /* 0x004A */
351     "Query_PhysLock",              /* 0x004B */
352     "_VolFlush",                   /* 0x004C */
353     "NotifyVolumeArrival",         /* 0x004D */
354     "NotifyVolumeRemoval",         /* 0x004E */
355     "QueryVolumeRemoval",          /* 0x004F */
356     "FSDUnmountCFSD",              /* 0x0050 */
357     "GetConversionTablePtrs",      /* 0x0051 */
358     "CheckAccessConflict",         /* 0x0052 */
359     "LockFile",                    /* 0x0053 */
360     "UnlockFile",                  /* 0x0054 */
361     "RemoveLocks",                 /* 0x0055 */
362     "CheckLocks",                  /* 0x0056 */
363     "CountLocks",                  /* 0x0057 */
364     "ReassignLockFileInst",        /* 0x0058 */
365     "UnassignLockList",            /* 0x0059 */
366     "MountChildVolume",            /* 0x005A */
367     "UnmountChildVolume",          /* 0x005B */
368     "SwapDrives",                  /* 0x005C */
369     "FSDMapFHtoIOREQ",             /* 0x005D */
370     "FSDParsePath",                /* 0x005E */
371     "FSDAttachSFT",                /* 0x005F */
372     "GetTimeZoneBias",             /* 0x0060 */
373     "PNPEvent",                    /* 0x0061 */
374     "RegisterCFSD",                /* 0x0062 */
375     "Win32MapExtendedHandleToSFT", /* 0x0063 */
376     "DbgSetFileHandleLimit",       /* 0x0064 */
377     "Win32MapSFTToExtendedHandle", /* 0x0065 */
378     "FSDGetCurrentDrive",          /* 0x0066 */
379     "InstallFileSystemApiHook",    /* 0x0067 */
380     "RemoveFileSystemApiHook",     /* 0x0068 */
381     "RunScheduledEvents",          /* 0x0069 */
382     "CheckDelResource",            /* 0x006A */
383     "Win32GetVMCurdir",            /* 0x006B */
384     "SetupFailedConnection",       /* 0x006C */
385     "_GetMappedErr",               /* 0x006D */
386     "ShortToLossyFcb",             /* 0x006F */
387     "GetLockState",                /* 0x0070 */
388     "BcsToBcs",                    /* 0x0071 */
389     "SetLoopback",                 /* 0x0072 */
390     "ClearLoopback",               /* 0x0073 */
391     "ParseOneElement",             /* 0x0074 */
392     "BcsToBcsUpper"                /* 0x0075 */
393 };
394
395
396 /*
397  * IFSMgr DeviceIO service
398  */
399
400 #define IFS_IOCTL_21                            100
401 #define IFS_IOCTL_2F                            101
402 #define IFS_IOCTL_GET_RES                       102
403 #define IFS_IOCTL_GET_NETPRO_NAME_A     103
404
405
406 HANDLE32 DEVICE_Open(LPCSTR filename, DWORD access) 
407 {
408         DEVICE_OBJECT *dev;
409         HANDLE32 handle;
410         int i;
411
412         dev = HeapAlloc( SystemHeap, 0, sizeof(DEVICE_OBJECT) );
413         if (!dev) return INVALID_HANDLE_VALUE32;
414
415         dev->header.type = K32OBJ_DEVICE_IOCTL;
416         dev->header.refcount = 1;
417         dev->mode       = access;
418         dev->devname    = HEAP_strdupA(SystemHeap,0,filename);
419         dev->info       = NULL;
420
421         for (i = 0; VxDList[i].name; i++)
422             if (!lstrcmpi32A(VxDList[i].name, filename))
423                 break;
424         if (VxDList[i].name)
425             dev->info = &VxDList[i];
426         else
427             FIXME(win32, "Unknown VxD %s\n", filename);
428
429
430         handle = HANDLE_Alloc( PROCESS_Current(), &(dev->header),
431                                FILE_ALL_ACCESS | GENERIC_READ |
432                                GENERIC_WRITE | GENERIC_EXECUTE /*FIXME*/, TRUE, -1 );
433         /* If the allocation failed, the object is already destroyed */
434         if (handle == INVALID_HANDLE_VALUE32) dev = NULL;
435         return handle;
436 }
437
438 static void DEVICE_Destroy(K32OBJ *obj) 
439 {
440     DEVICE_OBJECT *dev = (DEVICE_OBJECT *)obj;
441     assert( obj->type == K32OBJ_DEVICE_IOCTL );
442
443     if ( dev->devname )
444     {
445         HeapFree( SystemHeap, 0, dev->devname );
446         dev->devname = NULL;
447     }
448
449     obj->type = K32OBJ_UNKNOWN;
450     HeapFree( SystemHeap, 0, dev );
451 }
452
453 /****************************************************************************
454  *              DeviceIoControl (KERNEL32.188)
455  * This is one of those big ugly nasty procedure which can do
456  * a million and one things when it comes to devices. It can also be
457  * used for VxD communication.
458  *
459  * A return value of FALSE indicates that something has gone wrong which
460  * GetLastError can decypher.
461  */
462 BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode, 
463                               LPVOID lpvInBuffer, DWORD cbInBuffer,
464                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
465                               LPDWORD lpcbBytesReturned,
466                               LPOVERLAPPED lpOverlapped)
467 {
468         DEVICE_OBJECT   *dev = (DEVICE_OBJECT *)HANDLE_GetObjPtr(
469                 PROCESS_Current(), hDevice, K32OBJ_DEVICE_IOCTL, 0 /*FIXME*/, NULL );
470
471         TRACE(win32, "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n",
472                 hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
473                 lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped
474         );
475
476         if (!dev)
477         {
478                 SetLastError( ERROR_INVALID_PARAMETER );
479                 return FALSE;
480         }
481
482         /* Check if this is a user defined control code for a VxD */
483         if( HIWORD( dwIoControlCode ) == 0 )
484         {
485                 if ( dev->info && dev->info->deviceio )
486                 {
487                         return dev->info->deviceio( dev, dwIoControlCode, 
488                                         lpvInBuffer, cbInBuffer, 
489                                         lpvOutBuffer, cbOutBuffer, 
490                                         lpcbBytesReturned, lpOverlapped );
491                 }
492                 else
493                 {
494                         /* FIXME: Set appropriate error */
495                         FIXME( win32, "Unimplemented control %ld for VxD device %s\n", 
496                                           dwIoControlCode, dev->devname );
497                 }
498         }
499         else
500         {
501                 switch( dwIoControlCode )
502                 {
503                 case FSCTL_DELETE_REPARSE_POINT:
504                 case FSCTL_DISMOUNT_VOLUME:
505                 case FSCTL_GET_COMPRESSION:
506                 case FSCTL_GET_REPARSE_POINT:
507                 case FSCTL_LOCK_VOLUME:
508                 case FSCTL_QUERY_ALLOCATED_RANGES:
509                 case FSCTL_SET_COMPRESSION:
510                 case FSCTL_SET_REPARSE_POINT:
511                 case FSCTL_SET_SPARSE:
512                 case FSCTL_SET_ZERO_DATA:
513                 case FSCTL_UNLOCK_VOLUME:
514                 case IOCTL_DISK_CHECK_VERIFY:
515                 case IOCTL_DISK_EJECT_MEDIA:
516                 case IOCTL_DISK_FORMAT_TRACKS:
517                 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
518                 case IOCTL_DISK_GET_DRIVE_LAYOUT:
519                 case IOCTL_DISK_GET_MEDIA_TYPES:
520                 case IOCTL_DISK_GET_PARTITION_INFO:
521                 case IOCTL_DISK_LOAD_MEDIA:
522                 case IOCTL_DISK_MEDIA_REMOVAL:
523                 case IOCTL_DISK_PERFORMANCE:
524                 case IOCTL_DISK_REASSIGN_BLOCKS:
525                 case IOCTL_DISK_SET_DRIVE_LAYOUT:
526                 case IOCTL_DISK_SET_PARTITION_INFO:
527                 case IOCTL_DISK_VERIFY:
528                 case IOCTL_SERIAL_LSRMST_INSERT:
529                 case IOCTL_STORAGE_CHECK_VERIFY:
530                 case IOCTL_STORAGE_EJECT_MEDIA:
531                 case IOCTL_STORAGE_GET_MEDIA_TYPES:
532                 case IOCTL_STORAGE_LOAD_MEDIA:
533                 case IOCTL_STORAGE_MEDIA_REMOVAL:
534                         FIXME( win32, "unimplemented dwIoControlCode=%08lx\n", dwIoControlCode);
535                         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
536                         return FALSE;
537                         break;
538                 default:
539                         FIXME( win32, "ignored dwIoControlCode=%08lx\n",dwIoControlCode);
540                         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
541                         return FALSE;
542                         break;
543                 }
544         }
545         return FALSE;
546 }
547  
548 /***********************************************************************
549  *           DeviceIo_VTDAPI
550  */
551 static BOOL32 DeviceIo_VTDAPI(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
552                               LPVOID lpvInBuffer, DWORD cbInBuffer,
553                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
554                               LPDWORD lpcbBytesReturned,
555                               LPOVERLAPPED lpOverlapped)
556 {
557     BOOL32 retv = TRUE;
558
559     switch (dwIoControlCode)
560     {
561     case 5:
562         if (lpvOutBuffer && (cbOutBuffer>=4))
563             *(DWORD*)lpvOutBuffer = timeGetTime();
564
565         if (lpcbBytesReturned)
566             *lpcbBytesReturned = 4;
567
568         break;
569
570     default:
571         FIXME(win32, "Control %ld not implemented\n", dwIoControlCode);
572         retv = FALSE;
573         break;
574     }
575
576     return retv;
577 }
578
579
580
581
582
583 /***********************************************************************
584  *           VxDCall                   (KERNEL32.[1-9])
585  */
586 static void VxDCall( CONTEXT *context, int nArgs )
587 {
588     DWORD retv, service;
589     int i, ok = FALSE;
590
591     /* Pop return address to caller */
592     EIP_reg(context) = STACK32_POP(context);
593
594     /* Pop requested service ID */
595     service = STACK32_POP(context);
596
597     TRACE(win32, "(%08lx, ...)\n", service);
598
599     for (i = 0; VxDList[i].name; i++)
600         if (VxDList[i].id == HIWORD(service))
601             break;
602
603     if (!VxDList[i].name)
604         FIXME(win32, "Unknown VxD (%08lx)\n", service);
605     else if (!VxDList[i].vxdcall)
606         FIXME(win32, "Unimplemented VxD (%08lx)\n", service);
607     else
608         ok = VxDList[i].vxdcall(&retv, service, context);
609
610     /* If unimplemented, trust the caller to have called the
611        version with the correct number of arguments */
612     if (!ok)
613     {
614         ESP_reg(context) += 4 * nArgs;
615         retv = 0xffffffff;  /* FIXME */
616     }
617
618     /* Push return address back onto stack */
619     STACK32_PUSH(context, EIP_reg(context));
620
621     /* Return to caller */
622     EAX_reg(context) = retv;
623 }
624
625 REGS_ENTRYPOINT(VxDCall0) { VxDCall( context, 0 ); }
626 REGS_ENTRYPOINT(VxDCall1) { VxDCall( context, 1 ); }
627 REGS_ENTRYPOINT(VxDCall2) { VxDCall( context, 2 ); }
628 REGS_ENTRYPOINT(VxDCall3) { VxDCall( context, 3 ); }
629 REGS_ENTRYPOINT(VxDCall4) { VxDCall( context, 4 ); }
630 REGS_ENTRYPOINT(VxDCall5) { VxDCall( context, 5 ); }
631 REGS_ENTRYPOINT(VxDCall6) { VxDCall( context, 6 ); }
632 REGS_ENTRYPOINT(VxDCall7) { VxDCall( context, 7 ); }
633 REGS_ENTRYPOINT(VxDCall8) { VxDCall( context, 8 ); }
634
635 /***********************************************************************
636  *           VxDCall_VMM
637  */
638 BOOL32 VxDCall_VMM( DWORD *retv, DWORD service, CONTEXT *context )
639 {
640     BOOL32 ok = TRUE;
641
642     switch ( LOWORD(service) )
643     {
644     case 0x0011:  /* RegOpenKey */
645     {
646         HKEY    hkey       = (HKEY)   STACK32_POP( context );
647         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
648         LPHKEY  retkey     = (LPHKEY) STACK32_POP( context );
649         *retv = RegOpenKey32A( hkey, lpszSubKey, retkey );
650     }
651     break;
652
653     case 0x0012:  /* RegCreateKey */
654     {
655         HKEY    hkey       = (HKEY)   STACK32_POP( context );
656         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
657         LPHKEY  retkey     = (LPHKEY) STACK32_POP( context );
658         *retv = RegCreateKey32A( hkey, lpszSubKey, retkey );
659     }
660     break;
661
662     case 0x0013:  /* RegCloseKey */
663     {
664         HKEY    hkey       = (HKEY)   STACK32_POP( context );
665         *retv = RegCloseKey( hkey );
666     }
667     break;
668
669     case 0x0014:  /* RegDeleteKey */
670     {
671         HKEY    hkey       = (HKEY)   STACK32_POP( context );
672         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
673         *retv = RegDeleteKey32A( hkey, lpszSubKey );
674     }
675     break;
676
677     case 0x0015:  /* RegSetValue */
678     {
679         HKEY    hkey       = (HKEY)   STACK32_POP( context );
680         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
681         DWORD   dwType     = (DWORD)  STACK32_POP( context );
682         LPCSTR  lpszData   = (LPCSTR) STACK32_POP( context );
683         DWORD   cbData     = (DWORD)  STACK32_POP( context );
684         *retv = RegSetValue32A( hkey, lpszSubKey, dwType, lpszData, cbData );
685     }
686     break;
687
688     case 0x0016:  /* RegDeleteValue */
689     {
690         HKEY    hkey       = (HKEY)   STACK32_POP( context );
691         LPSTR   lpszValue  = (LPSTR)  STACK32_POP( context );
692         *retv = RegDeleteValue32A( hkey, lpszValue );
693     }
694     break;
695
696     case 0x0017:  /* RegQueryValue */
697     {
698         HKEY    hkey       = (HKEY)   STACK32_POP( context );
699         LPSTR   lpszSubKey = (LPSTR)  STACK32_POP( context );
700         LPSTR   lpszData   = (LPSTR)  STACK32_POP( context );
701         LPDWORD lpcbData   = (LPDWORD)STACK32_POP( context );
702         *retv = RegQueryValue32A( hkey, lpszSubKey, lpszData, lpcbData );
703     }
704     break;
705
706     case 0x0018:  /* RegEnumKey */
707     {
708         HKEY    hkey       = (HKEY)   STACK32_POP( context );
709         DWORD   iSubkey    = (DWORD)  STACK32_POP( context );
710         LPSTR   lpszName   = (LPSTR)  STACK32_POP( context );
711         DWORD   lpcchName  = (DWORD)  STACK32_POP( context );
712         *retv = RegEnumKey32A( hkey, iSubkey, lpszName, lpcchName );
713     }
714     break;
715
716     case 0x0019:  /* RegEnumValue */
717     {
718         HKEY    hkey       = (HKEY)   STACK32_POP( context );
719         DWORD   iValue     = (DWORD)  STACK32_POP( context );
720         LPSTR   lpszValue  = (LPSTR)  STACK32_POP( context );
721         LPDWORD lpcchValue = (LPDWORD)STACK32_POP( context );
722         LPDWORD lpReserved = (LPDWORD)STACK32_POP( context );
723         LPDWORD lpdwType   = (LPDWORD)STACK32_POP( context );
724         LPBYTE  lpbData    = (LPBYTE) STACK32_POP( context );
725         LPDWORD lpcbData   = (LPDWORD)STACK32_POP( context );
726         *retv = RegEnumValue32A( hkey, iValue, lpszValue, lpcchValue, 
727                                  lpReserved, lpdwType, lpbData, lpcbData );
728     }
729     break;
730
731     case 0x001A:  /* RegQueryValueEx */
732     {
733         HKEY    hkey       = (HKEY)   STACK32_POP( context );
734         LPSTR   lpszValue  = (LPSTR)  STACK32_POP( context );
735         LPDWORD lpReserved = (LPDWORD)STACK32_POP( context );
736         LPDWORD lpdwType   = (LPDWORD)STACK32_POP( context );
737         LPBYTE  lpbData    = (LPBYTE) STACK32_POP( context );
738         LPDWORD lpcbData   = (LPDWORD)STACK32_POP( context );
739         *retv = RegQueryValueEx32A( hkey, lpszValue, lpReserved, 
740                                     lpdwType, lpbData, lpcbData );
741     }
742     break;
743
744     case 0x001B:  /* RegSetValueEx */
745     {
746         HKEY    hkey       = (HKEY)   STACK32_POP( context );
747         LPSTR   lpszValue  = (LPSTR)  STACK32_POP( context );
748         DWORD   dwReserved = (DWORD)  STACK32_POP( context );
749         DWORD   dwType     = (DWORD)  STACK32_POP( context );
750         LPBYTE  lpbData    = (LPBYTE) STACK32_POP( context );
751         DWORD   cbData     = (DWORD)STACK32_POP( context );
752         *retv = RegSetValueEx32A( hkey, lpszValue, dwReserved, 
753                                   dwType, lpbData, cbData );
754     }
755     break;
756
757     case 0x001C:  /* RegFlushKey */
758     {
759         HKEY    hkey       = (HKEY)   STACK32_POP( context );
760         *retv = RegFlushKey( hkey );
761     }
762     break;
763
764     case 0x001D:  /* RegQueryInfoKey */
765     {
766         /* NOTE: This VxDCall takes only a subset of the parameters that the
767                  corresponding Win32 API call does. The implementation in Win95
768                  ADVAPI32 sets all output parameters not mentioned here to zero. */
769
770         HKEY    hkey       = (HKEY)   STACK32_POP( context );
771         LPDWORD lpcSubKeys = (LPDWORD)STACK32_POP( context );
772         LPDWORD lpcchMaxSubKey 
773                            = (LPDWORD)STACK32_POP( context );
774         LPDWORD lpcValues  = (LPDWORD)STACK32_POP( context );
775         LPDWORD lpcchMaxValueName 
776                            = (LPDWORD)STACK32_POP( context );
777         LPDWORD lpcchMaxValueData 
778                            = (LPDWORD)STACK32_POP( context );
779         *retv = RegQueryInfoKey32A( hkey, NULL, NULL, NULL, lpcSubKeys, lpcchMaxSubKey,
780                                     NULL, lpcValues, lpcchMaxValueName, lpcchMaxValueData,
781                                     NULL, NULL );
782     }
783     break;
784
785     case 0x0021:  /* RegLoadKey */
786     {
787         HKEY    hkey       = (HKEY)   STACK32_POP( context );
788         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
789         LPCSTR  lpszFile   = (LPCSTR) STACK32_POP( context );
790         *retv = RegLoadKey32A( hkey, lpszSubKey, lpszFile );
791     }
792     break;
793
794     case 0x0022:  /* RegUnLoadKey */
795     {
796         HKEY    hkey       = (HKEY)   STACK32_POP( context );
797         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
798         *retv = RegUnLoadKey32A( hkey, lpszSubKey );
799     }
800     break;
801
802     case 0x0023:  /* RegSaveKey */
803     {
804         HKEY    hkey       = (HKEY)   STACK32_POP( context );
805         LPCSTR  lpszFile   = (LPCSTR) STACK32_POP( context );
806         LPSECURITY_ATTRIBUTES sa = 
807                (LPSECURITY_ATTRIBUTES)STACK32_POP( context );
808         *retv = RegSaveKey32A( hkey, lpszFile, sa );
809     }
810     break;
811
812 #if 0 /* Functions are not yet implemented in misc/registry.c */
813     case 0x0024:  /* RegRemapPreDefKey */
814     case 0x0026:  /* RegQueryMultipleValues */
815 #endif
816
817     case 0x0027:  /* RegReplaceKey */
818     {
819         HKEY    hkey       = (HKEY)   STACK32_POP( context );
820         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
821         LPCSTR  lpszNewFile= (LPCSTR) STACK32_POP( context );
822         LPCSTR  lpszOldFile= (LPCSTR) STACK32_POP( context );
823         *retv = RegReplaceKey32A( hkey, lpszSubKey, lpszNewFile, lpszOldFile );
824     }
825     break;
826
827     default:
828         if (LOWORD(service) < N_VMM_SERVICE)
829             FIXME(win32, "Unimplemented service %s (%08lx)\n",
830                           VMM_Service_Name[LOWORD(service)], service);
831         else
832             FIXME(win32, "Unknown service %08lx\n", service);
833
834         ok = FALSE;
835         break;
836     }
837
838     return ok;
839 }
840
841
842 /***********************************************************************
843  *           VxDCall_IFSMgr
844  */
845 BOOL32 VxDCall_IFSMgr( DWORD *retv, DWORD service, CONTEXT *context )
846 {
847     if (LOWORD(service) < N_IFSMGR_SERVICE)
848         FIXME(win32, "Unimplemented service %s (%08lx)\n",
849                       IFSMgr_Service_Name[LOWORD(service)], service);
850     else
851         FIXME(win32, "Unknown service %08lx\n", service);
852
853         return FALSE;
854 }
855
856
857
858 /***********************************************************************
859  *           DeviceIo_IFSMgr
860  * NOTES
861  *   The ioctls is used by 'MSNET32.DLL'.
862  *
863  *   I have been unable to uncover any documentation about the ioctls so 
864  *   the implementation of the cases IFS_IOCTL_21 and IFS_IOCTL_2F are
865  *   based on a resonable guesses on information found in the Windows 95 DDK.
866  *   
867  */
868
869 struct win32apireq {
870         unsigned long   ar_proid;
871         unsigned long   ar_eax;         
872         unsigned long   ar_ebx; 
873         unsigned long   ar_ecx; 
874         unsigned long   ar_edx; 
875         unsigned long   ar_esi; 
876         unsigned long   ar_edi;
877         unsigned long   ar_ebp;         
878         unsigned short  ar_error;
879         unsigned short  ar_pad;
880 };
881
882 static void win32apieq_2_CONTEXT(struct win32apireq *pIn,CONTEXT *pCxt)
883 {
884         memset(pCxt,0,sizeof(CONTEXT));
885
886         pCxt->ContextFlags=CONTEXT_INTEGER|CONTEXT_CONTROL;
887         pCxt->Eax = pIn->ar_eax;
888         pCxt->Ebx = pIn->ar_ebx;
889         pCxt->Ecx = pIn->ar_ecx;
890         pCxt->Edx = pIn->ar_edx;
891         pCxt->Esi = pIn->ar_esi;
892         pCxt->Edi = pIn->ar_edi;
893
894         /* FIXME: Only partial CONTEXT_CONTROL */
895         pCxt->Ebp = pIn->ar_ebp;
896
897         /* FIXME: pIn->ar_proid ignored */
898         /* FIXME: pIn->ar_error ignored */
899         /* FIXME: pIn->ar_pad ignored */
900 }
901
902 static void CONTEXT_2_win32apieq(CONTEXT *pCxt,struct win32apireq *pOut)
903 {
904         memset(pOut,0,sizeof(struct win32apireq));
905
906         pOut->ar_eax = pCxt->Eax;
907         pOut->ar_ebx = pCxt->Ebx;
908         pOut->ar_ecx = pCxt->Ecx;
909         pOut->ar_edx = pCxt->Edx;
910         pOut->ar_esi = pCxt->Esi;
911         pOut->ar_edi = pCxt->Edi;
912
913         /* FIXME: Only partial CONTEXT_CONTROL */
914         pOut->ar_ebp = pCxt->Ebp;
915
916         /* FIXME: pOut->ar_proid ignored */
917         /* FIXME: pOut->ar_error ignored */
918         /* FIXME: pOut->ar_pad ignored */
919 }
920
921 static BOOL32 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
922                               LPVOID lpvInBuffer, DWORD cbInBuffer,
923                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
924                               LPDWORD lpcbBytesReturned,
925                               LPOVERLAPPED lpOverlapped)
926 {
927     BOOL32 retv = TRUE;
928         TRACE(win32,"(%p,%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
929                         dev,dwIoControlCode,
930                         lpvInBuffer,cbInBuffer,
931                         lpvOutBuffer,cbOutBuffer,
932                         lpcbBytesReturned,
933                         lpOverlapped);
934
935     switch (dwIoControlCode)
936     {
937         case IFS_IOCTL_21:
938         case IFS_IOCTL_2F:{
939                 CONTEXT cxt;
940                 struct win32apireq *pIn=(struct win32apireq *) lpvInBuffer;
941                 struct win32apireq *pOut=(struct win32apireq *) lpvOutBuffer;
942
943                 TRACE(win32,
944                         "Control '%s': "
945                         "proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
946                         "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx, ebp=0x%08lx, "
947                         "error=0x%04x, pad=0x%04x\n",
948                         (dwIoControlCode==IFS_IOCTL_21)?"IFS_IOCTL_21":"IFS_IOCTL_2F",
949                         pIn->ar_proid, pIn->ar_eax, pIn->ar_ebx, pIn->ar_ecx,
950                         pIn->ar_edx, pIn->ar_esi, pIn->ar_edi, pIn->ar_ebp,
951                         pIn->ar_error, pIn->ar_pad
952                 );                              
953                 
954                 win32apieq_2_CONTEXT(pIn,&cxt);
955
956                 if(dwIoControlCode==IFS_IOCTL_21)
957                 {
958                         DOS3Call(&cxt); /* Call int 21h */
959                 } else {
960                         INT_Int2fHandler(&cxt); /* Call int 2Fh */
961                 }
962                 
963                 CONTEXT_2_win32apieq(&cxt,pOut);
964                         
965         retv = TRUE;
966         } break;
967         case IFS_IOCTL_GET_RES:{
968         FIXME(win32, "Control 'IFS_IOCTL_GET_RES' not implemented\n");
969         retv = FALSE;
970         } break;
971         case IFS_IOCTL_GET_NETPRO_NAME_A:{
972         FIXME(win32, "Control 'IFS_IOCTL_GET_NETPRO_NAME_A' not implemented\n");
973         retv = FALSE;
974         } break;         
975     default:
976         FIXME(win32, "Control %ld not implemented\n", dwIoControlCode);
977         retv = FALSE;
978     }
979
980     return retv;
981 }