New stubs PrivateExtractIconEx[AW], PrivateExtractIconsW,
[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 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
67                               LPVOID lpvInBuffer, DWORD cbInBuffer,
68                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
69                               LPDWORD lpcbBytesReturned,
70                               LPOVERLAPPED lpOverlapped);
71
72 /*
73  * VxD names are taken from the Win95 DDK
74  */
75
76 struct VxDInfo
77 {
78     LPCSTR  name;
79     WORD    id;
80     BOOL32  (*vxdcall)(DWORD *, DWORD, CONTEXT *);
81     BOOL32  (*deviceio)(DEVICE_OBJECT *, DWORD, LPVOID, DWORD, 
82                         LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
83 }   
84     VxDList[] = 
85 {
86     /* Standard VxD IDs */
87     { "VMM",      0x0001, VxDCall_VMM, NULL },
88     { "DEBUG",    0x0002, NULL, NULL },
89     { "VPICD",    0x0003, NULL, NULL },
90     { "VDMAD",    0x0004, NULL, NULL },
91     { "VTD",      0x0005, NULL, NULL },
92     { "V86MMGR",  0x0006, NULL, NULL },
93     { "PAGESWAP", 0x0007, NULL, NULL },
94     { "PARITY",   0x0008, NULL, NULL },
95     { "REBOOT",   0x0009, NULL, NULL },
96     { "VDD",      0x000A, NULL, NULL },
97     { "VSD",      0x000B, NULL, NULL },
98     { "VMD",      0x000C, NULL, NULL },
99     { "VKD",      0x000D, NULL, NULL },
100     { "VCD",      0x000E, NULL, NULL },
101     { "VPD",      0x000F, NULL, NULL },
102     { "BLOCKDEV", 0x0010, NULL, NULL },
103     { "VMCPD",    0x0011, NULL, NULL },
104     { "EBIOS",    0x0012, NULL, NULL },
105     { "BIOSXLAT", 0x0013, NULL, NULL },
106     { "VNETBIOS", 0x0014, NULL, NULL },
107     { "DOSMGR",   0x0015, NULL, NULL },
108     { "WINLOAD",  0x0016, NULL, NULL },
109     { "SHELL",    0x0017, NULL, NULL },
110     { "VMPOLL",   0x0018, NULL, NULL },
111     { "VPROD",    0x0019, NULL, NULL },
112     { "DOSNET",   0x001A, NULL, NULL },
113     { "VFD",      0x001B, NULL, NULL },
114     { "VDD2",     0x001C, NULL, NULL },
115     { "WINDEBUG", 0x001D, NULL, NULL },
116     { "TSRLOAD",  0x001E, NULL, NULL },
117     { "BIOSHOOK", 0x001F, NULL, NULL },
118     { "INT13",    0x0020, NULL, NULL },
119     { "PAGEFILE", 0x0021, NULL, NULL },
120     { "SCSI",     0x0022, NULL, NULL },
121     { "MCA_POS",  0x0023, NULL, NULL },
122     { "SCSIFD",   0x0024, NULL, NULL },
123     { "VPEND",    0x0025, NULL, NULL },
124     { "VPOWERD",  0x0026, NULL, NULL },
125     { "VXDLDR",   0x0027, NULL, NULL },
126     { "NDIS",     0x0028, NULL, NULL },
127     { "BIOS_EXT", 0x0029, NULL, NULL },
128     { "VWIN32",   0x002A, NULL, NULL },
129     { "VCOMM",    0x002B, NULL, NULL },
130     { "SPOOLER",  0x002C, NULL, NULL },
131     { "WIN32S",   0x002D, NULL, NULL },
132     { "DEBUGCMD", 0x002E, NULL, NULL },
133
134     { "VNB",      0x0031, NULL, NULL },
135     { "SERVER",   0x0032, NULL, NULL },
136     { "CONFIGMG", 0x0033, NULL, NULL },
137     { "DWCFGMG",  0x0034, NULL, NULL },
138     { "SCSIPORT", 0x0035, NULL, NULL },
139     { "VFBACKUP", 0x0036, NULL, NULL },
140     { "ENABLE",   0x0037, NULL, NULL },
141     { "VCOND",    0x0038, NULL, NULL },
142
143     { "EFAX",     0x003A, NULL, NULL },
144     { "DSVXD",    0x003B, NULL, NULL },
145     { "ISAPNP",   0x003C, NULL, NULL },
146     { "BIOS",     0x003D, NULL, NULL },
147     { "WINSOCK",  0x003E, NULL, NULL },
148     { "WSOCK",    0x003E, NULL, NULL },
149     { "WSIPX",    0x003F, NULL, NULL },
150     { "IFSMgr",   0x0040, NULL, DeviceIo_IFSMgr },
151     { "VCDFSD",   0x0041, NULL, NULL },
152     { "MRCI2",    0x0042, NULL, NULL },
153     { "PCI",      0x0043, NULL, NULL },
154     { "PELOADER", 0x0044, NULL, NULL },
155     { "EISA",     0x0045, NULL, NULL },
156     { "DRAGCLI",  0x0046, NULL, NULL },
157     { "DRAGSRV",  0x0047, NULL, NULL },
158     { "PERF",     0x0048, NULL, NULL },
159     { "AWREDIR",  0x0049, NULL, NULL },
160
161     /* Far East support */
162     { "ETEN",     0x0060, NULL, NULL },
163     { "CHBIOS",   0x0061, NULL, NULL },
164     { "VMSGD",    0x0062, NULL, NULL },
165     { "VPPID",    0x0063, NULL, NULL },
166     { "VIME",     0x0064, NULL, NULL },
167     { "VHBIOSD",  0x0065, NULL, NULL },
168
169     /* Multimedia OEM IDs */
170     { "VTDAPI",   0x0442, NULL, DeviceIo_VTDAPI },
171
172     /* Network Device IDs */
173     { "VNetSup",  0x0480, NULL, NULL },
174     { "VRedir",   0x0481, NULL, NULL },
175     { "VBrowse",  0x0482, NULL, NULL },
176     { "VSHARE",   0x0483, NULL, NULL },
177     { "IFSMgr",   0x0484, NULL, NULL },
178     { "MEMPROBE", 0x0485, NULL, NULL },
179     { "VFAT",     0x0486, NULL, NULL },
180     { "NWLINK",   0x0487, NULL, NULL },
181     { "VNWLINK",  0x0487, NULL, NULL },
182     { "NWSUP",    0x0487, NULL, NULL },
183     { "VTDI",     0x0488, NULL, NULL },
184     { "VIP",      0x0489, NULL, NULL },
185     { "VTCP",     0x048A, NULL, NULL },
186     { "VCache",   0x048B, NULL, NULL },
187     { "VUDP",     0x048C, NULL, NULL },
188     { "VAsync",   0x048D, NULL, NULL },
189     { "NWREDIR",  0x048E, NULL, NULL },
190     { "STAT80",   0x048F, NULL, NULL },
191     { "SCSIPORT", 0x0490, NULL, NULL },
192     { "FILESEC",  0x0491, NULL, NULL },
193     { "NWSERVER", 0x0492, NULL, NULL },
194     { "SECPROV",  0x0493, NULL, NULL },
195     { "NSCL",     0x0494, NULL, NULL },
196     { "WSTCP",    0x0495, NULL, NULL },
197     { "NDIS2SUP", 0x0496, NULL, NULL },
198     { "MSODISUP", 0x0497, NULL, NULL },
199     { "Splitter", 0x0498, NULL, NULL },
200     { "PPP",      0x0499, NULL, NULL },
201     { "VDHCP",    0x049A, NULL, NULL },
202     { "VNBT",     0x049B, NULL, NULL },
203     { "LOGGER",   0x049D, NULL, NULL },
204     { "EFILTER",  0x049E, NULL, NULL },
205     { "FFILTER",  0x049F, NULL, NULL },
206     { "TFILTER",  0x04A0, NULL, NULL },
207     { "AFILTER",  0x04A1, NULL, NULL },
208     { "IRLAMP",   0x04A2, NULL, NULL },
209
210     { NULL,       0,      NULL, NULL }
211 };
212
213 /*
214  * VMM VxDCall service names are (mostly) taken from Stan Mitchell's
215  * "Inside the Windows 95 File System"
216  */
217
218 #define N_VMM_SERVICE 41
219
220 LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
221
222     "PageReserve",            /* 0x0000 */
223     "PageCommit",             /* 0x0001 */
224     "PageDecommit",           /* 0x0002 */
225     "PagerRegister",          /* 0x0003 */
226     "PagerQuery",             /* 0x0004 */
227     "HeapAllocate",           /* 0x0005 */
228     "ContextCreate",          /* 0x0006 */
229     "ContextDestroy",         /* 0x0007 */
230     "PageAttach",             /* 0x0008 */
231     "PageFlush",              /* 0x0009 */
232     "PageFree",               /* 0x000A */
233     "ContextSwitch",          /* 0x000B */
234     "HeapReAllocate",         /* 0x000C */
235     "PageModifyPerm",         /* 0x000D */
236     "PageQuery",              /* 0x000E */
237     "GetCurrentContext",      /* 0x000F */
238     "HeapFree",               /* 0x0010 */
239     "RegOpenKey",             /* 0x0011 */
240     "RegCreateKey",           /* 0x0012 */
241     "RegCloseKey",            /* 0x0013 */
242     "RegDeleteKey",           /* 0x0014 */
243     "RegSetValue",            /* 0x0015 */
244     "RegDeleteValue",         /* 0x0016 */
245     "RegQueryValue",          /* 0x0017 */
246     "RegEnumKey",             /* 0x0018 */
247     "RegEnumValue",           /* 0x0019 */
248     "RegQueryValueEx",        /* 0x001A */
249     "RegSetValueEx",          /* 0x001B */
250     "RegFlushKey",            /* 0x001C */
251     "RegQueryInfoKey",        /* 0x001D */
252     "GetDemandPageInfo",      /* 0x001E */
253     "BlockOnID",              /* 0x001F */
254     "SignalID",               /* 0x0020 */
255     "RegLoadKey",             /* 0x0021 */
256     "RegUnLoadKey",           /* 0x0022 */
257     "RegSaveKey",             /* 0x0023 */
258     "RegRemapPreDefKey",      /* 0x0024 */
259     "PageChangePager",        /* 0x0025 */
260     "RegQueryMultipleValues", /* 0x0026 */
261     "RegReplaceKey",          /* 0x0027 */
262     "<KERNEL32.101>"          /* 0x0028 -- What does this do??? */
263 };
264
265 HANDLE32 DEVICE_Open(LPCSTR filename, DWORD access) 
266 {
267         DEVICE_OBJECT *dev;
268         HANDLE32 handle;
269         int i;
270
271         dev = HeapAlloc( SystemHeap, 0, sizeof(DEVICE_OBJECT) );
272         if (!dev) return INVALID_HANDLE_VALUE32;
273
274         dev->header.type = K32OBJ_DEVICE_IOCTL;
275         dev->header.refcount = 1;
276         dev->mode       = access;
277         dev->devname    = HEAP_strdupA(SystemHeap,0,filename);
278         dev->info       = NULL;
279
280         for (i = 0; VxDList[i].name; i++)
281             if (!lstrcmpi32A(VxDList[i].name, filename))
282                 break;
283         if (VxDList[i].name)
284             dev->info = &VxDList[i];
285         else
286             FIXME(win32, "Unknown VxD %s\n", filename);
287
288
289         handle = HANDLE_Alloc( PROCESS_Current(), &(dev->header),
290                                FILE_ALL_ACCESS | GENERIC_READ |
291                                GENERIC_WRITE | GENERIC_EXECUTE /*FIXME*/, TRUE, -1 );
292         /* If the allocation failed, the object is already destroyed */
293         if (handle == INVALID_HANDLE_VALUE32) dev = NULL;
294         return handle;
295 }
296
297 static void DEVICE_Destroy(K32OBJ *obj) 
298 {
299     DEVICE_OBJECT *dev = (DEVICE_OBJECT *)obj;
300     assert( obj->type == K32OBJ_DEVICE_IOCTL );
301
302     if ( dev->devname )
303     {
304         HeapFree( SystemHeap, 0, dev->devname );
305         dev->devname = NULL;
306     }
307
308     obj->type = K32OBJ_UNKNOWN;
309     HeapFree( SystemHeap, 0, dev );
310 }
311
312 /****************************************************************************
313  *              DeviceIoControl (KERNEL32.188)
314  * This is one of those big ugly nasty procedure which can do
315  * a million and one things when it comes to devices. It can also be
316  * used for VxD communication.
317  *
318  * A return value of FALSE indicates that something has gone wrong which
319  * GetLastError can decypher.
320  */
321 BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode, 
322                               LPVOID lpvInBuffer, DWORD cbInBuffer,
323                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
324                               LPDWORD lpcbBytesReturned,
325                               LPOVERLAPPED lpOverlapped)
326 {
327         DEVICE_OBJECT   *dev = (DEVICE_OBJECT *)HANDLE_GetObjPtr(
328                 PROCESS_Current(), hDevice, K32OBJ_DEVICE_IOCTL, 0 /*FIXME*/, NULL );
329
330         TRACE(win32, "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n",
331                 hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
332                 lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped
333         );
334
335         if (!dev)
336         {
337                 SetLastError( ERROR_INVALID_PARAMETER );
338                 return FALSE;
339         }
340
341         /* Check if this is a user defined control code for a VxD */
342         if( HIWORD( dwIoControlCode ) == 0 )
343         {
344                 if ( dev->info && dev->info->deviceio )
345                 {
346                         return dev->info->deviceio( dev, dwIoControlCode, 
347                                         lpvInBuffer, cbInBuffer, 
348                                         lpvOutBuffer, cbOutBuffer, 
349                                         lpcbBytesReturned, lpOverlapped );
350                 }
351                 else
352                 {
353                         /* FIXME: Set appropriate error */
354                         FIXME( win32, "Unimplemented control %ld for VxD device %s\n", 
355                                           dwIoControlCode, dev->devname );
356                 }
357         }
358         else
359         {
360                 switch( dwIoControlCode )
361                 {
362                 case FSCTL_DELETE_REPARSE_POINT:
363                 case FSCTL_DISMOUNT_VOLUME:
364                 case FSCTL_GET_COMPRESSION:
365                 case FSCTL_GET_REPARSE_POINT:
366                 case FSCTL_LOCK_VOLUME:
367                 case FSCTL_QUERY_ALLOCATED_RANGES:
368                 case FSCTL_SET_COMPRESSION:
369                 case FSCTL_SET_REPARSE_POINT:
370                 case FSCTL_SET_SPARSE:
371                 case FSCTL_SET_ZERO_DATA:
372                 case FSCTL_UNLOCK_VOLUME:
373                 case IOCTL_DISK_CHECK_VERIFY:
374                 case IOCTL_DISK_EJECT_MEDIA:
375                 case IOCTL_DISK_FORMAT_TRACKS:
376                 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
377                 case IOCTL_DISK_GET_DRIVE_LAYOUT:
378                 case IOCTL_DISK_GET_MEDIA_TYPES:
379                 case IOCTL_DISK_GET_PARTITION_INFO:
380                 case IOCTL_DISK_LOAD_MEDIA:
381                 case IOCTL_DISK_MEDIA_REMOVAL:
382                 case IOCTL_DISK_PERFORMANCE:
383                 case IOCTL_DISK_REASSIGN_BLOCKS:
384                 case IOCTL_DISK_SET_DRIVE_LAYOUT:
385                 case IOCTL_DISK_SET_PARTITION_INFO:
386                 case IOCTL_DISK_VERIFY:
387                 case IOCTL_SERIAL_LSRMST_INSERT:
388                 case IOCTL_STORAGE_CHECK_VERIFY:
389                 case IOCTL_STORAGE_EJECT_MEDIA:
390                 case IOCTL_STORAGE_GET_MEDIA_TYPES:
391                 case IOCTL_STORAGE_LOAD_MEDIA:
392                 case IOCTL_STORAGE_MEDIA_REMOVAL:
393                         FIXME( win32, "unimplemented dwIoControlCode=%08lx\n", dwIoControlCode);
394                         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
395                         return FALSE;
396                         break;
397                 default:
398                         FIXME( win32, "ignored dwIoControlCode=%08lx\n",dwIoControlCode);
399                         SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
400                         return FALSE;
401                         break;
402                 }
403         }
404         return FALSE;
405 }
406  
407 /***********************************************************************
408  *           DeviceIo_VTDAPI
409  */
410 static BOOL32 DeviceIo_VTDAPI(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
411                               LPVOID lpvInBuffer, DWORD cbInBuffer,
412                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
413                               LPDWORD lpcbBytesReturned,
414                               LPOVERLAPPED lpOverlapped)
415 {
416     BOOL32 retv = TRUE;
417
418     switch (dwIoControlCode)
419     {
420     case 5:
421         if (lpvOutBuffer && (cbOutBuffer>=4))
422             *(DWORD*)lpvOutBuffer = timeGetTime();
423
424         if (lpcbBytesReturned)
425             *lpcbBytesReturned = 4;
426
427         break;
428
429     default:
430         FIXME(win32, "Control %ld not implemented\n", dwIoControlCode);
431         retv = FALSE;
432         break;
433     }
434
435     return retv;
436 }
437
438
439
440
441
442 /***********************************************************************
443  *           VxDCall                   (KERNEL32.[1-9])
444  */
445 static void VxDCall( CONTEXT *context, int nArgs )
446 {
447     DWORD retv, service;
448     int i, ok = FALSE;
449
450     /* Pop return address to caller */
451     EIP_reg(context) = STACK32_POP(context);
452
453     /* Pop requested service ID */
454     service = STACK32_POP(context);
455
456     TRACE(win32, "(%08lx, ...)\n", service);
457
458     for (i = 0; VxDList[i].name; i++)
459         if (VxDList[i].id == HIWORD(service))
460             break;
461
462     if (!VxDList[i].name)
463         FIXME(win32, "Unknown VxD (%08lx)\n", service);
464     else if (!VxDList[i].vxdcall)
465         FIXME(win32, "Unimplemented VxD (%08lx)\n", service);
466     else
467         ok = VxDList[i].vxdcall(&retv, service, context);
468
469     /* If unimplemented, trust the caller to have called the
470        version with the correct number of arguments */
471     if (!ok)
472     {
473         ESP_reg(context) += 4 * nArgs;
474         retv = 0xffffffff;  /* FIXME */
475     }
476
477     /* Push return address back onto stack */
478     STACK32_PUSH(context, EIP_reg(context));
479
480     /* Return to caller */
481     EAX_reg(context) = retv;
482 }
483
484 REGS_ENTRYPOINT(VxDCall0) { VxDCall( context, 0 ); }
485 REGS_ENTRYPOINT(VxDCall1) { VxDCall( context, 1 ); }
486 REGS_ENTRYPOINT(VxDCall2) { VxDCall( context, 2 ); }
487 REGS_ENTRYPOINT(VxDCall3) { VxDCall( context, 3 ); }
488 REGS_ENTRYPOINT(VxDCall4) { VxDCall( context, 4 ); }
489 REGS_ENTRYPOINT(VxDCall5) { VxDCall( context, 5 ); }
490 REGS_ENTRYPOINT(VxDCall6) { VxDCall( context, 6 ); }
491 REGS_ENTRYPOINT(VxDCall7) { VxDCall( context, 7 ); }
492 REGS_ENTRYPOINT(VxDCall8) { VxDCall( context, 8 ); }
493
494 /***********************************************************************
495  *           VxDCall_VMM
496  */
497 BOOL32 VxDCall_VMM( DWORD *retv, DWORD service, CONTEXT *context )
498 {
499     BOOL32 ok = TRUE;
500
501     switch ( LOWORD(service) )
502     {
503     case 0x0011:  /* RegOpenKey */
504     {
505         HKEY    hkey       = (HKEY)   STACK32_POP( context );
506         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
507         LPHKEY  retkey     = (LPHKEY) STACK32_POP( context );
508         *retv = RegOpenKey32A( hkey, lpszSubKey, retkey );
509     }
510     break;
511
512     case 0x0012:  /* RegCreateKey */
513     {
514         HKEY    hkey       = (HKEY)   STACK32_POP( context );
515         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
516         LPHKEY  retkey     = (LPHKEY) STACK32_POP( context );
517         *retv = RegCreateKey32A( hkey, lpszSubKey, retkey );
518     }
519     break;
520
521     case 0x0013:  /* RegCloseKey */
522     {
523         HKEY    hkey       = (HKEY)   STACK32_POP( context );
524         *retv = RegCloseKey( hkey );
525     }
526     break;
527
528     case 0x0014:  /* RegDeleteKey */
529     {
530         HKEY    hkey       = (HKEY)   STACK32_POP( context );
531         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
532         *retv = RegDeleteKey32A( hkey, lpszSubKey );
533     }
534     break;
535
536     case 0x0015:  /* RegSetValue */
537     {
538         HKEY    hkey       = (HKEY)   STACK32_POP( context );
539         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
540         DWORD   dwType     = (DWORD)  STACK32_POP( context );
541         LPCSTR  lpszData   = (LPCSTR) STACK32_POP( context );
542         DWORD   cbData     = (DWORD)  STACK32_POP( context );
543         *retv = RegSetValue32A( hkey, lpszSubKey, dwType, lpszData, cbData );
544     }
545     break;
546
547     case 0x0016:  /* RegDeleteValue */
548     {
549         HKEY    hkey       = (HKEY)   STACK32_POP( context );
550         LPSTR   lpszValue  = (LPSTR)  STACK32_POP( context );
551         *retv = RegDeleteValue32A( hkey, lpszValue );
552     }
553     break;
554
555     case 0x0017:  /* RegQueryValue */
556     {
557         HKEY    hkey       = (HKEY)   STACK32_POP( context );
558         LPSTR   lpszSubKey = (LPSTR)  STACK32_POP( context );
559         LPSTR   lpszData   = (LPSTR)  STACK32_POP( context );
560         LPDWORD lpcbData   = (LPDWORD)STACK32_POP( context );
561         *retv = RegQueryValue32A( hkey, lpszSubKey, lpszData, lpcbData );
562     }
563     break;
564
565     case 0x0018:  /* RegEnumKey */
566     {
567         HKEY    hkey       = (HKEY)   STACK32_POP( context );
568         DWORD   iSubkey    = (DWORD)  STACK32_POP( context );
569         LPSTR   lpszName   = (LPSTR)  STACK32_POP( context );
570         DWORD   lpcchName  = (DWORD)  STACK32_POP( context );
571         *retv = RegEnumKey32A( hkey, iSubkey, lpszName, lpcchName );
572     }
573     break;
574
575     case 0x0019:  /* RegEnumValue */
576     {
577         HKEY    hkey       = (HKEY)   STACK32_POP( context );
578         DWORD   iValue     = (DWORD)  STACK32_POP( context );
579         LPSTR   lpszValue  = (LPSTR)  STACK32_POP( context );
580         LPDWORD lpcchValue = (LPDWORD)STACK32_POP( context );
581         LPDWORD lpReserved = (LPDWORD)STACK32_POP( context );
582         LPDWORD lpdwType   = (LPDWORD)STACK32_POP( context );
583         LPBYTE  lpbData    = (LPBYTE) STACK32_POP( context );
584         LPDWORD lpcbData   = (LPDWORD)STACK32_POP( context );
585         *retv = RegEnumValue32A( hkey, iValue, lpszValue, lpcchValue, 
586                                  lpReserved, lpdwType, lpbData, lpcbData );
587     }
588     break;
589
590     case 0x001A:  /* RegQueryValueEx */
591     {
592         HKEY    hkey       = (HKEY)   STACK32_POP( context );
593         LPSTR   lpszValue  = (LPSTR)  STACK32_POP( context );
594         LPDWORD lpReserved = (LPDWORD)STACK32_POP( context );
595         LPDWORD lpdwType   = (LPDWORD)STACK32_POP( context );
596         LPBYTE  lpbData    = (LPBYTE) STACK32_POP( context );
597         LPDWORD lpcbData   = (LPDWORD)STACK32_POP( context );
598         *retv = RegQueryValueEx32A( hkey, lpszValue, lpReserved, 
599                                     lpdwType, lpbData, lpcbData );
600     }
601     break;
602
603     case 0x001B:  /* RegSetValueEx */
604     {
605         HKEY    hkey       = (HKEY)   STACK32_POP( context );
606         LPSTR   lpszValue  = (LPSTR)  STACK32_POP( context );
607         DWORD   dwReserved = (DWORD)  STACK32_POP( context );
608         DWORD   dwType     = (DWORD)  STACK32_POP( context );
609         LPBYTE  lpbData    = (LPBYTE) STACK32_POP( context );
610         DWORD   cbData     = (DWORD)STACK32_POP( context );
611         *retv = RegSetValueEx32A( hkey, lpszValue, dwReserved, 
612                                   dwType, lpbData, cbData );
613     }
614     break;
615
616     case 0x001C:  /* RegFlushKey */
617     {
618         HKEY    hkey       = (HKEY)   STACK32_POP( context );
619         *retv = RegFlushKey( hkey );
620     }
621     break;
622
623     case 0x001D:  /* RegQueryInfoKey */
624     {
625         /* NOTE: This VxDCall takes only a subset of the parameters that the
626                  corresponding Win32 API call does. The implementation in Win95
627                  ADVAPI32 sets all output parameters not mentioned here to zero. */
628
629         HKEY    hkey       = (HKEY)   STACK32_POP( context );
630         LPDWORD lpcSubKeys = (LPDWORD)STACK32_POP( context );
631         LPDWORD lpcchMaxSubKey 
632                            = (LPDWORD)STACK32_POP( context );
633         LPDWORD lpcValues  = (LPDWORD)STACK32_POP( context );
634         LPDWORD lpcchMaxValueName 
635                            = (LPDWORD)STACK32_POP( context );
636         LPDWORD lpcchMaxValueData 
637                            = (LPDWORD)STACK32_POP( context );
638         *retv = RegQueryInfoKey32A( hkey, NULL, NULL, NULL, lpcSubKeys, lpcchMaxSubKey,
639                                     NULL, lpcValues, lpcchMaxValueName, lpcchMaxValueData,
640                                     NULL, NULL );
641     }
642     break;
643
644     case 0x0021:  /* RegLoadKey */
645     {
646         HKEY    hkey       = (HKEY)   STACK32_POP( context );
647         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
648         LPCSTR  lpszFile   = (LPCSTR) STACK32_POP( context );
649         *retv = RegLoadKey32A( hkey, lpszSubKey, lpszFile );
650     }
651     break;
652
653     case 0x0022:  /* RegUnLoadKey */
654     {
655         HKEY    hkey       = (HKEY)   STACK32_POP( context );
656         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
657         *retv = RegUnLoadKey32A( hkey, lpszSubKey );
658     }
659     break;
660
661     case 0x0023:  /* RegSaveKey */
662     {
663         HKEY    hkey       = (HKEY)   STACK32_POP( context );
664         LPCSTR  lpszFile   = (LPCSTR) STACK32_POP( context );
665         LPSECURITY_ATTRIBUTES sa = 
666                (LPSECURITY_ATTRIBUTES)STACK32_POP( context );
667         *retv = RegSaveKey32A( hkey, lpszFile, sa );
668     }
669     break;
670
671 #if 0 /* Functions are not yet implemented in misc/registry.c */
672     case 0x0024:  /* RegRemapPreDefKey */
673     case 0x0026:  /* RegQueryMultipleValues */
674 #endif
675
676     case 0x0027:  /* RegReplaceKey */
677     {
678         HKEY    hkey       = (HKEY)   STACK32_POP( context );
679         LPCSTR  lpszSubKey = (LPCSTR) STACK32_POP( context );
680         LPCSTR  lpszNewFile= (LPCSTR) STACK32_POP( context );
681         LPCSTR  lpszOldFile= (LPCSTR) STACK32_POP( context );
682         *retv = RegReplaceKey32A( hkey, lpszSubKey, lpszNewFile, lpszOldFile );
683     }
684     break;
685
686     default:
687         if (LOWORD(service) < N_VMM_SERVICE)
688             FIXME(win32, "Unimplemented service %s (%08lx)\n",
689                           VMM_Service_Name[LOWORD(service)], service);
690         else
691             FIXME(win32, "Unknown service %08lx\n", service);
692
693         ok = FALSE;
694         break;
695     }
696
697     return ok;
698 }
699
700 /***********************************************************************
701  *           DeviceIo_IFSMgr
702  * NOTES
703  *   The ioctls is used by 'MSNET32.DLL'.
704  *
705  *   I have been unable to uncover any documentation about the ioctls so 
706  *   the implementation of the cases IFS_IOCTL_21 and IFS_IOCTL_2F are
707  *   based on a resonable guesses on information found in the Windows 95 DDK.
708  *   
709  */
710
711 /*
712  * IFSMgr DeviceIO service
713  */
714
715 #define IFS_IOCTL_21                100
716 #define IFS_IOCTL_2F                101
717 #define IFS_IOCTL_GET_RES           102
718 #define IFS_IOCTL_GET_NETPRO_NAME_A 103
719
720 struct win32apireq {
721         unsigned long   ar_proid;
722         unsigned long   ar_eax;         
723         unsigned long   ar_ebx; 
724         unsigned long   ar_ecx; 
725         unsigned long   ar_edx; 
726         unsigned long   ar_esi; 
727         unsigned long   ar_edi;
728         unsigned long   ar_ebp;         
729         unsigned short  ar_error;
730         unsigned short  ar_pad;
731 };
732
733 static void win32apieq_2_CONTEXT(struct win32apireq *pIn,CONTEXT *pCxt)
734 {
735         memset(pCxt,0,sizeof(CONTEXT));
736
737         pCxt->ContextFlags=CONTEXT_INTEGER|CONTEXT_CONTROL;
738         pCxt->Eax = pIn->ar_eax;
739         pCxt->Ebx = pIn->ar_ebx;
740         pCxt->Ecx = pIn->ar_ecx;
741         pCxt->Edx = pIn->ar_edx;
742         pCxt->Esi = pIn->ar_esi;
743         pCxt->Edi = pIn->ar_edi;
744
745         /* FIXME: Only partial CONTEXT_CONTROL */
746         pCxt->Ebp = pIn->ar_ebp;
747
748         /* FIXME: pIn->ar_proid ignored */
749         /* FIXME: pIn->ar_error ignored */
750         /* FIXME: pIn->ar_pad ignored */
751 }
752
753 static void CONTEXT_2_win32apieq(CONTEXT *pCxt,struct win32apireq *pOut)
754 {
755         memset(pOut,0,sizeof(struct win32apireq));
756
757         pOut->ar_eax = pCxt->Eax;
758         pOut->ar_ebx = pCxt->Ebx;
759         pOut->ar_ecx = pCxt->Ecx;
760         pOut->ar_edx = pCxt->Edx;
761         pOut->ar_esi = pCxt->Esi;
762         pOut->ar_edi = pCxt->Edi;
763
764         /* FIXME: Only partial CONTEXT_CONTROL */
765         pOut->ar_ebp = pCxt->Ebp;
766
767         /* FIXME: pOut->ar_proid ignored */
768         /* FIXME: pOut->ar_error ignored */
769         /* FIXME: pOut->ar_pad ignored */
770 }
771
772 static BOOL32 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
773                               LPVOID lpvInBuffer, DWORD cbInBuffer,
774                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
775                               LPDWORD lpcbBytesReturned,
776                               LPOVERLAPPED lpOverlapped)
777 {
778     BOOL32 retv = TRUE;
779         TRACE(win32,"(%p,%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
780                         dev,dwIoControlCode,
781                         lpvInBuffer,cbInBuffer,
782                         lpvOutBuffer,cbOutBuffer,
783                         lpcbBytesReturned,
784                         lpOverlapped);
785
786     switch (dwIoControlCode)
787     {
788         case IFS_IOCTL_21:
789         case IFS_IOCTL_2F:{
790                 CONTEXT cxt;
791                 struct win32apireq *pIn=(struct win32apireq *) lpvInBuffer;
792                 struct win32apireq *pOut=(struct win32apireq *) lpvOutBuffer;
793
794                 TRACE(win32,
795                         "Control '%s': "
796                         "proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
797                         "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx, ebp=0x%08lx, "
798                         "error=0x%04x, pad=0x%04x\n",
799                         (dwIoControlCode==IFS_IOCTL_21)?"IFS_IOCTL_21":"IFS_IOCTL_2F",
800                         pIn->ar_proid, pIn->ar_eax, pIn->ar_ebx, pIn->ar_ecx,
801                         pIn->ar_edx, pIn->ar_esi, pIn->ar_edi, pIn->ar_ebp,
802                         pIn->ar_error, pIn->ar_pad
803                 );                              
804                 
805                 win32apieq_2_CONTEXT(pIn,&cxt);
806
807                 if(dwIoControlCode==IFS_IOCTL_21)
808                 {
809                         DOS3Call(&cxt); /* Call int 21h */
810                 } else {
811                         INT_Int2fHandler(&cxt); /* Call int 2Fh */
812                 }
813                 
814                 CONTEXT_2_win32apieq(&cxt,pOut);
815                         
816         retv = TRUE;
817         } break;
818         case IFS_IOCTL_GET_RES:{
819         FIXME(win32, "Control 'IFS_IOCTL_GET_RES' not implemented\n");
820         retv = FALSE;
821         } break;
822         case IFS_IOCTL_GET_NETPRO_NAME_A:{
823         FIXME(win32, "Control 'IFS_IOCTL_GET_NETPRO_NAME_A' not implemented\n");
824         retv = FALSE;
825         } break;         
826     default:
827         FIXME(win32, "Control %ld not implemented\n", dwIoControlCode);
828         retv = FALSE;
829     }
830
831     return retv;
832 }