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 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode,
62 LPVOID lpvInBuffer, DWORD cbInBuffer,
63 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
64 LPDWORD lpcbBytesReturned,
65 LPOVERLAPPED lpOverlapped);
66 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode,
67 LPVOID lpvInBuffer, DWORD cbInBuffer,
68 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
69 LPDWORD lpcbBytesReturned,
70 LPOVERLAPPED lpOverlapped);
71 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode,
72 LPVOID lpvInBuffer, DWORD cbInBuffer,
73 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
74 LPDWORD lpcbBytesReturned,
75 LPOVERLAPPED lpOverlapped);
77 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode,
78 LPVOID lpvInBuffer, DWORD cbInBuffer,
79 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
80 LPDWORD lpcbBytesReturned,
81 LPOVERLAPPED lpOverlapped);
83 static BOOL DeviceIo_VCD(DWORD dwIoControlCode,
84 LPVOID lpvInBuffer, DWORD cbInBuffer,
85 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
86 LPDWORD lpcbBytesReturned,
87 LPOVERLAPPED lpOverlapped);
89 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode,
90 LPVOID lpvInBuffer, DWORD cbInBuffer,
91 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
92 LPDWORD lpcbBytesReturned,
93 LPOVERLAPPED lpOverlapped);
95 static BOOL DeviceIo_DHCP(DWORD dwIoControlCode,
96 LPVOID lpvInBuffer, DWORD cbInBuffer,
97 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
98 LPDWORD lpcbBytesReturned,
99 LPOVERLAPPED lpOverlapped);
101 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode,
102 LPVOID lpvInBuffer, DWORD cbInBuffer,
103 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
104 LPDWORD lpcbBytesReturned,
105 LPOVERLAPPED lpOverlapped);
107 static BOOL DeviceIo_HASP (DWORD dwIoControlCode,
108 LPVOID lpvInBuffer, DWORD cbInBuffer,
109 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
110 LPDWORD lpcbBytesReturned,
111 LPOVERLAPPED lpOverlapped);
113 static BOOL DeviceIo_NetBIOS(DWORD dwIoControlCode,
114 LPVOID lpvInBuffer, DWORD cbInBuffer,
115 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
116 LPDWORD lpcbBytesReturned,
117 LPOVERLAPPED lpOverlapped);
119 static BOOL DeviceIo_VNB(DWORD dwIoControlCode,
120 LPVOID lpvInBuffer, DWORD cbInBuffer,
121 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
122 LPDWORD lpcbBytesReturned,
123 LPOVERLAPPED lpOverlapped);
126 * VxD names are taken from the Win95 DDK
133 BOOL (*deviceio)(DWORD, LPVOID, DWORD,
134 LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
137 static const struct VxDInfo VxDList[] =
139 /* Standard VxD IDs */
140 { "VMM", 0x0001, NULL },
141 { "DEBUG", 0x0002, NULL },
142 { "VPICD", 0x0003, NULL },
143 { "VDMAD", 0x0004, NULL },
144 { "VTD", 0x0005, NULL },
145 { "V86MMGR", 0x0006, NULL },
146 { "PAGESWAP", 0x0007, NULL },
147 { "PARITY", 0x0008, NULL },
148 { "REBOOT", 0x0009, NULL },
149 { "VDD", 0x000A, NULL },
150 { "VSD", 0x000B, NULL },
151 { "VMD", 0x000C, NULL },
152 { "VKD", 0x000D, NULL },
153 { "VCD", 0x000E, DeviceIo_VCD },
154 { "VPD", 0x000F, NULL },
155 { "BLOCKDEV", 0x0010, NULL },
156 { "VMCPD", 0x0011, NULL },
157 { "EBIOS", 0x0012, NULL },
158 { "BIOSXLAT", 0x0013, NULL },
159 { "VNETBIOS", 0x0014, DeviceIo_NetBIOS },
160 { "DOSMGR", 0x0015, NULL },
161 { "WINLOAD", 0x0016, NULL },
162 { "SHELL", 0x0017, NULL },
163 { "VMPOLL", 0x0018, NULL },
164 { "VPROD", 0x0019, NULL },
165 { "DOSNET", 0x001A, NULL },
166 { "VFD", 0x001B, NULL },
167 { "VDD2", 0x001C, NULL },
168 { "WINDEBUG", 0x001D, NULL },
169 { "TSRLOAD", 0x001E, NULL },
170 { "BIOSHOOK", 0x001F, NULL },
171 { "INT13", 0x0020, NULL },
172 { "PAGEFILE", 0x0021, NULL },
173 { "SCSI", 0x0022, NULL },
174 { "MCA_POS", 0x0023, NULL },
175 { "SCSIFD", 0x0024, NULL },
176 { "VPEND", 0x0025, NULL },
177 { "VPOWERD", 0x0026, NULL },
178 { "VXDLDR", 0x0027, NULL },
179 { "NDIS", 0x0028, NULL },
180 { "BIOS_EXT", 0x0029, NULL },
181 { "VWIN32", 0x002A, DeviceIo_VWin32 },
182 { "VCOMM", 0x002B, NULL },
183 { "SPOOLER", 0x002C, NULL },
184 { "WIN32S", 0x002D, NULL },
185 { "DEBUGCMD", 0x002E, NULL },
187 { "VNB", 0x0031, DeviceIo_VNB },
188 { "SERVER", 0x0032, NULL },
189 { "CONFIGMG", 0x0033, NULL },
190 { "DWCFGMG", 0x0034, NULL },
191 { "SCSIPORT", 0x0035, NULL },
192 { "VFBACKUP", 0x0036, NULL },
193 { "ENABLE", 0x0037, NULL },
194 { "VCOND", 0x0038, NULL },
196 { "EFAX", 0x003A, NULL },
197 { "DSVXD", 0x003B, NULL },
198 { "ISAPNP", 0x003C, NULL },
199 { "BIOS", 0x003D, NULL },
200 { "WINSOCK", 0x003E, NULL },
201 { "WSOCK", 0x003E, NULL },
202 { "WSIPX", 0x003F, NULL },
203 { "IFSMgr", 0x0040, DeviceIo_IFSMgr },
204 { "VCDFSD", 0x0041, NULL },
205 { "MRCI2", 0x0042, NULL },
206 { "PCI", 0x0043, NULL },
207 { "PELOADER", 0x0044, NULL },
208 { "EISA", 0x0045, NULL },
209 { "DRAGCLI", 0x0046, NULL },
210 { "DRAGSRV", 0x0047, NULL },
211 { "PERF", 0x0048, NULL },
212 { "AWREDIR", 0x0049, NULL },
214 /* Far East support */
215 { "ETEN", 0x0060, NULL },
216 { "CHBIOS", 0x0061, NULL },
217 { "VMSGD", 0x0062, NULL },
218 { "VPPID", 0x0063, NULL },
219 { "VIME", 0x0064, NULL },
220 { "VHBIOSD", 0x0065, NULL },
222 /* Multimedia OEM IDs */
223 { "VTDAPI", 0x0442, DeviceIo_VTDAPI },
224 { "MMDEVLDR", 0x044A, DeviceIo_MMDEVLDR },
226 /* Network Device IDs */
227 { "VNetSup", 0x0480, NULL },
228 { "VRedir", 0x0481, NULL },
229 { "VBrowse", 0x0482, NULL },
230 { "VSHARE", 0x0483, NULL },
231 { "IFSMgr", 0x0484, NULL },
232 { "MEMPROBE", 0x0485, NULL },
233 { "VFAT", 0x0486, NULL },
234 { "NWLINK", 0x0487, NULL },
235 { "VNWLINK", 0x0487, NULL },
236 { "NWSUP", 0x0487, NULL },
237 { "VTDI", 0x0488, NULL },
238 { "VIP", 0x0489, NULL },
239 { "VTCP", 0x048A, NULL },
240 { "VCache", 0x048B, NULL },
241 { "VUDP", 0x048C, NULL },
242 { "VAsync", 0x048D, NULL },
243 { "NWREDIR", 0x048E, NULL },
244 { "STAT80", 0x048F, NULL },
245 { "SCSIPORT", 0x0490, NULL },
246 { "FILESEC", 0x0491, NULL },
247 { "NWSERVER", 0x0492, NULL },
248 { "SECPROV", 0x0493, NULL },
249 { "NSCL", 0x0494, NULL },
250 { "WSTCP", 0x0495, NULL },
251 { "NDIS2SUP", 0x0496, NULL },
252 { "MSODISUP", 0x0497, NULL },
253 { "Splitter", 0x0498, NULL },
254 { "PPP", 0x0499, NULL },
255 { "VDHCP", 0x049A, DeviceIo_DHCP },
256 { "VNBT", 0x049B, NULL },
257 { "LOGGER", 0x049D, NULL },
258 { "EFILTER", 0x049E, NULL },
259 { "FFILTER", 0x049F, NULL },
260 { "TFILTER", 0x04A0, NULL },
261 { "AFILTER", 0x04A1, NULL },
262 { "IRLAMP", 0x04A2, NULL },
264 { "PCCARD", 0x097C, DeviceIo_PCCARD },
265 { "HASP95", 0x3721, DeviceIo_HASP },
267 /* WINE additions, ids unknown */
268 { "MONODEBG.VXD", 0x4242, DeviceIo_MONODEBG },
273 HANDLE DEVICE_Open( LPCWSTR filenameW, DWORD access, LPSECURITY_ATTRIBUTES sa )
275 const struct VxDInfo *info;
276 char filename[MAX_PATH];
278 if (!WideCharToMultiByte(CP_ACP, 0, filenameW, -1, filename, MAX_PATH, NULL, NULL))
280 SetLastError( ERROR_FILE_NOT_FOUND );
284 for (info = VxDList; info->name; info++)
285 if (!strncasecmp( info->name, filename, strlen(info->name) ))
286 return FILE_CreateDevice( info->id | 0x10000, access, sa );
288 FIXME( "Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.\n",
290 SetLastError( ERROR_FILE_NOT_FOUND );
294 static DWORD DEVICE_GetClientID( HANDLE handle )
297 SERVER_START_REQ( get_device_id )
299 req->handle = handle;
300 if (!wine_server_call( req )) ret = reply->id;
306 static const struct VxDInfo *DEVICE_GetInfo( DWORD clientID )
308 const struct VxDInfo *info = NULL;
310 if (clientID & 0x10000)
312 for (info = VxDList; info->name; info++)
313 if (info->id == LOWORD(clientID)) break;
318 /****************************************************************************
319 * DeviceIoControl (KERNEL32.@)
320 * This is one of those big ugly nasty procedure which can do
321 * a million and one things when it comes to devices. It can also be
322 * used for VxD communication.
324 * A return value of FALSE indicates that something has gone wrong which
325 * GetLastError can decipher.
327 BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
328 LPVOID lpvInBuffer, DWORD cbInBuffer,
329 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
330 LPDWORD lpcbBytesReturned,
331 LPOVERLAPPED lpOverlapped)
335 TRACE( "(%p,%ld,%p,%ld,%p,%ld,%p,%p)\n",
336 hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
337 lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped );
339 if (!(clientID = DEVICE_GetClientID( hDevice )))
341 SetLastError( ERROR_INVALID_PARAMETER );
345 /* Check if this is a user defined control code for a VxD */
346 if( HIWORD( dwIoControlCode ) == 0 )
348 const struct VxDInfo *info;
349 if (!(info = DEVICE_GetInfo( clientID )))
351 FIXME( "No device found for id %lx\n", clientID);
353 else if ( info->deviceio )
355 return info->deviceio( dwIoControlCode,
356 lpvInBuffer, cbInBuffer,
357 lpvOutBuffer, cbOutBuffer,
358 lpcbBytesReturned, lpOverlapped );
362 FIXME( "Unimplemented control %ld for VxD device %s\n",
363 dwIoControlCode, info->name ? info->name : "???" );
364 /* FIXME: this is for invalid calls on W98SE,
365 * but maybe we should use ERROR_CALL_NOT_IMPLEMENTED
367 SetLastError( ERROR_INVALID_FUNCTION );
376 status = NtDeviceIoControlFile(hDevice, lpOverlapped->hEvent,
378 (PIO_STATUS_BLOCK)lpOverlapped,
380 lpvInBuffer, cbInBuffer,
381 lpvOutBuffer, cbOutBuffer);
382 if (status) SetLastError(RtlNtStatusToDosError(status));
383 if (lpcbBytesReturned) *lpcbBytesReturned = lpOverlapped->InternalHigh;
388 IO_STATUS_BLOCK iosb;
390 status = NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, &iosb,
392 lpvInBuffer, cbInBuffer,
393 lpvOutBuffer, cbOutBuffer);
394 if (status) SetLastError(RtlNtStatusToDosError(status));
395 if (lpcbBytesReturned) *lpcbBytesReturned = iosb.Information;
402 /***********************************************************************
405 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
406 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
407 LPDWORD lpcbBytesReturned,
408 LPOVERLAPPED lpOverlapped)
412 switch (dwIoControlCode)
415 if (lpvOutBuffer && (cbOutBuffer>=4))
416 *(DWORD*)lpvOutBuffer = GetTickCount();
418 if (lpcbBytesReturned)
419 *lpcbBytesReturned = 4;
424 FIXME( "Control %ld not implemented\n", dwIoControlCode);
432 /***********************************************************************
435 * These ioctls are used by 'MSNET32.DLL'.
437 * I have been unable to uncover any documentation about the ioctls so
438 * the implementation of the cases IFS_IOCTL_21 and IFS_IOCTL_2F are
439 * based on reasonable guesses on information found in the Windows 95 DDK.
444 * IFSMgr DeviceIO service
447 #define IFS_IOCTL_21 100
448 #define IFS_IOCTL_2F 101
449 #define IFS_IOCTL_GET_RES 102
450 #define IFS_IOCTL_GET_NETPRO_NAME_A 103
453 unsigned long ar_proid;
454 unsigned long ar_eax;
455 unsigned long ar_ebx;
456 unsigned long ar_ecx;
457 unsigned long ar_edx;
458 unsigned long ar_esi;
459 unsigned long ar_edi;
460 unsigned long ar_ebp;
461 unsigned short ar_error;
462 unsigned short ar_pad;
465 static void win32apieq_2_CONTEXT(struct win32apireq *pIn,CONTEXT86 *pCxt)
467 memset(pCxt,0,sizeof(*pCxt));
469 pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
470 pCxt->Eax = pIn->ar_eax;
471 pCxt->Ebx = pIn->ar_ebx;
472 pCxt->Ecx = pIn->ar_ecx;
473 pCxt->Edx = pIn->ar_edx;
474 pCxt->Esi = pIn->ar_esi;
475 pCxt->Edi = pIn->ar_edi;
477 /* FIXME: Only partial CONTEXT86_CONTROL */
478 pCxt->Ebp = pIn->ar_ebp;
480 /* FIXME: pIn->ar_proid ignored */
481 /* FIXME: pIn->ar_error ignored */
482 /* FIXME: pIn->ar_pad ignored */
485 static void CONTEXT_2_win32apieq(CONTEXT86 *pCxt,struct win32apireq *pOut)
487 memset(pOut,0,sizeof(struct win32apireq));
489 pOut->ar_eax = pCxt->Eax;
490 pOut->ar_ebx = pCxt->Ebx;
491 pOut->ar_ecx = pCxt->Ecx;
492 pOut->ar_edx = pCxt->Edx;
493 pOut->ar_esi = pCxt->Esi;
494 pOut->ar_edi = pCxt->Edi;
496 /* FIXME: Only partial CONTEXT86_CONTROL */
497 pOut->ar_ebp = pCxt->Ebp;
499 /* FIXME: pOut->ar_proid ignored */
500 /* FIXME: pOut->ar_error ignored */
501 /* FIXME: pOut->ar_pad ignored */
504 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
505 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
506 LPDWORD lpcbBytesReturned,
507 LPOVERLAPPED lpOverlapped)
510 TRACE("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
512 lpvInBuffer,cbInBuffer,
513 lpvOutBuffer,cbOutBuffer,
517 switch (dwIoControlCode)
522 struct win32apireq *pIn=(struct win32apireq *) lpvInBuffer;
523 struct win32apireq *pOut=(struct win32apireq *) lpvOutBuffer;
527 "proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
528 "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx, ebp=0x%08lx, "
529 "error=0x%04x, pad=0x%04x\n",
530 (dwIoControlCode==IFS_IOCTL_21)?"IFS_IOCTL_21":"IFS_IOCTL_2F",
531 pIn->ar_proid, pIn->ar_eax, pIn->ar_ebx, pIn->ar_ecx,
532 pIn->ar_edx, pIn->ar_esi, pIn->ar_edi, pIn->ar_ebp,
533 pIn->ar_error, pIn->ar_pad
536 win32apieq_2_CONTEXT(pIn,&cxt);
538 if(dwIoControlCode==IFS_IOCTL_21)
539 INSTR_CallBuiltinHandler( &cxt, 0x21 );
541 INSTR_CallBuiltinHandler( &cxt, 0x2f );
543 CONTEXT_2_win32apieq(&cxt,pOut);
547 case IFS_IOCTL_GET_RES:{
548 FIXME( "Control 'IFS_IOCTL_GET_RES' not implemented\n");
551 case IFS_IOCTL_GET_NETPRO_NAME_A:{
552 FIXME( "Control 'IFS_IOCTL_GET_NETPRO_NAME_A' not implemented\n");
556 FIXME( "Control %ld not implemented\n", dwIoControlCode);
563 /***********************************************************************
566 static BOOL DeviceIo_VCD(DWORD dwIoControlCode,
567 LPVOID lpvInBuffer, DWORD cbInBuffer,
568 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
569 LPDWORD lpcbBytesReturned,
570 LPOVERLAPPED lpOverlapped)
574 switch (dwIoControlCode)
576 case IOCTL_SERIAL_LSRMST_INSERT:
578 FIXME( "IOCTL_SERIAL_LSRMST_INSERT NIY !\n");
584 FIXME( "Unknown Control %ld\n", dwIoControlCode);
593 /***********************************************************************
597 static void DIOCRegs_2_CONTEXT( DIOC_REGISTERS *pIn, CONTEXT86 *pCxt )
599 memset( pCxt, 0, sizeof(*pCxt) );
600 /* Note: segment registers == 0 means that CTX_SEG_OFF_TO_LIN
601 will interpret 32-bit register contents as linear pointers */
603 pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
604 pCxt->Eax = pIn->reg_EAX;
605 pCxt->Ebx = pIn->reg_EBX;
606 pCxt->Ecx = pIn->reg_ECX;
607 pCxt->Edx = pIn->reg_EDX;
608 pCxt->Esi = pIn->reg_ESI;
609 pCxt->Edi = pIn->reg_EDI;
611 /* FIXME: Only partial CONTEXT86_CONTROL */
612 pCxt->EFlags = pIn->reg_Flags;
615 static void CONTEXT_2_DIOCRegs( CONTEXT86 *pCxt, DIOC_REGISTERS *pOut )
617 memset( pOut, 0, sizeof(DIOC_REGISTERS) );
619 pOut->reg_EAX = pCxt->Eax;
620 pOut->reg_EBX = pCxt->Ebx;
621 pOut->reg_ECX = pCxt->Ecx;
622 pOut->reg_EDX = pCxt->Edx;
623 pOut->reg_ESI = pCxt->Esi;
624 pOut->reg_EDI = pCxt->Edi;
626 /* FIXME: Only partial CONTEXT86_CONTROL */
627 pOut->reg_Flags = pCxt->EFlags;
630 #define DIOC_AH(regs) (((unsigned char*)&((regs)->reg_EAX))[1])
631 #define DIOC_AL(regs) (((unsigned char*)&((regs)->reg_EAX))[0])
632 #define DIOC_BH(regs) (((unsigned char*)&((regs)->reg_EBX))[1])
633 #define DIOC_BL(regs) (((unsigned char*)&((regs)->reg_EBX))[0])
634 #define DIOC_DH(regs) (((unsigned char*)&((regs)->reg_EDX))[1])
635 #define DIOC_DL(regs) (((unsigned char*)&((regs)->reg_EDX))[0])
637 #define DIOC_AX(regs) (((unsigned short*)&((regs)->reg_EAX))[0])
638 #define DIOC_BX(regs) (((unsigned short*)&((regs)->reg_EBX))[0])
639 #define DIOC_CX(regs) (((unsigned short*)&((regs)->reg_ECX))[0])
640 #define DIOC_DX(regs) (((unsigned short*)&((regs)->reg_EDX))[0])
642 #define DIOC_SET_CARRY(regs) (((regs)->reg_Flags)|=0x00000001)
644 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode,
645 LPVOID lpvInBuffer, DWORD cbInBuffer,
646 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
647 LPDWORD lpcbBytesReturned,
648 LPOVERLAPPED lpOverlapped)
652 switch (dwIoControlCode)
654 case VWIN32_DIOC_DOS_IOCTL:
655 case 0x10: /* Int 0x21 call, call it VWIN_DIOC_INT21 ? */
656 case VWIN32_DIOC_DOS_INT13:
657 case VWIN32_DIOC_DOS_INT25:
658 case VWIN32_DIOC_DOS_INT26:
659 case 0x29: /* Int 0x31 call, call it VWIN_DIOC_INT31 ? */
660 case VWIN32_DIOC_DOS_DRIVEINFO:
663 DIOC_REGISTERS *pIn = (DIOC_REGISTERS *)lpvInBuffer;
664 DIOC_REGISTERS *pOut = (DIOC_REGISTERS *)lpvOutBuffer;
667 TRACE( "Control '%s': "
668 "eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
669 "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx \n",
670 (dwIoControlCode == VWIN32_DIOC_DOS_IOCTL)? "VWIN32_DIOC_DOS_IOCTL" :
671 (dwIoControlCode == VWIN32_DIOC_DOS_INT25)? "VWIN32_DIOC_DOS_INT25" :
672 (dwIoControlCode == VWIN32_DIOC_DOS_INT26)? "VWIN32_DIOC_DOS_INT26" :
673 (dwIoControlCode == VWIN32_DIOC_DOS_DRIVEINFO)? "VWIN32_DIOC_DOS_DRIVEINFO" : "???",
674 pIn->reg_EAX, pIn->reg_EBX, pIn->reg_ECX,
675 pIn->reg_EDX, pIn->reg_ESI, pIn->reg_EDI );
677 DIOCRegs_2_CONTEXT( pIn, &cxt );
679 switch (dwIoControlCode)
681 case VWIN32_DIOC_DOS_IOCTL: /* Call int 21h */
682 case 0x10: /* Int 0x21 call, call it VWIN_DIOC_INT21 ? */
683 case VWIN32_DIOC_DOS_DRIVEINFO: /* Call int 21h 730x */
686 case VWIN32_DIOC_DOS_INT13:
689 case VWIN32_DIOC_DOS_INT25:
692 case VWIN32_DIOC_DOS_INT26:
695 case 0x29: /* Int 0x31 call, call it VWIN_DIOC_INT31 ? */
700 INSTR_CallBuiltinHandler( &cxt, intnum );
701 CONTEXT_2_DIOCRegs( &cxt, pOut );
705 case VWIN32_DIOC_SIMCTRLC:
706 FIXME( "Control VWIN32_DIOC_SIMCTRLC not implemented\n");
711 FIXME( "Unknown Control %ld\n", dwIoControlCode);
719 /* this is the main multimedia device loader */
720 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode,
721 LPVOID lpvInBuffer, DWORD cbInBuffer,
722 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
723 LPDWORD lpcbBytesReturned,
724 LPOVERLAPPED lpOverlapped)
726 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
728 lpvInBuffer,cbInBuffer,
729 lpvOutBuffer,cbOutBuffer,
733 switch (dwIoControlCode) {
736 *(DWORD*)lpvOutBuffer=0;
737 *lpcbBytesReturned=4;
742 /* this is used by some Origin games */
743 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode,
744 LPVOID lpvInBuffer, DWORD cbInBuffer,
745 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
746 LPDWORD lpcbBytesReturned,
747 LPOVERLAPPED lpOverlapped)
749 switch (dwIoControlCode) {
750 case 1: /* version */
751 *(LPDWORD)lpvOutBuffer = 0x20004; /* WC SecretOps */
753 case 9: /* debug output */
754 ERR("MONODEBG: %s\n",debugstr_a(lpvInBuffer));
757 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
759 lpvInBuffer,cbInBuffer,
760 lpvOutBuffer,cbOutBuffer,
770 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode,
771 LPVOID lpvInBuffer, DWORD cbInBuffer,
772 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
773 LPDWORD lpcbBytesReturned,
774 LPOVERLAPPED lpOverlapped)
776 switch (dwIoControlCode) {
777 case 0x0000: /* PCCARD_Get_Version */
778 case 0x0001: /* PCCARD_Card_Services */
780 FIXME( "(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
782 lpvInBuffer,cbInBuffer,
783 lpvOutBuffer,cbOutBuffer,
792 static BOOL DeviceIo_HASP(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
793 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
794 LPDWORD lpcbBytesReturned,
795 LPOVERLAPPED lpOverlapped)
798 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
800 lpvInBuffer,cbInBuffer,
801 lpvOutBuffer,cbOutBuffer,
808 typedef UCHAR (WINAPI *NetbiosFunc)(LPVOID);
810 static BOOL DeviceIo_NetBIOS(DWORD dwIoControlCode,
811 LPVOID lpvInBuffer, DWORD cbInBuffer,
812 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
813 LPDWORD lpcbBytesReturned,
814 LPOVERLAPPED lpOverlapped)
816 static HMODULE netapi;
817 static NetbiosFunc pNetbios;
819 if (dwIoControlCode != 256)
821 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
823 lpvInBuffer,cbInBuffer,
824 lpvOutBuffer,cbOutBuffer,
832 if (!netapi) netapi = LoadLibraryA("netapi32.dll");
833 if (netapi) pNetbios = (NetbiosFunc)GetProcAddress(netapi, "Netbios");
837 pNetbios(lpvInBuffer);
844 static BOOL DeviceIo_DHCP(DWORD dwIoControlCode, LPVOID lpvInBuffer,
846 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
847 LPDWORD lpcbBytesReturned,
848 LPOVERLAPPED lpOverlapped)
852 switch (dwIoControlCode) {
855 /* since IpReleaseAddress/IpRenewAddress are not implemented, say there
856 * are no DHCP adapters
858 error = ERROR_FILE_NOT_FOUND;
862 /* FIXME: don't know what this means */
864 if (lpcbBytesReturned)
865 *lpcbBytesReturned = sizeof(DWORD);
866 if (lpvOutBuffer && cbOutBuffer >= 4)
868 *(LPDWORD)lpvOutBuffer = 0;
872 error = ERROR_BUFFER_OVERFLOW;
876 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
878 lpvInBuffer,cbInBuffer,
879 lpvOutBuffer,cbOutBuffer,
882 error = ERROR_NOT_SUPPORTED;
887 return error == NO_ERROR;
890 typedef DWORD (WINAPI *GetNetworkParamsFunc)(PFIXED_INFO, PDWORD);
891 typedef DWORD (WINAPI *GetAdaptersInfoFunc)(PIP_ADAPTER_INFO, PDWORD);
893 typedef struct _nbtInfo
903 #define MAX_NBT_ENTRIES 7
905 typedef struct _nbtTable
908 nbtInfo table[MAX_NBT_ENTRIES];
915 static BOOL DeviceIo_VNB(DWORD dwIoControlCode,
916 LPVOID lpvInBuffer, DWORD cbInBuffer,
917 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
918 LPDWORD lpcbBytesReturned,
919 LPOVERLAPPED lpOverlapped)
921 static HMODULE iphlpapi;
922 static GetNetworkParamsFunc pGetNetworkParams;
923 static GetAdaptersInfoFunc pGetAdaptersInfo;
926 switch (dwIoControlCode)
929 if (lpcbBytesReturned)
930 *lpcbBytesReturned = sizeof(nbtTable);
931 if (!lpvOutBuffer || cbOutBuffer < sizeof(nbtTable))
932 error = ERROR_BUFFER_OVERFLOW;
935 nbtTable *info = (nbtTable *)lpvOutBuffer;
937 memset(info, 0, sizeof(nbtTable));
940 iphlpapi = LoadLibraryA("iphlpapi.dll");
941 pGetNetworkParams = (GetNetworkParamsFunc)GetProcAddress(iphlpapi,"GetNetworkParams");
942 pGetAdaptersInfo = (GetAdaptersInfoFunc)GetProcAddress(iphlpapi, "GetAdaptersInfo");
948 error = pGetNetworkParams(NULL, &size);
949 if (ERROR_BUFFER_OVERFLOW == error)
951 PFIXED_INFO fixedInfo = (PFIXED_INFO)HeapAlloc(
952 GetProcessHeap(), 0, size);
954 error = pGetNetworkParams(fixedInfo, &size);
955 if (NO_ERROR == error)
957 info->nodeType = (WORD)fixedInfo->NodeType;
958 info->scopeLen = max(strlen(fixedInfo->ScopeId) + 1,
959 sizeof(info->scope) - 1);
960 memcpy(info->scope, fixedInfo->ScopeId,
962 info->scope[info->scopeLen] = '\0';
963 /* FIXME: gotta L2-encode the scope ID */
964 /* could set DNS servers here too, but since
965 * ipconfig.exe and winipcfg.exe read these from the
966 * registry, there's no point */
969 HeapFree(GetProcessHeap(), 0, fixedInfo);
972 error = pGetAdaptersInfo(NULL, &size);
973 if (ERROR_BUFFER_OVERFLOW == error)
975 PIP_ADAPTER_INFO adapterInfo = (PIP_ADAPTER_INFO)
976 HeapAlloc(GetProcessHeap(), 0, size);
978 error = pGetAdaptersInfo(adapterInfo, &size);
979 if (NO_ERROR == error)
981 PIP_ADAPTER_INFO ptr = adapterInfo;
983 for (ptr = adapterInfo; ptr && info->numEntries <
984 MAX_NBT_ENTRIES; ptr = ptr->Next)
989 ptr->IpAddressList.IpAddress.String);
990 if (addr != 0 && addr != INADDR_NONE)
991 info->table[info->numEntries].ip =
994 ptr->PrimaryWinsServer.IpAddress.String);
995 if (addr != 0 && addr != INADDR_NONE)
996 info->table[info->numEntries].winsPrimary
999 ptr->SecondaryWinsServer.IpAddress.String);
1000 if (addr != 0 && addr != INADDR_NONE)
1001 info->table[info->numEntries].winsSecondary
1007 HeapFree(GetProcessHeap(), 0, adapterInfo);
1011 error = GetLastError();
1016 /* nbtstat.exe uses this, but the return seems to be a bunch of
1017 * pointers, so it's not so easy to reverse engineer. Fall through
1018 * to unimplemented...
1021 FIXME( "Unimplemented control %ld for VxD device VNB\n",
1023 error = ERROR_NOT_SUPPORTED;
1027 SetLastError(error);
1028 return error == NO_ERROR;