Scale the buffer sizes with MAX_LISTED_ENV_VAR.
[wine] / dlls / kernel / 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  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <sys/types.h>
31 #include <string.h>
32 #include <stdarg.h>
33 #include <time.h>
34
35 #include "ntstatus.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winreg.h"
39 #include "winerror.h"
40 #include "winnls.h"
41 #include "file.h"
42 #include "winioctl.h"
43 #include "winnt.h"
44 #include "kernel_private.h"
45 #include "wine/server.h"
46 #include "wine/debug.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(file);
49
50
51 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode,
52                               LPVOID lpvInBuffer, DWORD cbInBuffer,
53                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
54                               LPDWORD lpcbBytesReturned,
55                               LPOVERLAPPED lpOverlapped);
56 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode,
57                               LPVOID lpvInBuffer, DWORD cbInBuffer,
58                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
59                               LPDWORD lpcbBytesReturned,
60                               LPOVERLAPPED lpOverlapped);
61 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode,
62                               LPVOID lpvInBuffer, DWORD cbInBuffer,
63                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
64                               LPDWORD lpcbBytesReturned,
65                               LPOVERLAPPED lpOverlapped);
66
67 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode,
68                               LPVOID lpvInBuffer, DWORD cbInBuffer,
69                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
70                               LPDWORD lpcbBytesReturned,
71                               LPOVERLAPPED lpOverlapped);
72
73 static BOOL DeviceIo_VCD(DWORD dwIoControlCode,
74                               LPVOID lpvInBuffer, DWORD cbInBuffer,
75                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
76                               LPDWORD lpcbBytesReturned,
77                               LPOVERLAPPED lpOverlapped);
78
79 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode,
80                               LPVOID lpvInBuffer, DWORD cbInBuffer,
81                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
82                               LPDWORD lpcbBytesReturned,
83                               LPOVERLAPPED lpOverlapped);
84
85 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode,
86                               LPVOID lpvInBuffer, DWORD cbInBuffer,
87                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
88                               LPDWORD lpcbBytesReturned,
89                               LPOVERLAPPED lpOverlapped);
90
91 static BOOL DeviceIo_HASP (DWORD dwIoControlCode,
92                               LPVOID lpvInBuffer, DWORD cbInBuffer,
93                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
94                               LPDWORD lpcbBytesReturned,
95                               LPOVERLAPPED lpOverlapped);
96 /*
97  * VxD names are taken from the Win95 DDK
98  */
99
100 struct VxDInfo
101 {
102     LPCSTR  name;
103     WORD    id;
104     BOOL  (*deviceio)(DWORD, LPVOID, DWORD,
105                         LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
106 };
107
108 static const struct VxDInfo VxDList[] =
109 {
110     /* Standard VxD IDs */
111     { "VMM",      0x0001, NULL },
112     { "DEBUG",    0x0002, NULL },
113     { "VPICD",    0x0003, NULL },
114     { "VDMAD",    0x0004, NULL },
115     { "VTD",      0x0005, NULL },
116     { "V86MMGR",  0x0006, NULL },
117     { "PAGESWAP", 0x0007, NULL },
118     { "PARITY",   0x0008, NULL },
119     { "REBOOT",   0x0009, NULL },
120     { "VDD",      0x000A, NULL },
121     { "VSD",      0x000B, NULL },
122     { "VMD",      0x000C, NULL },
123     { "VKD",      0x000D, NULL },
124     { "VCD",      0x000E, DeviceIo_VCD },
125     { "VPD",      0x000F, NULL },
126     { "BLOCKDEV", 0x0010, NULL },
127     { "VMCPD",    0x0011, NULL },
128     { "EBIOS",    0x0012, NULL },
129     { "BIOSXLAT", 0x0013, NULL },
130     { "VNETBIOS", 0x0014, NULL },
131     { "DOSMGR",   0x0015, NULL },
132     { "WINLOAD",  0x0016, NULL },
133     { "SHELL",    0x0017, NULL },
134     { "VMPOLL",   0x0018, NULL },
135     { "VPROD",    0x0019, NULL },
136     { "DOSNET",   0x001A, NULL },
137     { "VFD",      0x001B, NULL },
138     { "VDD2",     0x001C, NULL },
139     { "WINDEBUG", 0x001D, NULL },
140     { "TSRLOAD",  0x001E, NULL },
141     { "BIOSHOOK", 0x001F, NULL },
142     { "INT13",    0x0020, NULL },
143     { "PAGEFILE", 0x0021, NULL },
144     { "SCSI",     0x0022, NULL },
145     { "MCA_POS",  0x0023, NULL },
146     { "SCSIFD",   0x0024, NULL },
147     { "VPEND",    0x0025, NULL },
148     { "VPOWERD",  0x0026, NULL },
149     { "VXDLDR",   0x0027, NULL },
150     { "NDIS",     0x0028, NULL },
151     { "BIOS_EXT", 0x0029, NULL },
152     { "VWIN32",   0x002A, DeviceIo_VWin32 },
153     { "VCOMM",    0x002B, NULL },
154     { "SPOOLER",  0x002C, NULL },
155     { "WIN32S",   0x002D, NULL },
156     { "DEBUGCMD", 0x002E, NULL },
157
158     { "VNB",      0x0031, NULL },
159     { "SERVER",   0x0032, NULL },
160     { "CONFIGMG", 0x0033, NULL },
161     { "DWCFGMG",  0x0034, NULL },
162     { "SCSIPORT", 0x0035, NULL },
163     { "VFBACKUP", 0x0036, NULL },
164     { "ENABLE",   0x0037, NULL },
165     { "VCOND",    0x0038, NULL },
166
167     { "EFAX",     0x003A, NULL },
168     { "DSVXD",    0x003B, NULL },
169     { "ISAPNP",   0x003C, NULL },
170     { "BIOS",     0x003D, NULL },
171     { "WINSOCK",  0x003E, NULL },
172     { "WSOCK",    0x003E, NULL },
173     { "WSIPX",    0x003F, NULL },
174     { "IFSMgr",   0x0040, DeviceIo_IFSMgr },
175     { "VCDFSD",   0x0041, NULL },
176     { "MRCI2",    0x0042, NULL },
177     { "PCI",      0x0043, NULL },
178     { "PELOADER", 0x0044, NULL },
179     { "EISA",     0x0045, NULL },
180     { "DRAGCLI",  0x0046, NULL },
181     { "DRAGSRV",  0x0047, NULL },
182     { "PERF",     0x0048, NULL },
183     { "AWREDIR",  0x0049, NULL },
184
185     /* Far East support */
186     { "ETEN",     0x0060, NULL },
187     { "CHBIOS",   0x0061, NULL },
188     { "VMSGD",    0x0062, NULL },
189     { "VPPID",    0x0063, NULL },
190     { "VIME",     0x0064, NULL },
191     { "VHBIOSD",  0x0065, NULL },
192
193     /* Multimedia OEM IDs */
194     { "VTDAPI",   0x0442, DeviceIo_VTDAPI },
195     { "MMDEVLDR", 0x044A, DeviceIo_MMDEVLDR },
196
197     /* Network Device IDs */
198     { "VNetSup",  0x0480, NULL },
199     { "VRedir",   0x0481, NULL },
200     { "VBrowse",  0x0482, NULL },
201     { "VSHARE",   0x0483, NULL },
202     { "IFSMgr",   0x0484, NULL },
203     { "MEMPROBE", 0x0485, NULL },
204     { "VFAT",     0x0486, NULL },
205     { "NWLINK",   0x0487, NULL },
206     { "VNWLINK",  0x0487, NULL },
207     { "NWSUP",    0x0487, NULL },
208     { "VTDI",     0x0488, NULL },
209     { "VIP",      0x0489, NULL },
210     { "VTCP",     0x048A, NULL },
211     { "VCache",   0x048B, NULL },
212     { "VUDP",     0x048C, NULL },
213     { "VAsync",   0x048D, NULL },
214     { "NWREDIR",  0x048E, NULL },
215     { "STAT80",   0x048F, NULL },
216     { "SCSIPORT", 0x0490, NULL },
217     { "FILESEC",  0x0491, NULL },
218     { "NWSERVER", 0x0492, NULL },
219     { "SECPROV",  0x0493, NULL },
220     { "NSCL",     0x0494, NULL },
221     { "WSTCP",    0x0495, NULL },
222     { "NDIS2SUP", 0x0496, NULL },
223     { "MSODISUP", 0x0497, NULL },
224     { "Splitter", 0x0498, NULL },
225     { "PPP",      0x0499, NULL },
226     { "VDHCP",    0x049A, NULL },
227     { "VNBT",     0x049B, NULL },
228     { "LOGGER",   0x049D, NULL },
229     { "EFILTER",  0x049E, NULL },
230     { "FFILTER",  0x049F, NULL },
231     { "TFILTER",  0x04A0, NULL },
232     { "AFILTER",  0x04A1, NULL },
233     { "IRLAMP",   0x04A2, NULL },
234
235     { "PCCARD",   0x097C, DeviceIo_PCCARD },
236     { "HASP95",   0x3721, DeviceIo_HASP },
237
238     /* WINE additions, ids unknown */
239     { "MONODEBG.VXD", 0x4242, DeviceIo_MONODEBG },
240
241     { NULL,       0,      NULL }
242 };
243
244 HANDLE DEVICE_Open( LPCWSTR filenameW, DWORD access, LPSECURITY_ATTRIBUTES sa )
245 {
246     const struct VxDInfo *info;
247     char filename[MAX_PATH];
248
249     if (!WideCharToMultiByte(CP_ACP, 0, filenameW, -1, filename, MAX_PATH, NULL, NULL))
250     {
251         SetLastError( ERROR_FILE_NOT_FOUND );
252         return 0;
253     }
254
255     for (info = VxDList; info->name; info++)
256         if (!strncasecmp( info->name, filename, strlen(info->name) ))
257             return FILE_CreateDevice( info->id | 0x10000, access, sa );
258
259     FIXME( "Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.\n",
260            filename);
261     SetLastError( ERROR_FILE_NOT_FOUND );
262     return 0;
263 }
264
265 static DWORD DEVICE_GetClientID( HANDLE handle )
266 {
267     DWORD       ret = 0;
268     SERVER_START_REQ( get_device_id )
269     {
270         req->handle = handle;
271         if (!wine_server_call( req )) ret = reply->id;
272     }
273     SERVER_END_REQ;
274     return ret;
275 }
276
277 static const struct VxDInfo *DEVICE_GetInfo( DWORD clientID )
278 {
279     const struct VxDInfo *info = NULL;
280
281     if (clientID & 0x10000)
282     {
283         for (info = VxDList; info->name; info++)
284             if (info->id == LOWORD(clientID)) break;
285     }
286     return info;
287 }
288
289 /****************************************************************************
290  *              DeviceIoControl (KERNEL32.@)
291  * This is one of those big ugly nasty procedure which can do
292  * a million and one things when it comes to devices. It can also be
293  * used for VxD communication.
294  *
295  * A return value of FALSE indicates that something has gone wrong which
296  * GetLastError can decipher.
297  */
298 BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
299                               LPVOID lpvInBuffer, DWORD cbInBuffer,
300                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
301                               LPDWORD lpcbBytesReturned,
302                               LPOVERLAPPED lpOverlapped)
303 {
304         DWORD clientID;
305
306         TRACE( "(%p,%ld,%p,%ld,%p,%ld,%p,%p)\n",
307                hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
308                lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped  );
309
310         if (!(clientID = DEVICE_GetClientID( hDevice )))
311         {
312                 SetLastError( ERROR_INVALID_PARAMETER );
313                 return FALSE;
314         }
315
316         /* Check if this is a user defined control code for a VxD */
317         if( HIWORD( dwIoControlCode ) == 0 )
318         {
319                 const struct VxDInfo *info;
320                 if (!(info = DEVICE_GetInfo( clientID )))
321                 {
322                         FIXME( "No device found for id %lx\n", clientID);
323                 }
324                 else if ( info->deviceio )
325                 {
326                         return info->deviceio( dwIoControlCode,
327                                         lpvInBuffer, cbInBuffer,
328                                         lpvOutBuffer, cbOutBuffer,
329                                         lpcbBytesReturned, lpOverlapped );
330                 }
331                 else
332                 {
333                         FIXME( "Unimplemented control %ld for VxD device %s\n",
334                                dwIoControlCode, info->name ? info->name : "???" );
335                         /* FIXME: this is for invalid calls on W98SE,
336                          * but maybe we should use ERROR_CALL_NOT_IMPLEMENTED
337                          * instead ? */
338                         SetLastError( ERROR_INVALID_FUNCTION );
339                 }
340         }
341         else
342         {       
343             NTSTATUS            status;
344
345             if (lpOverlapped)
346             {
347                 status = NtDeviceIoControlFile(hDevice, lpOverlapped->hEvent, 
348                                                NULL, NULL, 
349                                                (PIO_STATUS_BLOCK)lpOverlapped,
350                                                dwIoControlCode, 
351                                                lpvInBuffer, cbInBuffer,
352                                                lpvOutBuffer, cbOutBuffer);
353                 if (status) SetLastError(RtlNtStatusToDosError(status));
354                 if (lpcbBytesReturned) *lpcbBytesReturned = lpOverlapped->InternalHigh;
355                 return !status;
356             }
357             else
358             {
359                 IO_STATUS_BLOCK     iosb;
360
361                 status = NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, &iosb,
362                                                dwIoControlCode, 
363                                                lpvInBuffer, cbInBuffer,
364                                                lpvOutBuffer, cbOutBuffer);
365                 if (status) SetLastError(RtlNtStatusToDosError(status));
366                 if (lpcbBytesReturned) *lpcbBytesReturned = iosb.Information;
367                 return !status;
368             }
369         }
370         return FALSE;
371 }
372
373 /***********************************************************************
374  *           DeviceIo_VTDAPI
375  */
376 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
377                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
378                               LPDWORD lpcbBytesReturned,
379                               LPOVERLAPPED lpOverlapped)
380 {
381     BOOL retv = TRUE;
382
383     switch (dwIoControlCode)
384     {
385     case 5:
386         if (lpvOutBuffer && (cbOutBuffer>=4))
387             *(DWORD*)lpvOutBuffer = GetTickCount();
388
389         if (lpcbBytesReturned)
390             *lpcbBytesReturned = 4;
391
392         break;
393
394     default:
395         FIXME( "Control %ld not implemented\n", dwIoControlCode);
396         retv = FALSE;
397         break;
398     }
399
400     return retv;
401 }
402
403 /***********************************************************************
404  *           DeviceIo_IFSMgr
405  * NOTES
406  *   These ioctls are used by 'MSNET32.DLL'.
407  *
408  *   I have been unable to uncover any documentation about the ioctls so
409  *   the implementation of the cases IFS_IOCTL_21 and IFS_IOCTL_2F are
410  *   based on reasonable guesses on information found in the Windows 95 DDK.
411  *
412  */
413
414 /*
415  * IFSMgr DeviceIO service
416  */
417
418 #define IFS_IOCTL_21                100
419 #define IFS_IOCTL_2F                101
420 #define IFS_IOCTL_GET_RES           102
421 #define IFS_IOCTL_GET_NETPRO_NAME_A 103
422
423 struct win32apireq {
424         unsigned long   ar_proid;
425         unsigned long   ar_eax;
426         unsigned long   ar_ebx;
427         unsigned long   ar_ecx;
428         unsigned long   ar_edx;
429         unsigned long   ar_esi;
430         unsigned long   ar_edi;
431         unsigned long   ar_ebp;
432         unsigned short  ar_error;
433         unsigned short  ar_pad;
434 };
435
436 static void win32apieq_2_CONTEXT(struct win32apireq *pIn,CONTEXT86 *pCxt)
437 {
438         memset(pCxt,0,sizeof(*pCxt));
439
440         pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
441         pCxt->Eax = pIn->ar_eax;
442         pCxt->Ebx = pIn->ar_ebx;
443         pCxt->Ecx = pIn->ar_ecx;
444         pCxt->Edx = pIn->ar_edx;
445         pCxt->Esi = pIn->ar_esi;
446         pCxt->Edi = pIn->ar_edi;
447
448         /* FIXME: Only partial CONTEXT86_CONTROL */
449         pCxt->Ebp = pIn->ar_ebp;
450
451         /* FIXME: pIn->ar_proid ignored */
452         /* FIXME: pIn->ar_error ignored */
453         /* FIXME: pIn->ar_pad ignored */
454 }
455
456 static void CONTEXT_2_win32apieq(CONTEXT86 *pCxt,struct win32apireq *pOut)
457 {
458         memset(pOut,0,sizeof(struct win32apireq));
459
460         pOut->ar_eax = pCxt->Eax;
461         pOut->ar_ebx = pCxt->Ebx;
462         pOut->ar_ecx = pCxt->Ecx;
463         pOut->ar_edx = pCxt->Edx;
464         pOut->ar_esi = pCxt->Esi;
465         pOut->ar_edi = pCxt->Edi;
466
467         /* FIXME: Only partial CONTEXT86_CONTROL */
468         pOut->ar_ebp = pCxt->Ebp;
469
470         /* FIXME: pOut->ar_proid ignored */
471         /* FIXME: pOut->ar_error ignored */
472         /* FIXME: pOut->ar_pad ignored */
473 }
474
475 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
476                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
477                               LPDWORD lpcbBytesReturned,
478                               LPOVERLAPPED lpOverlapped)
479 {
480     BOOL retv = TRUE;
481         TRACE("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
482                         dwIoControlCode,
483                         lpvInBuffer,cbInBuffer,
484                         lpvOutBuffer,cbOutBuffer,
485                         lpcbBytesReturned,
486                         lpOverlapped);
487
488     switch (dwIoControlCode)
489     {
490         case IFS_IOCTL_21:
491         case IFS_IOCTL_2F:{
492                 CONTEXT86 cxt;
493                 struct win32apireq *pIn=(struct win32apireq *) lpvInBuffer;
494                 struct win32apireq *pOut=(struct win32apireq *) lpvOutBuffer;
495
496                 TRACE(
497                         "Control '%s': "
498                         "proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
499                         "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx, ebp=0x%08lx, "
500                         "error=0x%04x, pad=0x%04x\n",
501                         (dwIoControlCode==IFS_IOCTL_21)?"IFS_IOCTL_21":"IFS_IOCTL_2F",
502                         pIn->ar_proid, pIn->ar_eax, pIn->ar_ebx, pIn->ar_ecx,
503                         pIn->ar_edx, pIn->ar_esi, pIn->ar_edi, pIn->ar_ebp,
504                         pIn->ar_error, pIn->ar_pad
505                 );
506
507                 win32apieq_2_CONTEXT(pIn,&cxt);
508
509                 if(dwIoControlCode==IFS_IOCTL_21)
510                     INSTR_CallBuiltinHandler( &cxt, 0x21 );
511                 else
512                     INSTR_CallBuiltinHandler( &cxt, 0x2f );
513
514                 CONTEXT_2_win32apieq(&cxt,pOut);
515
516         retv = TRUE;
517         } break;
518         case IFS_IOCTL_GET_RES:{
519         FIXME( "Control 'IFS_IOCTL_GET_RES' not implemented\n");
520         retv = FALSE;
521         } break;
522         case IFS_IOCTL_GET_NETPRO_NAME_A:{
523         FIXME( "Control 'IFS_IOCTL_GET_NETPRO_NAME_A' not implemented\n");
524         retv = FALSE;
525         } break;
526     default:
527         FIXME( "Control %ld not implemented\n", dwIoControlCode);
528         retv = FALSE;
529     }
530
531     return retv;
532 }
533
534 /***********************************************************************
535  *           DeviceIo_VCD
536  */
537 static BOOL DeviceIo_VCD(DWORD dwIoControlCode,
538                               LPVOID lpvInBuffer, DWORD cbInBuffer,
539                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
540                               LPDWORD lpcbBytesReturned,
541                               LPOVERLAPPED lpOverlapped)
542 {
543     BOOL retv = TRUE;
544
545     switch (dwIoControlCode)
546     {
547     case IOCTL_SERIAL_LSRMST_INSERT:
548     {
549         FIXME( "IOCTL_SERIAL_LSRMST_INSERT NIY !\n");
550         retv = FALSE;
551     }
552     break;
553
554     default:
555         FIXME( "Unknown Control %ld\n", dwIoControlCode);
556         retv = FALSE;
557         break;
558     }
559
560     return retv;
561 }
562
563
564 /***********************************************************************
565  *           DeviceIo_VWin32
566  */
567
568 static void DIOCRegs_2_CONTEXT( DIOC_REGISTERS *pIn, CONTEXT86 *pCxt )
569 {
570     memset( pCxt, 0, sizeof(*pCxt) );
571     /* Note: segment registers == 0 means that CTX_SEG_OFF_TO_LIN
572              will interpret 32-bit register contents as linear pointers */
573
574     pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
575     pCxt->Eax = pIn->reg_EAX;
576     pCxt->Ebx = pIn->reg_EBX;
577     pCxt->Ecx = pIn->reg_ECX;
578     pCxt->Edx = pIn->reg_EDX;
579     pCxt->Esi = pIn->reg_ESI;
580     pCxt->Edi = pIn->reg_EDI;
581
582     /* FIXME: Only partial CONTEXT86_CONTROL */
583     pCxt->EFlags = pIn->reg_Flags;
584 }
585
586 static void CONTEXT_2_DIOCRegs( CONTEXT86 *pCxt, DIOC_REGISTERS *pOut )
587 {
588     memset( pOut, 0, sizeof(DIOC_REGISTERS) );
589
590     pOut->reg_EAX = pCxt->Eax;
591     pOut->reg_EBX = pCxt->Ebx;
592     pOut->reg_ECX = pCxt->Ecx;
593     pOut->reg_EDX = pCxt->Edx;
594     pOut->reg_ESI = pCxt->Esi;
595     pOut->reg_EDI = pCxt->Edi;
596
597     /* FIXME: Only partial CONTEXT86_CONTROL */
598     pOut->reg_Flags = pCxt->EFlags;
599 }
600
601 #define DIOC_AH(regs) (((unsigned char*)&((regs)->reg_EAX))[1])
602 #define DIOC_AL(regs) (((unsigned char*)&((regs)->reg_EAX))[0])
603 #define DIOC_BH(regs) (((unsigned char*)&((regs)->reg_EBX))[1])
604 #define DIOC_BL(regs) (((unsigned char*)&((regs)->reg_EBX))[0])
605 #define DIOC_DH(regs) (((unsigned char*)&((regs)->reg_EDX))[1])
606 #define DIOC_DL(regs) (((unsigned char*)&((regs)->reg_EDX))[0])
607
608 #define DIOC_AX(regs) (((unsigned short*)&((regs)->reg_EAX))[0])
609 #define DIOC_BX(regs) (((unsigned short*)&((regs)->reg_EBX))[0])
610 #define DIOC_CX(regs) (((unsigned short*)&((regs)->reg_ECX))[0])
611 #define DIOC_DX(regs) (((unsigned short*)&((regs)->reg_EDX))[0])
612
613 #define DIOC_SET_CARRY(regs) (((regs)->reg_Flags)|=0x00000001)
614
615 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode,
616                               LPVOID lpvInBuffer, DWORD cbInBuffer,
617                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
618                               LPDWORD lpcbBytesReturned,
619                               LPOVERLAPPED lpOverlapped)
620 {
621     BOOL retv = TRUE;
622
623     switch (dwIoControlCode)
624     {
625     case VWIN32_DIOC_DOS_IOCTL:
626     case 0x10: /* Int 0x21 call, call it VWIN_DIOC_INT21 ? */
627     case VWIN32_DIOC_DOS_INT13:
628     case VWIN32_DIOC_DOS_INT25:
629     case VWIN32_DIOC_DOS_INT26:
630     case 0x29: /* Int 0x31 call, call it VWIN_DIOC_INT31 ? */
631     case VWIN32_DIOC_DOS_DRIVEINFO:
632     {
633         CONTEXT86 cxt;
634         DIOC_REGISTERS *pIn  = (DIOC_REGISTERS *)lpvInBuffer;
635         DIOC_REGISTERS *pOut = (DIOC_REGISTERS *)lpvOutBuffer;
636         BYTE intnum = 0;
637
638         TRACE( "Control '%s': "
639                "eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
640                "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx \n",
641                (dwIoControlCode == VWIN32_DIOC_DOS_IOCTL)? "VWIN32_DIOC_DOS_IOCTL" :
642                (dwIoControlCode == VWIN32_DIOC_DOS_INT25)? "VWIN32_DIOC_DOS_INT25" :
643                (dwIoControlCode == VWIN32_DIOC_DOS_INT26)? "VWIN32_DIOC_DOS_INT26" :
644                (dwIoControlCode == VWIN32_DIOC_DOS_DRIVEINFO)? "VWIN32_DIOC_DOS_DRIVEINFO" :  "???",
645                pIn->reg_EAX, pIn->reg_EBX, pIn->reg_ECX,
646                pIn->reg_EDX, pIn->reg_ESI, pIn->reg_EDI );
647
648         DIOCRegs_2_CONTEXT( pIn, &cxt );
649
650         switch (dwIoControlCode)
651         {
652         case VWIN32_DIOC_DOS_IOCTL: /* Call int 21h */
653         case 0x10: /* Int 0x21 call, call it VWIN_DIOC_INT21 ? */
654         case VWIN32_DIOC_DOS_DRIVEINFO:        /* Call int 21h 730x */
655             intnum = 0x21;
656             break;
657         case VWIN32_DIOC_DOS_INT13:
658             intnum = 0x13;
659             break;
660         case VWIN32_DIOC_DOS_INT25: 
661             intnum = 0x25;
662             break;
663         case VWIN32_DIOC_DOS_INT26:
664             intnum = 0x26;
665             break;
666         case 0x29: /* Int 0x31 call, call it VWIN_DIOC_INT31 ? */
667             intnum = 0x31;
668             break;
669         }
670
671         INSTR_CallBuiltinHandler( &cxt, intnum );
672         CONTEXT_2_DIOCRegs( &cxt, pOut );
673     }
674     break;
675
676     case VWIN32_DIOC_SIMCTRLC:
677         FIXME( "Control VWIN32_DIOC_SIMCTRLC not implemented\n");
678         retv = FALSE;
679         break;
680
681     default:
682         FIXME( "Unknown Control %ld\n", dwIoControlCode);
683         retv = FALSE;
684         break;
685     }
686
687     return retv;
688 }
689
690 /* this is the main multimedia device loader */
691 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode,
692                               LPVOID lpvInBuffer, DWORD cbInBuffer,
693                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
694                               LPDWORD lpcbBytesReturned,
695                               LPOVERLAPPED lpOverlapped)
696 {
697         FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
698             dwIoControlCode,
699             lpvInBuffer,cbInBuffer,
700             lpvOutBuffer,cbOutBuffer,
701             lpcbBytesReturned,
702             lpOverlapped
703         );
704         switch (dwIoControlCode) {
705         case 5:
706                 /* Hmm. */
707                 *(DWORD*)lpvOutBuffer=0;
708                 *lpcbBytesReturned=4;
709                 return TRUE;
710         }
711         return FALSE;
712 }
713 /* this is used by some Origin games */
714 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode,
715                               LPVOID lpvInBuffer, DWORD cbInBuffer,
716                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
717                               LPDWORD lpcbBytesReturned,
718                               LPOVERLAPPED lpOverlapped)
719 {
720         switch (dwIoControlCode) {
721         case 1: /* version */
722                 *(LPDWORD)lpvOutBuffer = 0x20004; /* WC SecretOps */
723                 break;
724         case 9: /* debug output */
725                 ERR("MONODEBG: %s\n",debugstr_a(lpvInBuffer));
726                 break;
727         default:
728                 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
729                         dwIoControlCode,
730                         lpvInBuffer,cbInBuffer,
731                         lpvOutBuffer,cbOutBuffer,
732                         lpcbBytesReturned,
733                         lpOverlapped
734                 );
735                 break;
736         }
737         return TRUE;
738 }
739 /* pccard */
740 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode,
741                               LPVOID lpvInBuffer, DWORD cbInBuffer,
742                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
743                               LPDWORD lpcbBytesReturned,
744                               LPOVERLAPPED lpOverlapped)
745 {
746         switch (dwIoControlCode) {
747         case 0x0000: /* PCCARD_Get_Version */
748         case 0x0001: /* PCCARD_Card_Services */
749         default:
750                 FIXME( "(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
751                         dwIoControlCode,
752                         lpvInBuffer,cbInBuffer,
753                         lpvOutBuffer,cbOutBuffer,
754                         lpcbBytesReturned,
755                         lpOverlapped
756                 );
757                 break;
758         }
759         return FALSE;
760 }
761
762 static BOOL DeviceIo_HASP(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
763                               LPVOID lpvOutBuffer, DWORD cbOutBuffer,
764                               LPDWORD lpcbBytesReturned,
765                               LPOVERLAPPED lpOverlapped)
766 {
767     BOOL retv = TRUE;
768         FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
769                         dwIoControlCode,
770                         lpvInBuffer,cbInBuffer,
771                         lpvOutBuffer,cbOutBuffer,
772                         lpcbBytesReturned,
773                         lpOverlapped);
774
775     return retv;
776 }