2 * Win32 device functions
4 * Copyright 1998 Marcus Meissner
5 * Copyright 1998 Ulrich Weigand
6 * Copyright 1998 Patrik Stridvall
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.
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.
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
24 #include "wine/port.h"
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_SOCKET_H
32 # include <sys/socket.h>
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
37 #ifdef HAVE_ARPA_INET_H
38 # include <arpa/inet.h>
54 #include "kernel_private.h"
55 #include "wine/server.h"
56 #include "wine/debug.h"
58 WINE_DEFAULT_DEBUG_CHANNEL(file);
61 #define INADDR_NONE ~0UL
64 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode,
65 LPVOID lpvInBuffer, DWORD cbInBuffer,
66 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
67 LPDWORD lpcbBytesReturned,
68 LPOVERLAPPED lpOverlapped);
69 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode,
70 LPVOID lpvInBuffer, DWORD cbInBuffer,
71 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
72 LPDWORD lpcbBytesReturned,
73 LPOVERLAPPED lpOverlapped);
74 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode,
75 LPVOID lpvInBuffer, DWORD cbInBuffer,
76 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
77 LPDWORD lpcbBytesReturned,
78 LPOVERLAPPED lpOverlapped);
80 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode,
81 LPVOID lpvInBuffer, DWORD cbInBuffer,
82 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
83 LPDWORD lpcbBytesReturned,
84 LPOVERLAPPED lpOverlapped);
86 static BOOL DeviceIo_VCD(DWORD dwIoControlCode,
87 LPVOID lpvInBuffer, DWORD cbInBuffer,
88 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
89 LPDWORD lpcbBytesReturned,
90 LPOVERLAPPED lpOverlapped);
92 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode,
93 LPVOID lpvInBuffer, DWORD cbInBuffer,
94 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
95 LPDWORD lpcbBytesReturned,
96 LPOVERLAPPED lpOverlapped);
98 static BOOL DeviceIo_DHCP(DWORD dwIoControlCode,
99 LPVOID lpvInBuffer, DWORD cbInBuffer,
100 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
101 LPDWORD lpcbBytesReturned,
102 LPOVERLAPPED lpOverlapped);
104 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode,
105 LPVOID lpvInBuffer, DWORD cbInBuffer,
106 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
107 LPDWORD lpcbBytesReturned,
108 LPOVERLAPPED lpOverlapped);
110 static BOOL DeviceIo_HASP (DWORD dwIoControlCode,
111 LPVOID lpvInBuffer, DWORD cbInBuffer,
112 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
113 LPDWORD lpcbBytesReturned,
114 LPOVERLAPPED lpOverlapped);
116 static BOOL DeviceIo_NetBIOS(DWORD dwIoControlCode,
117 LPVOID lpvInBuffer, DWORD cbInBuffer,
118 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
119 LPDWORD lpcbBytesReturned,
120 LPOVERLAPPED lpOverlapped);
122 static BOOL DeviceIo_VNB(DWORD dwIoControlCode,
123 LPVOID lpvInBuffer, DWORD cbInBuffer,
124 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
125 LPDWORD lpcbBytesReturned,
126 LPOVERLAPPED lpOverlapped);
129 * VxD names are taken from the Win95 DDK
136 BOOL (*deviceio)(DWORD, LPVOID, DWORD,
137 LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
140 static const struct VxDInfo VxDList[] =
142 /* Standard VxD IDs */
143 { "VMM", 0x0001, NULL },
144 { "DEBUG", 0x0002, NULL },
145 { "VPICD", 0x0003, NULL },
146 { "VDMAD", 0x0004, NULL },
147 { "VTD", 0x0005, NULL },
148 { "V86MMGR", 0x0006, NULL },
149 { "PAGESWAP", 0x0007, NULL },
150 { "PARITY", 0x0008, NULL },
151 { "REBOOT", 0x0009, NULL },
152 { "VDD", 0x000A, NULL },
153 { "VSD", 0x000B, NULL },
154 { "VMD", 0x000C, NULL },
155 { "VKD", 0x000D, NULL },
156 { "VCD", 0x000E, DeviceIo_VCD },
157 { "VPD", 0x000F, NULL },
158 { "BLOCKDEV", 0x0010, NULL },
159 { "VMCPD", 0x0011, NULL },
160 { "EBIOS", 0x0012, NULL },
161 { "BIOSXLAT", 0x0013, NULL },
162 { "VNETBIOS", 0x0014, DeviceIo_NetBIOS },
163 { "DOSMGR", 0x0015, NULL },
164 { "WINLOAD", 0x0016, NULL },
165 { "SHELL", 0x0017, NULL },
166 { "VMPOLL", 0x0018, NULL },
167 { "VPROD", 0x0019, NULL },
168 { "DOSNET", 0x001A, NULL },
169 { "VFD", 0x001B, NULL },
170 { "VDD2", 0x001C, NULL },
171 { "WINDEBUG", 0x001D, NULL },
172 { "TSRLOAD", 0x001E, NULL },
173 { "BIOSHOOK", 0x001F, NULL },
174 { "INT13", 0x0020, NULL },
175 { "PAGEFILE", 0x0021, NULL },
176 { "SCSI", 0x0022, NULL },
177 { "MCA_POS", 0x0023, NULL },
178 { "SCSIFD", 0x0024, NULL },
179 { "VPEND", 0x0025, NULL },
180 { "VPOWERD", 0x0026, NULL },
181 { "VXDLDR", 0x0027, NULL },
182 { "NDIS", 0x0028, NULL },
183 { "BIOS_EXT", 0x0029, NULL },
184 { "VWIN32", 0x002A, DeviceIo_VWin32 },
185 { "VCOMM", 0x002B, NULL },
186 { "SPOOLER", 0x002C, NULL },
187 { "WIN32S", 0x002D, NULL },
188 { "DEBUGCMD", 0x002E, NULL },
190 { "VNB", 0x0031, DeviceIo_VNB },
191 { "SERVER", 0x0032, NULL },
192 { "CONFIGMG", 0x0033, NULL },
193 { "DWCFGMG", 0x0034, NULL },
194 { "SCSIPORT", 0x0035, NULL },
195 { "VFBACKUP", 0x0036, NULL },
196 { "ENABLE", 0x0037, NULL },
197 { "VCOND", 0x0038, NULL },
199 { "EFAX", 0x003A, NULL },
200 { "DSVXD", 0x003B, NULL },
201 { "ISAPNP", 0x003C, NULL },
202 { "BIOS", 0x003D, NULL },
203 { "WINSOCK", 0x003E, NULL },
204 { "WSOCK", 0x003E, NULL },
205 { "WSIPX", 0x003F, NULL },
206 { "IFSMgr", 0x0040, DeviceIo_IFSMgr },
207 { "VCDFSD", 0x0041, NULL },
208 { "MRCI2", 0x0042, NULL },
209 { "PCI", 0x0043, NULL },
210 { "PELOADER", 0x0044, NULL },
211 { "EISA", 0x0045, NULL },
212 { "DRAGCLI", 0x0046, NULL },
213 { "DRAGSRV", 0x0047, NULL },
214 { "PERF", 0x0048, NULL },
215 { "AWREDIR", 0x0049, NULL },
217 /* Far East support */
218 { "ETEN", 0x0060, NULL },
219 { "CHBIOS", 0x0061, NULL },
220 { "VMSGD", 0x0062, NULL },
221 { "VPPID", 0x0063, NULL },
222 { "VIME", 0x0064, NULL },
223 { "VHBIOSD", 0x0065, NULL },
225 /* Multimedia OEM IDs */
226 { "VTDAPI", 0x0442, DeviceIo_VTDAPI },
227 { "MMDEVLDR", 0x044A, DeviceIo_MMDEVLDR },
229 /* Network Device IDs */
230 { "VNetSup", 0x0480, NULL },
231 { "VRedir", 0x0481, NULL },
232 { "VBrowse", 0x0482, NULL },
233 { "VSHARE", 0x0483, NULL },
234 { "IFSMgr", 0x0484, NULL },
235 { "MEMPROBE", 0x0485, NULL },
236 { "VFAT", 0x0486, NULL },
237 { "NWLINK", 0x0487, NULL },
238 { "VNWLINK", 0x0487, NULL },
239 { "NWSUP", 0x0487, NULL },
240 { "VTDI", 0x0488, NULL },
241 { "VIP", 0x0489, NULL },
242 { "VTCP", 0x048A, NULL },
243 { "VCache", 0x048B, NULL },
244 { "VUDP", 0x048C, NULL },
245 { "VAsync", 0x048D, NULL },
246 { "NWREDIR", 0x048E, NULL },
247 { "STAT80", 0x048F, NULL },
248 { "SCSIPORT", 0x0490, NULL },
249 { "FILESEC", 0x0491, NULL },
250 { "NWSERVER", 0x0492, NULL },
251 { "SECPROV", 0x0493, NULL },
252 { "NSCL", 0x0494, NULL },
253 { "WSTCP", 0x0495, NULL },
254 { "NDIS2SUP", 0x0496, NULL },
255 { "MSODISUP", 0x0497, NULL },
256 { "Splitter", 0x0498, NULL },
257 { "PPP", 0x0499, NULL },
258 { "VDHCP", 0x049A, DeviceIo_DHCP },
259 { "VNBT", 0x049B, NULL },
260 { "LOGGER", 0x049D, NULL },
261 { "EFILTER", 0x049E, NULL },
262 { "FFILTER", 0x049F, NULL },
263 { "TFILTER", 0x04A0, NULL },
264 { "AFILTER", 0x04A1, NULL },
265 { "IRLAMP", 0x04A2, NULL },
267 { "PCCARD", 0x097C, DeviceIo_PCCARD },
268 { "HASP95", 0x3721, DeviceIo_HASP },
270 /* WINE additions, ids unknown */
271 { "MONODEBG.VXD", 0x4242, DeviceIo_MONODEBG },
276 HANDLE DEVICE_Open( LPCWSTR filenameW, DWORD access, LPSECURITY_ATTRIBUTES sa )
278 const struct VxDInfo *info;
279 char filename[MAX_PATH];
281 if (!WideCharToMultiByte(CP_ACP, 0, filenameW, -1, filename, MAX_PATH, NULL, NULL))
283 SetLastError( ERROR_FILE_NOT_FOUND );
287 for (info = VxDList; info->name; info++)
288 if (!strncasecmp( info->name, filename, strlen(info->name) ))
289 return FILE_CreateDevice( info->id | 0x10000, access, sa );
291 FIXME( "Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.\n",
294 SetLastError( ERROR_FILE_NOT_FOUND );
298 static DWORD DEVICE_GetClientID( HANDLE handle )
301 SERVER_START_REQ( get_device_id )
303 req->handle = handle;
304 if (!wine_server_call( req )) ret = reply->id;
310 static const struct VxDInfo *DEVICE_GetInfo( DWORD clientID )
312 const struct VxDInfo *info = NULL;
314 if (clientID & 0x10000)
316 for (info = VxDList; info->name; info++)
317 if (info->id == LOWORD(clientID)) break;
322 /****************************************************************************
323 * DeviceIoControl (KERNEL32.@)
324 * This is one of those big ugly nasty procedure which can do
325 * a million and one things when it comes to devices. It can also be
326 * used for VxD communication.
328 * A return value of FALSE indicates that something has gone wrong which
329 * GetLastError can decipher.
331 BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
332 LPVOID lpvInBuffer, DWORD cbInBuffer,
333 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
334 LPDWORD lpcbBytesReturned,
335 LPOVERLAPPED lpOverlapped)
339 TRACE( "(%p,%ld,%p,%ld,%p,%ld,%p,%p)\n",
340 hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
341 lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped );
343 if (!(clientID = DEVICE_GetClientID( hDevice )))
345 SetLastError( ERROR_INVALID_PARAMETER );
349 /* Check if this is a user defined control code for a VxD */
350 if( HIWORD( dwIoControlCode ) == 0 )
352 const struct VxDInfo *info;
353 if (!(info = DEVICE_GetInfo( clientID )))
355 FIXME( "No device found for id %lx\n", clientID);
357 else if ( info->deviceio )
359 return info->deviceio( dwIoControlCode,
360 lpvInBuffer, cbInBuffer,
361 lpvOutBuffer, cbOutBuffer,
362 lpcbBytesReturned, lpOverlapped );
366 FIXME( "Unimplemented control %ld for VxD device %s\n",
367 dwIoControlCode, info->name ? info->name : "???" );
368 /* FIXME: this is for invalid calls on W98SE,
369 * but maybe we should use ERROR_CALL_NOT_IMPLEMENTED
371 SetLastError( ERROR_INVALID_FUNCTION );
380 status = NtDeviceIoControlFile(hDevice, lpOverlapped->hEvent,
382 (PIO_STATUS_BLOCK)lpOverlapped,
384 lpvInBuffer, cbInBuffer,
385 lpvOutBuffer, cbOutBuffer);
386 if (status) SetLastError(RtlNtStatusToDosError(status));
387 if (lpcbBytesReturned) *lpcbBytesReturned = lpOverlapped->InternalHigh;
392 IO_STATUS_BLOCK iosb;
394 status = NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, &iosb,
396 lpvInBuffer, cbInBuffer,
397 lpvOutBuffer, cbOutBuffer);
398 if (status) SetLastError(RtlNtStatusToDosError(status));
399 if (lpcbBytesReturned) *lpcbBytesReturned = iosb.Information;
406 /***********************************************************************
409 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
410 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
411 LPDWORD lpcbBytesReturned,
412 LPOVERLAPPED lpOverlapped)
416 switch (dwIoControlCode)
419 if (lpvOutBuffer && (cbOutBuffer>=4))
420 *(DWORD*)lpvOutBuffer = GetTickCount();
422 if (lpcbBytesReturned)
423 *lpcbBytesReturned = 4;
428 FIXME( "Control %ld not implemented\n", dwIoControlCode);
436 /***********************************************************************
439 * These ioctls are used by 'MSNET32.DLL'.
441 * I have been unable to uncover any documentation about the ioctls so
442 * the implementation of the cases IFS_IOCTL_21 and IFS_IOCTL_2F are
443 * based on reasonable guesses on information found in the Windows 95 DDK.
448 * IFSMgr DeviceIO service
451 #define IFS_IOCTL_21 100
452 #define IFS_IOCTL_2F 101
453 #define IFS_IOCTL_GET_RES 102
454 #define IFS_IOCTL_GET_NETPRO_NAME_A 103
457 unsigned long ar_proid;
458 unsigned long ar_eax;
459 unsigned long ar_ebx;
460 unsigned long ar_ecx;
461 unsigned long ar_edx;
462 unsigned long ar_esi;
463 unsigned long ar_edi;
464 unsigned long ar_ebp;
465 unsigned short ar_error;
466 unsigned short ar_pad;
469 static void win32apieq_2_CONTEXT(struct win32apireq *pIn,CONTEXT86 *pCxt)
471 memset(pCxt,0,sizeof(*pCxt));
473 pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
474 pCxt->Eax = pIn->ar_eax;
475 pCxt->Ebx = pIn->ar_ebx;
476 pCxt->Ecx = pIn->ar_ecx;
477 pCxt->Edx = pIn->ar_edx;
478 pCxt->Esi = pIn->ar_esi;
479 pCxt->Edi = pIn->ar_edi;
481 /* FIXME: Only partial CONTEXT86_CONTROL */
482 pCxt->Ebp = pIn->ar_ebp;
484 /* FIXME: pIn->ar_proid ignored */
485 /* FIXME: pIn->ar_error ignored */
486 /* FIXME: pIn->ar_pad ignored */
489 static void CONTEXT_2_win32apieq(CONTEXT86 *pCxt,struct win32apireq *pOut)
491 memset(pOut,0,sizeof(struct win32apireq));
493 pOut->ar_eax = pCxt->Eax;
494 pOut->ar_ebx = pCxt->Ebx;
495 pOut->ar_ecx = pCxt->Ecx;
496 pOut->ar_edx = pCxt->Edx;
497 pOut->ar_esi = pCxt->Esi;
498 pOut->ar_edi = pCxt->Edi;
500 /* FIXME: Only partial CONTEXT86_CONTROL */
501 pOut->ar_ebp = pCxt->Ebp;
503 /* FIXME: pOut->ar_proid ignored */
504 /* FIXME: pOut->ar_error ignored */
505 /* FIXME: pOut->ar_pad ignored */
508 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
509 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
510 LPDWORD lpcbBytesReturned,
511 LPOVERLAPPED lpOverlapped)
514 TRACE("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
516 lpvInBuffer,cbInBuffer,
517 lpvOutBuffer,cbOutBuffer,
521 switch (dwIoControlCode)
526 struct win32apireq *pIn=(struct win32apireq *) lpvInBuffer;
527 struct win32apireq *pOut=(struct win32apireq *) lpvOutBuffer;
531 "proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
532 "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx, ebp=0x%08lx, "
533 "error=0x%04x, pad=0x%04x\n",
534 (dwIoControlCode==IFS_IOCTL_21)?"IFS_IOCTL_21":"IFS_IOCTL_2F",
535 pIn->ar_proid, pIn->ar_eax, pIn->ar_ebx, pIn->ar_ecx,
536 pIn->ar_edx, pIn->ar_esi, pIn->ar_edi, pIn->ar_ebp,
537 pIn->ar_error, pIn->ar_pad
540 win32apieq_2_CONTEXT(pIn,&cxt);
542 if(dwIoControlCode==IFS_IOCTL_21)
543 INSTR_CallBuiltinHandler( &cxt, 0x21 );
545 INSTR_CallBuiltinHandler( &cxt, 0x2f );
547 CONTEXT_2_win32apieq(&cxt,pOut);
551 case IFS_IOCTL_GET_RES:{
552 FIXME( "Control 'IFS_IOCTL_GET_RES' not implemented\n");
555 case IFS_IOCTL_GET_NETPRO_NAME_A:{
556 FIXME( "Control 'IFS_IOCTL_GET_NETPRO_NAME_A' not implemented\n");
560 FIXME( "Control %ld not implemented\n", dwIoControlCode);
567 /***********************************************************************
570 static BOOL DeviceIo_VCD(DWORD dwIoControlCode,
571 LPVOID lpvInBuffer, DWORD cbInBuffer,
572 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
573 LPDWORD lpcbBytesReturned,
574 LPOVERLAPPED lpOverlapped)
578 switch (dwIoControlCode)
580 case IOCTL_SERIAL_LSRMST_INSERT:
582 FIXME( "IOCTL_SERIAL_LSRMST_INSERT NIY !\n");
588 FIXME( "Unknown Control %ld\n", dwIoControlCode);
597 /***********************************************************************
601 static void DIOCRegs_2_CONTEXT( DIOC_REGISTERS *pIn, CONTEXT86 *pCxt )
603 memset( pCxt, 0, sizeof(*pCxt) );
604 /* Note: segment registers == 0 means that CTX_SEG_OFF_TO_LIN
605 will interpret 32-bit register contents as linear pointers */
607 pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
608 pCxt->Eax = pIn->reg_EAX;
609 pCxt->Ebx = pIn->reg_EBX;
610 pCxt->Ecx = pIn->reg_ECX;
611 pCxt->Edx = pIn->reg_EDX;
612 pCxt->Esi = pIn->reg_ESI;
613 pCxt->Edi = pIn->reg_EDI;
615 /* FIXME: Only partial CONTEXT86_CONTROL */
617 pCxt->EFlags = pIn->reg_Flags & ~0x00020000; /* clear vm86 mode */
620 static void CONTEXT_2_DIOCRegs( CONTEXT86 *pCxt, DIOC_REGISTERS *pOut )
622 memset( pOut, 0, sizeof(DIOC_REGISTERS) );
624 pOut->reg_EAX = pCxt->Eax;
625 pOut->reg_EBX = pCxt->Ebx;
626 pOut->reg_ECX = pCxt->Ecx;
627 pOut->reg_EDX = pCxt->Edx;
628 pOut->reg_ESI = pCxt->Esi;
629 pOut->reg_EDI = pCxt->Edi;
631 /* FIXME: Only partial CONTEXT86_CONTROL */
632 pOut->reg_Flags = pCxt->EFlags;
635 #define DIOC_AH(regs) (((unsigned char*)&((regs)->reg_EAX))[1])
636 #define DIOC_AL(regs) (((unsigned char*)&((regs)->reg_EAX))[0])
637 #define DIOC_BH(regs) (((unsigned char*)&((regs)->reg_EBX))[1])
638 #define DIOC_BL(regs) (((unsigned char*)&((regs)->reg_EBX))[0])
639 #define DIOC_DH(regs) (((unsigned char*)&((regs)->reg_EDX))[1])
640 #define DIOC_DL(regs) (((unsigned char*)&((regs)->reg_EDX))[0])
642 #define DIOC_AX(regs) (((unsigned short*)&((regs)->reg_EAX))[0])
643 #define DIOC_BX(regs) (((unsigned short*)&((regs)->reg_EBX))[0])
644 #define DIOC_CX(regs) (((unsigned short*)&((regs)->reg_ECX))[0])
645 #define DIOC_DX(regs) (((unsigned short*)&((regs)->reg_EDX))[0])
647 #define DIOC_SET_CARRY(regs) (((regs)->reg_Flags)|=0x00000001)
649 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode,
650 LPVOID lpvInBuffer, DWORD cbInBuffer,
651 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
652 LPDWORD lpcbBytesReturned,
653 LPOVERLAPPED lpOverlapped)
657 switch (dwIoControlCode)
659 case VWIN32_DIOC_DOS_IOCTL:
660 case 0x10: /* Int 0x21 call, call it VWIN_DIOC_INT21 ? */
661 case VWIN32_DIOC_DOS_INT13:
662 case VWIN32_DIOC_DOS_INT25:
663 case VWIN32_DIOC_DOS_INT26:
664 case 0x29: /* Int 0x31 call, call it VWIN_DIOC_INT31 ? */
665 case VWIN32_DIOC_DOS_DRIVEINFO:
668 DIOC_REGISTERS *pIn = (DIOC_REGISTERS *)lpvInBuffer;
669 DIOC_REGISTERS *pOut = (DIOC_REGISTERS *)lpvOutBuffer;
672 TRACE( "Control '%s': "
673 "eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
674 "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx \n",
675 (dwIoControlCode == VWIN32_DIOC_DOS_IOCTL)? "VWIN32_DIOC_DOS_IOCTL" :
676 (dwIoControlCode == VWIN32_DIOC_DOS_INT25)? "VWIN32_DIOC_DOS_INT25" :
677 (dwIoControlCode == VWIN32_DIOC_DOS_INT26)? "VWIN32_DIOC_DOS_INT26" :
678 (dwIoControlCode == VWIN32_DIOC_DOS_DRIVEINFO)? "VWIN32_DIOC_DOS_DRIVEINFO" : "???",
679 pIn->reg_EAX, pIn->reg_EBX, pIn->reg_ECX,
680 pIn->reg_EDX, pIn->reg_ESI, pIn->reg_EDI );
682 DIOCRegs_2_CONTEXT( pIn, &cxt );
684 switch (dwIoControlCode)
686 case VWIN32_DIOC_DOS_IOCTL: /* Call int 21h */
687 case 0x10: /* Int 0x21 call, call it VWIN_DIOC_INT21 ? */
688 case VWIN32_DIOC_DOS_DRIVEINFO: /* Call int 21h 730x */
691 case VWIN32_DIOC_DOS_INT13:
694 case VWIN32_DIOC_DOS_INT25:
697 case VWIN32_DIOC_DOS_INT26:
700 case 0x29: /* Int 0x31 call, call it VWIN_DIOC_INT31 ? */
705 INSTR_CallBuiltinHandler( &cxt, intnum );
706 CONTEXT_2_DIOCRegs( &cxt, pOut );
710 case VWIN32_DIOC_SIMCTRLC:
711 FIXME( "Control VWIN32_DIOC_SIMCTRLC not implemented\n");
716 FIXME( "Unknown Control %ld\n", dwIoControlCode);
724 /* this is the main multimedia device loader */
725 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode,
726 LPVOID lpvInBuffer, DWORD cbInBuffer,
727 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
728 LPDWORD lpcbBytesReturned,
729 LPOVERLAPPED lpOverlapped)
731 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
733 lpvInBuffer,cbInBuffer,
734 lpvOutBuffer,cbOutBuffer,
738 switch (dwIoControlCode) {
741 *(DWORD*)lpvOutBuffer=0;
742 *lpcbBytesReturned=4;
747 /* this is used by some Origin games */
748 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode,
749 LPVOID lpvInBuffer, DWORD cbInBuffer,
750 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
751 LPDWORD lpcbBytesReturned,
752 LPOVERLAPPED lpOverlapped)
754 switch (dwIoControlCode) {
755 case 1: /* version */
756 *(LPDWORD)lpvOutBuffer = 0x20004; /* WC SecretOps */
758 case 9: /* debug output */
759 ERR("MONODEBG: %s\n",debugstr_a(lpvInBuffer));
762 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
764 lpvInBuffer,cbInBuffer,
765 lpvOutBuffer,cbOutBuffer,
775 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode,
776 LPVOID lpvInBuffer, DWORD cbInBuffer,
777 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
778 LPDWORD lpcbBytesReturned,
779 LPOVERLAPPED lpOverlapped)
781 switch (dwIoControlCode) {
782 case 0x0000: /* PCCARD_Get_Version */
783 case 0x0001: /* PCCARD_Card_Services */
785 FIXME( "(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
787 lpvInBuffer,cbInBuffer,
788 lpvOutBuffer,cbOutBuffer,
797 static BOOL DeviceIo_HASP(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
798 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
799 LPDWORD lpcbBytesReturned,
800 LPOVERLAPPED lpOverlapped)
803 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
805 lpvInBuffer,cbInBuffer,
806 lpvOutBuffer,cbOutBuffer,
813 typedef UCHAR (WINAPI *NetbiosFunc)(LPVOID);
815 static BOOL DeviceIo_NetBIOS(DWORD dwIoControlCode,
816 LPVOID lpvInBuffer, DWORD cbInBuffer,
817 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
818 LPDWORD lpcbBytesReturned,
819 LPOVERLAPPED lpOverlapped)
821 static HMODULE netapi;
822 static NetbiosFunc pNetbios;
824 if (dwIoControlCode != 256)
826 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
828 lpvInBuffer,cbInBuffer,
829 lpvOutBuffer,cbOutBuffer,
837 if (!netapi) netapi = LoadLibraryA("netapi32.dll");
838 if (netapi) pNetbios = (NetbiosFunc)GetProcAddress(netapi, "Netbios");
842 pNetbios(lpvInBuffer);
849 static BOOL DeviceIo_DHCP(DWORD dwIoControlCode, LPVOID lpvInBuffer,
851 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
852 LPDWORD lpcbBytesReturned,
853 LPOVERLAPPED lpOverlapped)
857 switch (dwIoControlCode) {
860 /* since IpReleaseAddress/IpRenewAddress are not implemented, say there
861 * are no DHCP adapters
863 error = ERROR_FILE_NOT_FOUND;
867 /* FIXME: don't know what this means */
869 if (lpcbBytesReturned)
870 *lpcbBytesReturned = sizeof(DWORD);
871 if (lpvOutBuffer && cbOutBuffer >= 4)
873 *(LPDWORD)lpvOutBuffer = 0;
877 error = ERROR_BUFFER_OVERFLOW;
881 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
883 lpvInBuffer,cbInBuffer,
884 lpvOutBuffer,cbOutBuffer,
887 error = ERROR_NOT_SUPPORTED;
892 return error == NO_ERROR;
895 typedef DWORD (WINAPI *GetNetworkParamsFunc)(PFIXED_INFO, PDWORD);
896 typedef DWORD (WINAPI *GetAdaptersInfoFunc)(PIP_ADAPTER_INFO, PDWORD);
898 typedef struct _nbtInfo
908 #define MAX_NBT_ENTRIES 7
910 typedef struct _nbtTable
913 nbtInfo table[MAX_NBT_ENTRIES];
920 static BOOL DeviceIo_VNB(DWORD dwIoControlCode,
921 LPVOID lpvInBuffer, DWORD cbInBuffer,
922 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
923 LPDWORD lpcbBytesReturned,
924 LPOVERLAPPED lpOverlapped)
926 static HMODULE iphlpapi;
927 static GetNetworkParamsFunc pGetNetworkParams;
928 static GetAdaptersInfoFunc pGetAdaptersInfo;
931 switch (dwIoControlCode)
934 if (lpcbBytesReturned)
935 *lpcbBytesReturned = sizeof(nbtTable);
936 if (!lpvOutBuffer || cbOutBuffer < sizeof(nbtTable))
937 error = ERROR_BUFFER_OVERFLOW;
940 nbtTable *info = (nbtTable *)lpvOutBuffer;
942 memset(info, 0, sizeof(nbtTable));
945 iphlpapi = LoadLibraryA("iphlpapi.dll");
946 pGetNetworkParams = (GetNetworkParamsFunc)GetProcAddress(iphlpapi,"GetNetworkParams");
947 pGetAdaptersInfo = (GetAdaptersInfoFunc)GetProcAddress(iphlpapi, "GetAdaptersInfo");
953 error = pGetNetworkParams(NULL, &size);
954 if (ERROR_BUFFER_OVERFLOW == error)
956 PFIXED_INFO fixedInfo = (PFIXED_INFO)HeapAlloc(
957 GetProcessHeap(), 0, size);
959 error = pGetNetworkParams(fixedInfo, &size);
960 if (NO_ERROR == error)
962 info->nodeType = (WORD)fixedInfo->NodeType;
963 info->scopeLen = min(strlen(fixedInfo->ScopeId) + 1,
964 sizeof(info->scope) - 2);
965 memcpy(info->scope + 1, fixedInfo->ScopeId,
967 info->scope[info->scopeLen + 1] = '\0';
969 /* convert into L2-encoded version */
972 for (ptr = info->scope + 1; *ptr &&
973 ptr - info->scope < sizeof(info->scope); )
975 for (lenPtr = ptr - 1, *lenPtr = 0;
976 *ptr && *ptr != '.' &&
977 ptr - info->scope < sizeof(info->scope);
983 /* could set DNS servers here too, but since
984 * ipconfig.exe and winipcfg.exe read these from the
985 * registry, there's no point */
988 HeapFree(GetProcessHeap(), 0, fixedInfo);
991 error = pGetAdaptersInfo(NULL, &size);
992 if (ERROR_BUFFER_OVERFLOW == error)
994 PIP_ADAPTER_INFO adapterInfo = (PIP_ADAPTER_INFO)
995 HeapAlloc(GetProcessHeap(), 0, size);
997 error = pGetAdaptersInfo(adapterInfo, &size);
998 if (NO_ERROR == error)
1000 PIP_ADAPTER_INFO ptr = adapterInfo;
1002 for (ptr = adapterInfo; ptr && info->numEntries <
1003 MAX_NBT_ENTRIES; ptr = ptr->Next)
1008 ptr->IpAddressList.IpAddress.String);
1009 if (addr != 0 && addr != INADDR_NONE)
1010 info->table[info->numEntries].ip =
1013 ptr->PrimaryWinsServer.IpAddress.String);
1014 if (addr != 0 && addr != INADDR_NONE)
1015 info->table[info->numEntries].winsPrimary
1018 ptr->SecondaryWinsServer.IpAddress.String);
1019 if (addr != 0 && addr != INADDR_NONE)
1020 info->table[info->numEntries].winsSecondary
1026 HeapFree(GetProcessHeap(), 0, adapterInfo);
1030 error = GetLastError();
1035 /* nbtstat.exe uses this, but the return seems to be a bunch of
1036 * pointers, so it's not so easy to reverse engineer. Fall through
1037 * to unimplemented...
1040 FIXME( "Unimplemented control %ld for VxD device VNB\n",
1042 error = ERROR_NOT_SUPPORTED;
1046 SetLastError(error);
1047 return error == NO_ERROR;