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",
291 SetLastError( ERROR_FILE_NOT_FOUND );
295 static DWORD DEVICE_GetClientID( HANDLE handle )
298 SERVER_START_REQ( get_device_id )
300 req->handle = handle;
301 if (!wine_server_call( req )) ret = reply->id;
307 static const struct VxDInfo *DEVICE_GetInfo( DWORD clientID )
309 const struct VxDInfo *info = NULL;
311 if (clientID & 0x10000)
313 for (info = VxDList; info->name; info++)
314 if (info->id == LOWORD(clientID)) break;
319 /****************************************************************************
320 * DeviceIoControl (KERNEL32.@)
321 * This is one of those big ugly nasty procedure which can do
322 * a million and one things when it comes to devices. It can also be
323 * used for VxD communication.
325 * A return value of FALSE indicates that something has gone wrong which
326 * GetLastError can decipher.
328 BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,
329 LPVOID lpvInBuffer, DWORD cbInBuffer,
330 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
331 LPDWORD lpcbBytesReturned,
332 LPOVERLAPPED lpOverlapped)
336 TRACE( "(%p,%ld,%p,%ld,%p,%ld,%p,%p)\n",
337 hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
338 lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped );
340 if (!(clientID = DEVICE_GetClientID( hDevice )))
342 SetLastError( ERROR_INVALID_PARAMETER );
346 /* Check if this is a user defined control code for a VxD */
347 if( HIWORD( dwIoControlCode ) == 0 )
349 const struct VxDInfo *info;
350 if (!(info = DEVICE_GetInfo( clientID )))
352 FIXME( "No device found for id %lx\n", clientID);
354 else if ( info->deviceio )
356 return info->deviceio( dwIoControlCode,
357 lpvInBuffer, cbInBuffer,
358 lpvOutBuffer, cbOutBuffer,
359 lpcbBytesReturned, lpOverlapped );
363 FIXME( "Unimplemented control %ld for VxD device %s\n",
364 dwIoControlCode, info->name ? info->name : "???" );
365 /* FIXME: this is for invalid calls on W98SE,
366 * but maybe we should use ERROR_CALL_NOT_IMPLEMENTED
368 SetLastError( ERROR_INVALID_FUNCTION );
377 status = NtDeviceIoControlFile(hDevice, lpOverlapped->hEvent,
379 (PIO_STATUS_BLOCK)lpOverlapped,
381 lpvInBuffer, cbInBuffer,
382 lpvOutBuffer, cbOutBuffer);
383 if (status) SetLastError(RtlNtStatusToDosError(status));
384 if (lpcbBytesReturned) *lpcbBytesReturned = lpOverlapped->InternalHigh;
389 IO_STATUS_BLOCK iosb;
391 status = NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, &iosb,
393 lpvInBuffer, cbInBuffer,
394 lpvOutBuffer, cbOutBuffer);
395 if (status) SetLastError(RtlNtStatusToDosError(status));
396 if (lpcbBytesReturned) *lpcbBytesReturned = iosb.Information;
403 /***********************************************************************
406 static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
407 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
408 LPDWORD lpcbBytesReturned,
409 LPOVERLAPPED lpOverlapped)
413 switch (dwIoControlCode)
416 if (lpvOutBuffer && (cbOutBuffer>=4))
417 *(DWORD*)lpvOutBuffer = GetTickCount();
419 if (lpcbBytesReturned)
420 *lpcbBytesReturned = 4;
425 FIXME( "Control %ld not implemented\n", dwIoControlCode);
433 /***********************************************************************
436 * These ioctls are used by 'MSNET32.DLL'.
438 * I have been unable to uncover any documentation about the ioctls so
439 * the implementation of the cases IFS_IOCTL_21 and IFS_IOCTL_2F are
440 * based on reasonable guesses on information found in the Windows 95 DDK.
445 * IFSMgr DeviceIO service
448 #define IFS_IOCTL_21 100
449 #define IFS_IOCTL_2F 101
450 #define IFS_IOCTL_GET_RES 102
451 #define IFS_IOCTL_GET_NETPRO_NAME_A 103
454 unsigned long ar_proid;
455 unsigned long ar_eax;
456 unsigned long ar_ebx;
457 unsigned long ar_ecx;
458 unsigned long ar_edx;
459 unsigned long ar_esi;
460 unsigned long ar_edi;
461 unsigned long ar_ebp;
462 unsigned short ar_error;
463 unsigned short ar_pad;
466 static void win32apieq_2_CONTEXT(struct win32apireq *pIn,CONTEXT86 *pCxt)
468 memset(pCxt,0,sizeof(*pCxt));
470 pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
471 pCxt->Eax = pIn->ar_eax;
472 pCxt->Ebx = pIn->ar_ebx;
473 pCxt->Ecx = pIn->ar_ecx;
474 pCxt->Edx = pIn->ar_edx;
475 pCxt->Esi = pIn->ar_esi;
476 pCxt->Edi = pIn->ar_edi;
478 /* FIXME: Only partial CONTEXT86_CONTROL */
479 pCxt->Ebp = pIn->ar_ebp;
481 /* FIXME: pIn->ar_proid ignored */
482 /* FIXME: pIn->ar_error ignored */
483 /* FIXME: pIn->ar_pad ignored */
486 static void CONTEXT_2_win32apieq(CONTEXT86 *pCxt,struct win32apireq *pOut)
488 memset(pOut,0,sizeof(struct win32apireq));
490 pOut->ar_eax = pCxt->Eax;
491 pOut->ar_ebx = pCxt->Ebx;
492 pOut->ar_ecx = pCxt->Ecx;
493 pOut->ar_edx = pCxt->Edx;
494 pOut->ar_esi = pCxt->Esi;
495 pOut->ar_edi = pCxt->Edi;
497 /* FIXME: Only partial CONTEXT86_CONTROL */
498 pOut->ar_ebp = pCxt->Ebp;
500 /* FIXME: pOut->ar_proid ignored */
501 /* FIXME: pOut->ar_error ignored */
502 /* FIXME: pOut->ar_pad ignored */
505 static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
506 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
507 LPDWORD lpcbBytesReturned,
508 LPOVERLAPPED lpOverlapped)
511 TRACE("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
513 lpvInBuffer,cbInBuffer,
514 lpvOutBuffer,cbOutBuffer,
518 switch (dwIoControlCode)
523 struct win32apireq *pIn=(struct win32apireq *) lpvInBuffer;
524 struct win32apireq *pOut=(struct win32apireq *) lpvOutBuffer;
528 "proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
529 "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx, ebp=0x%08lx, "
530 "error=0x%04x, pad=0x%04x\n",
531 (dwIoControlCode==IFS_IOCTL_21)?"IFS_IOCTL_21":"IFS_IOCTL_2F",
532 pIn->ar_proid, pIn->ar_eax, pIn->ar_ebx, pIn->ar_ecx,
533 pIn->ar_edx, pIn->ar_esi, pIn->ar_edi, pIn->ar_ebp,
534 pIn->ar_error, pIn->ar_pad
537 win32apieq_2_CONTEXT(pIn,&cxt);
539 if(dwIoControlCode==IFS_IOCTL_21)
540 INSTR_CallBuiltinHandler( &cxt, 0x21 );
542 INSTR_CallBuiltinHandler( &cxt, 0x2f );
544 CONTEXT_2_win32apieq(&cxt,pOut);
548 case IFS_IOCTL_GET_RES:{
549 FIXME( "Control 'IFS_IOCTL_GET_RES' not implemented\n");
552 case IFS_IOCTL_GET_NETPRO_NAME_A:{
553 FIXME( "Control 'IFS_IOCTL_GET_NETPRO_NAME_A' not implemented\n");
557 FIXME( "Control %ld not implemented\n", dwIoControlCode);
564 /***********************************************************************
567 static BOOL DeviceIo_VCD(DWORD dwIoControlCode,
568 LPVOID lpvInBuffer, DWORD cbInBuffer,
569 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
570 LPDWORD lpcbBytesReturned,
571 LPOVERLAPPED lpOverlapped)
575 switch (dwIoControlCode)
577 case IOCTL_SERIAL_LSRMST_INSERT:
579 FIXME( "IOCTL_SERIAL_LSRMST_INSERT NIY !\n");
585 FIXME( "Unknown Control %ld\n", dwIoControlCode);
594 /***********************************************************************
598 static void DIOCRegs_2_CONTEXT( DIOC_REGISTERS *pIn, CONTEXT86 *pCxt )
600 memset( pCxt, 0, sizeof(*pCxt) );
601 /* Note: segment registers == 0 means that CTX_SEG_OFF_TO_LIN
602 will interpret 32-bit register contents as linear pointers */
604 pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
605 pCxt->Eax = pIn->reg_EAX;
606 pCxt->Ebx = pIn->reg_EBX;
607 pCxt->Ecx = pIn->reg_ECX;
608 pCxt->Edx = pIn->reg_EDX;
609 pCxt->Esi = pIn->reg_ESI;
610 pCxt->Edi = pIn->reg_EDI;
612 /* FIXME: Only partial CONTEXT86_CONTROL */
614 pCxt->EFlags = pIn->reg_Flags & ~0x00020000; /* clear vm86 mode */
617 static void CONTEXT_2_DIOCRegs( CONTEXT86 *pCxt, DIOC_REGISTERS *pOut )
619 memset( pOut, 0, sizeof(DIOC_REGISTERS) );
621 pOut->reg_EAX = pCxt->Eax;
622 pOut->reg_EBX = pCxt->Ebx;
623 pOut->reg_ECX = pCxt->Ecx;
624 pOut->reg_EDX = pCxt->Edx;
625 pOut->reg_ESI = pCxt->Esi;
626 pOut->reg_EDI = pCxt->Edi;
628 /* FIXME: Only partial CONTEXT86_CONTROL */
629 pOut->reg_Flags = pCxt->EFlags;
632 #define DIOC_AH(regs) (((unsigned char*)&((regs)->reg_EAX))[1])
633 #define DIOC_AL(regs) (((unsigned char*)&((regs)->reg_EAX))[0])
634 #define DIOC_BH(regs) (((unsigned char*)&((regs)->reg_EBX))[1])
635 #define DIOC_BL(regs) (((unsigned char*)&((regs)->reg_EBX))[0])
636 #define DIOC_DH(regs) (((unsigned char*)&((regs)->reg_EDX))[1])
637 #define DIOC_DL(regs) (((unsigned char*)&((regs)->reg_EDX))[0])
639 #define DIOC_AX(regs) (((unsigned short*)&((regs)->reg_EAX))[0])
640 #define DIOC_BX(regs) (((unsigned short*)&((regs)->reg_EBX))[0])
641 #define DIOC_CX(regs) (((unsigned short*)&((regs)->reg_ECX))[0])
642 #define DIOC_DX(regs) (((unsigned short*)&((regs)->reg_EDX))[0])
644 #define DIOC_SET_CARRY(regs) (((regs)->reg_Flags)|=0x00000001)
646 static BOOL DeviceIo_VWin32(DWORD dwIoControlCode,
647 LPVOID lpvInBuffer, DWORD cbInBuffer,
648 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
649 LPDWORD lpcbBytesReturned,
650 LPOVERLAPPED lpOverlapped)
654 switch (dwIoControlCode)
656 case VWIN32_DIOC_DOS_IOCTL:
657 case 0x10: /* Int 0x21 call, call it VWIN_DIOC_INT21 ? */
658 case VWIN32_DIOC_DOS_INT13:
659 case VWIN32_DIOC_DOS_INT25:
660 case VWIN32_DIOC_DOS_INT26:
661 case 0x29: /* Int 0x31 call, call it VWIN_DIOC_INT31 ? */
662 case VWIN32_DIOC_DOS_DRIVEINFO:
665 DIOC_REGISTERS *pIn = (DIOC_REGISTERS *)lpvInBuffer;
666 DIOC_REGISTERS *pOut = (DIOC_REGISTERS *)lpvOutBuffer;
669 TRACE( "Control '%s': "
670 "eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
671 "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx \n",
672 (dwIoControlCode == VWIN32_DIOC_DOS_IOCTL)? "VWIN32_DIOC_DOS_IOCTL" :
673 (dwIoControlCode == VWIN32_DIOC_DOS_INT25)? "VWIN32_DIOC_DOS_INT25" :
674 (dwIoControlCode == VWIN32_DIOC_DOS_INT26)? "VWIN32_DIOC_DOS_INT26" :
675 (dwIoControlCode == VWIN32_DIOC_DOS_DRIVEINFO)? "VWIN32_DIOC_DOS_DRIVEINFO" : "???",
676 pIn->reg_EAX, pIn->reg_EBX, pIn->reg_ECX,
677 pIn->reg_EDX, pIn->reg_ESI, pIn->reg_EDI );
679 DIOCRegs_2_CONTEXT( pIn, &cxt );
681 switch (dwIoControlCode)
683 case VWIN32_DIOC_DOS_IOCTL: /* Call int 21h */
684 case 0x10: /* Int 0x21 call, call it VWIN_DIOC_INT21 ? */
685 case VWIN32_DIOC_DOS_DRIVEINFO: /* Call int 21h 730x */
688 case VWIN32_DIOC_DOS_INT13:
691 case VWIN32_DIOC_DOS_INT25:
694 case VWIN32_DIOC_DOS_INT26:
697 case 0x29: /* Int 0x31 call, call it VWIN_DIOC_INT31 ? */
702 INSTR_CallBuiltinHandler( &cxt, intnum );
703 CONTEXT_2_DIOCRegs( &cxt, pOut );
707 case VWIN32_DIOC_SIMCTRLC:
708 FIXME( "Control VWIN32_DIOC_SIMCTRLC not implemented\n");
713 FIXME( "Unknown Control %ld\n", dwIoControlCode);
721 /* this is the main multimedia device loader */
722 static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode,
723 LPVOID lpvInBuffer, DWORD cbInBuffer,
724 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
725 LPDWORD lpcbBytesReturned,
726 LPOVERLAPPED lpOverlapped)
728 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
730 lpvInBuffer,cbInBuffer,
731 lpvOutBuffer,cbOutBuffer,
735 switch (dwIoControlCode) {
738 *(DWORD*)lpvOutBuffer=0;
739 *lpcbBytesReturned=4;
744 /* this is used by some Origin games */
745 static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode,
746 LPVOID lpvInBuffer, DWORD cbInBuffer,
747 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
748 LPDWORD lpcbBytesReturned,
749 LPOVERLAPPED lpOverlapped)
751 switch (dwIoControlCode) {
752 case 1: /* version */
753 *(LPDWORD)lpvOutBuffer = 0x20004; /* WC SecretOps */
755 case 9: /* debug output */
756 ERR("MONODEBG: %s\n",debugstr_a(lpvInBuffer));
759 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
761 lpvInBuffer,cbInBuffer,
762 lpvOutBuffer,cbOutBuffer,
772 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode,
773 LPVOID lpvInBuffer, DWORD cbInBuffer,
774 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
775 LPDWORD lpcbBytesReturned,
776 LPOVERLAPPED lpOverlapped)
778 switch (dwIoControlCode) {
779 case 0x0000: /* PCCARD_Get_Version */
780 case 0x0001: /* PCCARD_Card_Services */
782 FIXME( "(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
784 lpvInBuffer,cbInBuffer,
785 lpvOutBuffer,cbOutBuffer,
794 static BOOL DeviceIo_HASP(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
795 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
796 LPDWORD lpcbBytesReturned,
797 LPOVERLAPPED lpOverlapped)
800 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
802 lpvInBuffer,cbInBuffer,
803 lpvOutBuffer,cbOutBuffer,
810 typedef UCHAR (WINAPI *NetbiosFunc)(LPVOID);
812 static BOOL DeviceIo_NetBIOS(DWORD dwIoControlCode,
813 LPVOID lpvInBuffer, DWORD cbInBuffer,
814 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
815 LPDWORD lpcbBytesReturned,
816 LPOVERLAPPED lpOverlapped)
818 static HMODULE netapi;
819 static NetbiosFunc pNetbios;
821 if (dwIoControlCode != 256)
823 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
825 lpvInBuffer,cbInBuffer,
826 lpvOutBuffer,cbOutBuffer,
834 if (!netapi) netapi = LoadLibraryA("netapi32.dll");
835 if (netapi) pNetbios = (NetbiosFunc)GetProcAddress(netapi, "Netbios");
839 pNetbios(lpvInBuffer);
846 static BOOL DeviceIo_DHCP(DWORD dwIoControlCode, LPVOID lpvInBuffer,
848 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
849 LPDWORD lpcbBytesReturned,
850 LPOVERLAPPED lpOverlapped)
854 switch (dwIoControlCode) {
857 /* since IpReleaseAddress/IpRenewAddress are not implemented, say there
858 * are no DHCP adapters
860 error = ERROR_FILE_NOT_FOUND;
864 /* FIXME: don't know what this means */
866 if (lpcbBytesReturned)
867 *lpcbBytesReturned = sizeof(DWORD);
868 if (lpvOutBuffer && cbOutBuffer >= 4)
870 *(LPDWORD)lpvOutBuffer = 0;
874 error = ERROR_BUFFER_OVERFLOW;
878 FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
880 lpvInBuffer,cbInBuffer,
881 lpvOutBuffer,cbOutBuffer,
884 error = ERROR_NOT_SUPPORTED;
889 return error == NO_ERROR;
892 typedef DWORD (WINAPI *GetNetworkParamsFunc)(PFIXED_INFO, PDWORD);
893 typedef DWORD (WINAPI *GetAdaptersInfoFunc)(PIP_ADAPTER_INFO, PDWORD);
895 typedef struct _nbtInfo
905 #define MAX_NBT_ENTRIES 7
907 typedef struct _nbtTable
910 nbtInfo table[MAX_NBT_ENTRIES];
917 static BOOL DeviceIo_VNB(DWORD dwIoControlCode,
918 LPVOID lpvInBuffer, DWORD cbInBuffer,
919 LPVOID lpvOutBuffer, DWORD cbOutBuffer,
920 LPDWORD lpcbBytesReturned,
921 LPOVERLAPPED lpOverlapped)
923 static HMODULE iphlpapi;
924 static GetNetworkParamsFunc pGetNetworkParams;
925 static GetAdaptersInfoFunc pGetAdaptersInfo;
928 switch (dwIoControlCode)
931 if (lpcbBytesReturned)
932 *lpcbBytesReturned = sizeof(nbtTable);
933 if (!lpvOutBuffer || cbOutBuffer < sizeof(nbtTable))
934 error = ERROR_BUFFER_OVERFLOW;
937 nbtTable *info = (nbtTable *)lpvOutBuffer;
939 memset(info, 0, sizeof(nbtTable));
942 iphlpapi = LoadLibraryA("iphlpapi.dll");
943 pGetNetworkParams = (GetNetworkParamsFunc)GetProcAddress(iphlpapi,"GetNetworkParams");
944 pGetAdaptersInfo = (GetAdaptersInfoFunc)GetProcAddress(iphlpapi, "GetAdaptersInfo");
950 error = pGetNetworkParams(NULL, &size);
951 if (ERROR_BUFFER_OVERFLOW == error)
953 PFIXED_INFO fixedInfo = (PFIXED_INFO)HeapAlloc(
954 GetProcessHeap(), 0, size);
956 error = pGetNetworkParams(fixedInfo, &size);
957 if (NO_ERROR == error)
959 info->nodeType = (WORD)fixedInfo->NodeType;
960 info->scopeLen = min(strlen(fixedInfo->ScopeId) + 1,
961 sizeof(info->scope) - 2);
962 memcpy(info->scope + 1, fixedInfo->ScopeId,
964 info->scope[info->scopeLen + 1] = '\0';
966 /* convert into L2-encoded version */
969 for (ptr = info->scope + 1; *ptr &&
970 ptr - info->scope < sizeof(info->scope); )
972 for (lenPtr = ptr - 1, *lenPtr = 0;
973 *ptr && *ptr != '.' &&
974 ptr - info->scope < sizeof(info->scope);
980 /* could set DNS servers here too, but since
981 * ipconfig.exe and winipcfg.exe read these from the
982 * registry, there's no point */
985 HeapFree(GetProcessHeap(), 0, fixedInfo);
988 error = pGetAdaptersInfo(NULL, &size);
989 if (ERROR_BUFFER_OVERFLOW == error)
991 PIP_ADAPTER_INFO adapterInfo = (PIP_ADAPTER_INFO)
992 HeapAlloc(GetProcessHeap(), 0, size);
994 error = pGetAdaptersInfo(adapterInfo, &size);
995 if (NO_ERROR == error)
997 PIP_ADAPTER_INFO ptr = adapterInfo;
999 for (ptr = adapterInfo; ptr && info->numEntries <
1000 MAX_NBT_ENTRIES; ptr = ptr->Next)
1005 ptr->IpAddressList.IpAddress.String);
1006 if (addr != 0 && addr != INADDR_NONE)
1007 info->table[info->numEntries].ip =
1010 ptr->PrimaryWinsServer.IpAddress.String);
1011 if (addr != 0 && addr != INADDR_NONE)
1012 info->table[info->numEntries].winsPrimary
1015 ptr->SecondaryWinsServer.IpAddress.String);
1016 if (addr != 0 && addr != INADDR_NONE)
1017 info->table[info->numEntries].winsSecondary
1023 HeapFree(GetProcessHeap(), 0, adapterInfo);
1027 error = GetLastError();
1032 /* nbtstat.exe uses this, but the return seems to be a bunch of
1033 * pointers, so it's not so easy to reverse engineer. Fall through
1034 * to unimplemented...
1037 FIXME( "Unimplemented control %ld for VxD device VNB\n",
1039 error = ERROR_NOT_SUPPORTED;
1043 SetLastError(error);
1044 return error == NO_ERROR;