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