VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/Monitor/USBMonFlt.cpp@ 31896

最後變更 在這個檔案從31896是 31896,由 vboxsync 提交於 15 年 前

export the VBoxUSB host driver to OSE

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 34.2 KB
 
1/** @file
2 * VBox host drivers - USB drivers - Win32 USB monitor driver
3 */
4
5/*
6 * Copyright (C) 2006-2007 Oracle Corporation
7 *
8 * Oracle Corporation confidential
9 * All rights reserved
10 */
11
12
13/*******************************************************************************
14* Header Files *
15*******************************************************************************/
16#include "USBMon.h"
17#include <VBox/cdefs.h>
18#include <VBox/types.h>
19#include <iprt/process.h>
20#include <iprt/assert.h>
21#include <VBox/sup.h>
22
23#include <VBox/log.h>
24#include <iprt/assert.h>
25#include <stdio.h>
26
27#pragma warning(disable : 4200)
28#include "usbdi.h"
29#pragma warning(default : 4200)
30#include "usbdlib.h"
31#include "VBoxUSBFilterMgr.h"
32#include <VBox/usblib.h>
33#include <devguid.h>
34
35/*
36 * Note: Must match the VID & PID in the USB driver .inf file!!
37 */
38/*
39 BusQueryDeviceID USB\Vid_80EE&Pid_CAFE
40 BusQueryInstanceID 2
41 BusQueryHardwareIDs USB\Vid_80EE&Pid_CAFE&Rev_0100
42 BusQueryHardwareIDs USB\Vid_80EE&Pid_CAFE
43 BusQueryCompatibleIDs USB\Class_ff&SubClass_00&Prot_00
44 BusQueryCompatibleIDs USB\Class_ff&SubClass_00
45 BusQueryCompatibleIDs USB\Class_ff
46*/
47
48#define szBusQueryDeviceId L"USB\\Vid_80EE&Pid_CAFE"
49#define szBusQueryHardwareIDs L"USB\\Vid_80EE&Pid_CAFE&Rev_0100\0USB\\Vid_80EE&Pid_CAFE\0\0"
50#define szBusQueryCompatibleIDs L"USB\\Class_ff&SubClass_00&Prot_00\0USB\\Class_ff&SubClass_00\0USB\\Class_ff\0\0"
51
52#define szDeviceTextDescription L"VirtualBox USB"
53
54/* Possible USB bus driver names. */
55static LPWSTR lpszStandardControllerName[1] =
56{
57 L"\\Driver\\usbhub",
58};
59
60#define MAX_ATTACHED_USB_DEVICES 64
61
62typedef struct
63{
64 bool fAttached, fCaptured;
65 PDEVICE_OBJECT Pdo;
66 uint16_t idVendor;
67 uint16_t idProduct;
68 uint16_t bcdDevice;
69 uint8_t bClass;
70 uint8_t bSubClass;
71 uint8_t bProtocol;
72 char szSerial[MAX_USB_SERIAL_STRING];
73 char szMfgName[MAX_USB_SERIAL_STRING];
74 char szProduct[MAX_USB_SERIAL_STRING];
75} FLTUSB_DEVICE, *PFLTUSB_DEVICE;
76
77/* Device driver instance data */
78typedef struct
79{
80 LONG cUSBDevices;
81 LONG CaptureCount;
82
83 LONG cUSBStateChange;
84
85 KSPIN_LOCK lock;
86
87 FLTUSB_DEVICE USBDevice[MAX_ATTACHED_USB_DEVICES];
88
89 /* Set to force grabbing of newly arrived devices */
90 bool fForceGrab;
91 /* Set to disable all filters */
92 bool fDisableFilters;
93
94} DRVINSTANCE, *PDRVINSTANCE;
95
96DRVINSTANCE DrvInstance = {0};
97
98/* Forward declarations. */
99NTSTATUS VBoxUSBGetDeviceDescription(PDEVICE_OBJECT pDevObj, USHORT *pusVendorId, USHORT *pusProductId, USHORT *pusRevision);
100NTSTATUS VBoxUSBGetDeviceIdStrings(PDEVICE_OBJECT pDevObj, PFLTUSB_DEVICE pFltDev);
101
102#define ACQUIRE_LOCK() \
103 KIRQL oldIrql; \
104 KeAcquireSpinLock(&DrvInstance.lock, &oldIrql);
105
106#define RELEASE_LOCK() \
107 KeReleaseSpinLock(&DrvInstance.lock, oldIrql);
108
109
110NTSTATUS _stdcall VBoxUSBInit()
111{
112 memset(&DrvInstance, 0, sizeof(DrvInstance));
113 KeInitializeSpinLock(&DrvInstance.lock);
114 VBoxUSBFilterInit();
115 return STATUS_SUCCESS;
116}
117
118NTSTATUS _stdcall VBoxUSBTerm()
119{
120 VBoxUSBFilterTerm();
121 return STATUS_SUCCESS;
122}
123
124
125/**
126 * Device I/O Control entry point.
127 *
128 * @param pDevObj Device object.
129 * @param pIrp Request packet.
130 */
131NTSTATUS _stdcall VBoxUSBDispatchIO(PDEVICE_OBJECT DeviceObject, PIRP Irp)
132{
133 PIO_STACK_LOCATION irpStack;
134 NTSTATUS status;
135 ULONG info = 0;
136 PVOID ioBuffer;
137 ULONG inputBufferLength;
138 ULONG outputBufferLength;
139
140 status = STATUS_SUCCESS;
141 Irp->IoStatus.Information = 0;
142 irpStack = IoGetCurrentIrpStackLocation (Irp);
143
144 ioBuffer = Irp->AssociatedIrp.SystemBuffer;
145 inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
146 outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
147
148 switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
149 {
150 case SUPUSBFLT_IOCTL_USB_CHANGE:
151 {
152 PUSBSUP_USB_CHANGE pOut = (PUSBSUP_USB_CHANGE)ioBuffer;
153
154 if (!ioBuffer || outputBufferLength != sizeof(*pOut) || inputBufferLength != 0)
155 {
156 AssertMsgFailed(("SUPUSBFLT_IOCTL_USB_CHANGE: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
157 inputBufferLength, 0, outputBufferLength, sizeof(*pOut)));
158 status = STATUS_INVALID_PARAMETER;
159 break;
160 }
161 Assert(sizeof(DrvInstance.cUSBStateChange) == sizeof(uint32_t));
162
163//// DebugPrint(("SUPUSBFLT_IOCTL_USB_CHANGE -> %d\n", DrvInstance.cUSBStateChange));
164 pOut->cUSBStateChange = DrvInstance.cUSBStateChange;
165
166 info = sizeof(*pOut);
167 break;
168 }
169
170 case SUPUSBFLT_IOCTL_GET_NUM_DEVICES:
171 {
172 PUSBSUP_GETNUMDEV pOut = (PUSBSUP_GETNUMDEV)ioBuffer;
173
174 if (!ioBuffer || outputBufferLength != sizeof(*pOut) || inputBufferLength != 0)
175 {
176 AssertMsgFailed(("SUPUSBFLT_IOCTL_GET_NUM_DEVICES: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
177 inputBufferLength, 0, outputBufferLength, sizeof(*pOut)));
178 status = STATUS_INVALID_PARAMETER;
179 break;
180 }
181 DebugPrint(("SUPUSBFLT_IOCTL_GET_NUM_DEVICES -> %d devices\n", DrvInstance.cUSBDevices));
182 pOut->cUSBDevices = DrvInstance.cUSBDevices;
183 info = sizeof(*pOut);
184 break;
185 }
186
187 case SUPUSBFLT_IOCTL_CAPTURE_DEVICE:
188 {
189 PUSBSUP_CAPTURE pIn = (PUSBSUP_CAPTURE)ioBuffer;
190
191 DebugPrint(("SUPUSBFLT_IOCTL_CAPTURE_DEVICE\n"));
192 if (!ioBuffer || inputBufferLength != sizeof(*pIn) || outputBufferLength != 0)
193 {
194 AssertMsgFailed(("SUPUSBFLT_IOCTL_CAPTURE_DEVICE: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
195 inputBufferLength, sizeof(*pIn), outputBufferLength, 0));
196 status = STATUS_INVALID_PARAMETER;
197 break;
198 }
199 status = VBoxUSBGrabDevice(pIn->usVendorId, pIn->usProductId, pIn->usRevision);
200 break;
201 }
202
203 case SUPUSBFLT_IOCTL_RELEASE_DEVICE:
204 {
205 PUSBSUP_RELEASE pIn = (PUSBSUP_RELEASE)ioBuffer;
206
207 DebugPrint(("SUPUSBFLT_IOCTL_RELEASE_DEVICE\n"));
208 if (!ioBuffer || inputBufferLength != sizeof(*pIn) || outputBufferLength != 0)
209 {
210 AssertMsgFailed(("SUPUSBFLT_IOCTL_RELEASE_DEVICE: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
211 inputBufferLength, sizeof(*pIn), outputBufferLength, 0));
212 status = STATUS_INVALID_PARAMETER;
213 break;
214 }
215 status = VBoxUSBReleaseDevice(pIn->usVendorId, pIn->usProductId, pIn->usRevision);
216 break;
217 }
218
219 case SUPUSBFLT_IOCTL_GET_VERSION:
220 {
221 PUSBSUP_VERSION pOut = (PUSBSUP_VERSION)ioBuffer;
222
223 DebugPrint(("SUPUSBFLT_IOCTL_GET_VERSION\n"));
224 if (!ioBuffer || outputBufferLength != sizeof(*pOut) || inputBufferLength != 0)
225 {
226 AssertMsgFailed(("SUPUSBFLT_IOCTL_GET_VERSION: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
227 inputBufferLength, 0, outputBufferLength, sizeof(*pOut)));
228 status = STATUS_INVALID_PARAMETER;
229 break;
230 }
231 pOut->u32Major = USBMON_MAJOR_VERSION;
232 pOut->u32Minor = USBMON_MINOR_VERSION;
233 info = sizeof(*pOut);
234 break;
235 }
236
237 case SUPUSBFLT_IOCTL_ADD_FILTER:
238 {
239 PUSBFILTER pFilter = (PUSBFILTER)ioBuffer;
240 PUSBSUP_FLTADDOUT pOut = (PUSBSUP_FLTADDOUT)ioBuffer;
241 RTPROCESS pid = RTProcSelf();
242 uintptr_t uId = 0;
243
244 /* Validate input. */
245 if (RT_UNLIKELY(!ioBuffer || inputBufferLength != sizeof(*pFilter) || outputBufferLength != sizeof(*pOut)))
246 {
247 AssertMsgFailed(("SUPUSBFLT_IOCTL_ADD_FILTER: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
248 inputBufferLength, sizeof(pFilter), outputBufferLength, 0));
249 status = STATUS_INVALID_PARAMETER;
250 break;
251 }
252
253 /* Log the filter details. */
254 DebugPrint(("SUPUSBFLT_IOCTL_ADD_FILTER %s %s %s\n",
255 USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) : "<null>",
256 USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) : "<null>",
257 USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) : "<null>"));
258#ifdef DEBUG
259 DebugPrint(("VBoxUSBClient::addFilter: idVendor=%#x idProduct=%#x bcdDevice=%#x bDeviceClass=%#x bDeviceSubClass=%#x bDeviceProtocol=%#x bBus=%#x bPort=%#x\n",
260 USBFilterGetNum(pFilter, USBFILTERIDX_VENDOR_ID),
261 USBFilterGetNum(pFilter, USBFILTERIDX_PRODUCT_ID),
262 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_REV),
263 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_CLASS),
264 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_SUB_CLASS),
265 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_PROTOCOL),
266 USBFilterGetNum(pFilter, USBFILTERIDX_BUS),
267 USBFilterGetNum(pFilter, USBFILTERIDX_PORT)));
268#endif
269
270 /* We can't get the bus/port numbers. Ignore them while matching. */
271 USBFilterSetMustBePresent(pFilter, USBFILTERIDX_BUS, false);
272 USBFilterSetMustBePresent(pFilter, USBFILTERIDX_PORT, false);
273
274 /* Add the filter. */
275 pOut->rc = VBoxUSBFilterAdd(pFilter, pid, &uId);
276 pOut->uId = uId;
277
278 info = sizeof(*pOut);
279 break;
280 }
281
282 case SUPUSBFLT_IOCTL_REMOVE_FILTER:
283 {
284 uintptr_t *pIn = (uintptr_t *)ioBuffer;
285 RTPROCESS pid = RTProcSelf();
286
287 if (!ioBuffer || inputBufferLength != sizeof(*pIn))
288 {
289 AssertMsgFailed(("SUPUSBFLT_IOCTL_REMOVE_FILTER: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
290 inputBufferLength, sizeof(pIn), outputBufferLength, 0));
291 status = STATUS_INVALID_PARAMETER;
292 break;
293 }
294 DebugPrint(("SUPUSBFLT_IOCTL_REMOVE_FILTER %x\n", *pIn));
295 VBoxUSBFilterRemove(pid, *pIn);
296 break;
297 }
298
299 default:
300 status = STATUS_INVALID_PARAMETER;
301 break;
302 }
303 Irp->IoStatus.Information = info;
304
305 return status;
306}
307
308NTSTATUS _stdcall VBoxUSBCreate()
309{
310 Assert(sizeof(DrvInstance.CaptureCount) == sizeof(LONG));
311 InterlockedIncrement(&DrvInstance.CaptureCount);
312 return STATUS_SUCCESS;
313}
314
315NTSTATUS _stdcall VBoxUSBClose()
316{
317 ACQUIRE_LOCK();
318 Assert(sizeof(DrvInstance.CaptureCount) == sizeof(LONG));
319 InterlockedDecrement(&DrvInstance.CaptureCount);
320 Assert(DrvInstance.CaptureCount >= 0);
321 VBoxUSBFilterRemoveOwner(RTProcSelf());
322
323 if (DrvInstance.CaptureCount == 0)
324 {
325 DrvInstance.cUSBDevices = 0;
326 }
327 RELEASE_LOCK();
328 return STATUS_SUCCESS;
329}
330
331
332unsigned myxdigit(char c)
333{
334 if (c >= 'a' && c <= 'z')
335 c = c - 'a' + 'A';
336 if (c >= '0' && c <= '9')
337 return c - '0';
338 if (c >= 'A' && c <= 'F')
339 return c - 'A' + 10;
340 return 0;
341}
342
343#if 1
344bool VBoxMatchFilter(PDEVICE_OBJECT pdo)
345{
346 USBFILTER Device;
347 int index;
348 PFLTUSB_DEVICE USBDevice;
349
350 if (DrvInstance.fForceGrab)
351 {
352 DebugPrint(("VBoxMatchFilter -> Force Grab -> TRUE\n"));
353 return true;
354 }
355 if (DrvInstance.fDisableFilters)
356 {
357 DebugPrint(("VBoxMatchFilter -> filters disabled -> FALSE\n"));
358 return false;
359 }
360
361 index = VBoxUSBIsKnownPDO(pdo);
362 if (index == -1)
363 {
364 DebugPrint(("VBoxMatchFilter -> unknown PDO -> FALSE\n"));
365 return false;
366 }
367 ACQUIRE_LOCK();
368
369 USBDevice = &DrvInstance.USBDevice[index];
370 USBFilterInit(&Device, USBFILTERTYPE_CAPTURE);
371
372 USBFilterSetNumExact(&Device, USBFILTERIDX_VENDOR_ID, USBDevice->idVendor, true);
373 USBFilterSetNumExact(&Device, USBFILTERIDX_PRODUCT_ID, USBDevice->idProduct, true);
374 USBFilterSetNumExact(&Device, USBFILTERIDX_DEVICE_REV, USBDevice->bcdDevice, true);
375 USBFilterSetNumExact(&Device, USBFILTERIDX_DEVICE_CLASS, USBDevice->bClass, true);
376 USBFilterSetNumExact(&Device, USBFILTERIDX_DEVICE_SUB_CLASS, USBDevice->bSubClass, true);
377 USBFilterSetNumExact(&Device, USBFILTERIDX_DEVICE_PROTOCOL, USBDevice->bProtocol, true);
378 USBFilterSetStringExact(&Device, USBFILTERIDX_MANUFACTURER_STR, USBDevice->szMfgName, true);
379 USBFilterSetStringExact(&Device, USBFILTERIDX_PRODUCT_STR, USBDevice->szProduct, true);
380 USBFilterSetStringExact(&Device, USBFILTERIDX_SERIAL_NUMBER_STR, USBDevice->szSerial, true);
381
382 /* Run filters on the thing. */
383 uintptr_t uId = 0;
384 RTPROCESS Owner = VBoxUSBFilterMatch(&Device, &uId);
385 USBFilterDelete(&Device);
386 if (Owner == NIL_RTPROCESS)
387 {
388 RELEASE_LOCK();
389 return false;
390 }
391 DebugPrint(("VBoxMatchFilter: HIT\n"));
392 RELEASE_LOCK();
393 return true;
394}
395#else
396bool VBoxMatchFilter(WCHAR *pszDeviceId)
397{
398 //#define szBusQueryDeviceId L"USB\\Vid_80EE&Pid_CAFE"
399 uint16_t pId;
400 uint16_t vId;
401// char szRevision[4];
402#ifdef DEBUG
403 WCHAR *pszOrgDeviceId = pszDeviceId;
404#endif
405 USBFILTER Device;
406
407 if (DrvInstance.fForceGrab)
408 {
409 DebugPrint(("VBoxMatchFilter -> Force Grab -> TRUE\n"));
410 return true;
411 }
412 if (DrvInstance.fDisableFilters)
413 {
414 DebugPrint(("VBoxMatchFilter -> filters disabled -> FALSE\n"));
415 return false;
416 }
417
418 if (RtlCompareMemory(pszDeviceId, L"USB\\", 4*sizeof(WCHAR)) != 4*sizeof(WCHAR))
419 return false;
420
421 while(*pszDeviceId != 0 && *pszDeviceId != '_')
422 pszDeviceId++;
423 if(*pszDeviceId == 0)
424 return false;
425 pszDeviceId++;
426
427 /* Vid_ skipped */
428 vId = myxdigit((CHAR)pszDeviceId[0]) << 12
429 | myxdigit((CHAR)pszDeviceId[1]) << 8
430 | myxdigit((CHAR)pszDeviceId[2]) << 4
431 | myxdigit((CHAR)pszDeviceId[3]) << 0;
432
433 while(*pszDeviceId != 0 && *pszDeviceId != '_')
434 pszDeviceId++;
435 if(*pszDeviceId == 0)
436 return false;
437 pszDeviceId++;
438
439 /* Pid_ skipped */
440 pId = myxdigit((CHAR)pszDeviceId[0]) << 12
441 | myxdigit((CHAR)pszDeviceId[1]) << 8
442 | myxdigit((CHAR)pszDeviceId[2]) << 4
443 | myxdigit((CHAR)pszDeviceId[3]) << 0;
444
445 ACQUIRE_LOCK();
446
447 USBFilterInit(&Device, USBFILTERTYPE_CAPTURE);
448
449 USBFilterSetNumExact(&Device, USBFILTERIDX_VENDOR_ID, vId, true);
450 USBFilterSetNumExact(&Device, USBFILTERIDX_PRODUCT_ID, pId, true);
451
452 /* Run filters on the thing. */
453 uintptr_t uId = 0;
454 RTPROCESS Owner = VBoxUSBFilterMatch(&Device, &uId);
455 USBFilterDelete(&Device);
456 if (Owner == NIL_RTPROCESS)
457 {
458 RELEASE_LOCK();
459 return false;
460 }
461 DebugPrint(("VBoxMatchFilter: HIT\n"));
462 RELEASE_LOCK();
463 return true;
464}
465#endif
466
467bool VBoxUSBAddDevice(PDEVICE_OBJECT pdo)
468{
469 if (VBoxUSBIsKnownPDO(pdo) != -1)
470 return true;
471
472 ACQUIRE_LOCK()
473 for (int i=0;i<MAX_ATTACHED_USB_DEVICES;i++)
474 {
475 if (DrvInstance.USBDevice[i].fAttached == false)
476 {
477 DebugPrint(("VBoxUSBAddDevice %p\n", pdo));
478 DrvInstance.USBDevice[i].fAttached = true;
479 DrvInstance.USBDevice[i].Pdo = pdo;
480 DrvInstance.USBDevice[i].fCaptured = false;
481 Assert(DrvInstance.cUSBDevices <= MAX_ATTACHED_USB_DEVICES);
482
483 DebugPrint(("Signal USB change ADD\n"));
484 RELEASE_LOCK();
485 /* There doesn't appear to be any good way to get device information
486 * from Windows. Reading its descriptor should do the trick though.
487 */
488 VBoxUSBGetDeviceIdStrings(pdo, &DrvInstance.USBDevice[i]);
489
490 InterlockedIncrement(&DrvInstance.cUSBStateChange);
491 return true;
492 }
493 }
494 RELEASE_LOCK();
495 return false;
496}
497
498int VBoxUSBIsKnownPDO(PDEVICE_OBJECT pdo)
499{
500 Assert(pdo);
501 ACQUIRE_LOCK();
502 for (int i=0;i<MAX_ATTACHED_USB_DEVICES;i++)
503 {
504 if (DrvInstance.USBDevice[i].Pdo == pdo)
505 {
506 RELEASE_LOCK();
507 return i;
508 }
509 }
510 RELEASE_LOCK();
511 return -1;
512}
513
514bool VBoxUSBRemoveDevice(PDEVICE_OBJECT pdo)
515{
516 ACQUIRE_LOCK();
517
518 for (int i=0;i<MAX_ATTACHED_USB_DEVICES;i++)
519 {
520 if (DrvInstance.USBDevice[i].Pdo == pdo)
521 {
522 DebugPrint(("VBoxUSBRemoveDevice %p\n", pdo));
523 DrvInstance.USBDevice[i].fAttached = false;
524 DrvInstance.USBDevice[i].Pdo = NULL;
525
526 if (DrvInstance.USBDevice[i].fCaptured == true)
527 {
528 InterlockedDecrement(&DrvInstance.cUSBDevices);
529 Assert(DrvInstance.cUSBDevices >= 0);
530
531 DrvInstance.USBDevice[i].fCaptured = false;
532 }
533
534 DebugPrint(("Signal USB change REMOVE\n"));
535 InterlockedIncrement(&DrvInstance.cUSBStateChange);
536
537 RELEASE_LOCK();
538 return true;
539 }
540 }
541 RELEASE_LOCK();
542 return false;
543}
544
545bool VBoxUSBCaptureDevice(PDEVICE_OBJECT pdo)
546{
547 Assert(DrvInstance.CaptureCount);
548 if (DrvInstance.CaptureCount == 0)
549 return false;
550
551 ACQUIRE_LOCK();
552 for (int i=0;i<MAX_ATTACHED_USB_DEVICES;i++)
553 {
554 if ( DrvInstance.USBDevice[i].Pdo == pdo
555 && DrvInstance.USBDevice[i].fCaptured == false)
556 {
557 DebugPrint(("VBoxUSBCaptureDevice %p\n", pdo));
558
559 Assert(DrvInstance.USBDevice[i].fAttached);
560
561 DrvInstance.USBDevice[i].fCaptured = true;
562 InterlockedIncrement(&DrvInstance.cUSBDevices);
563 RELEASE_LOCK();
564 return true;
565 }
566 }
567 RELEASE_LOCK();
568 return false;
569}
570
571void VBoxUSBDeviceArrived(PDEVICE_OBJECT pdo)
572{
573 /* If we manually release a device, then all filters will be temporarily disabled; Enable them again when the
574 * device has been started.
575 */
576 DrvInstance.fDisableFilters = false;
577
578 /* If we manually capture a device, we are forced to grab the next device that arrives. Disable this mode here */
579 DrvInstance.fForceGrab = false;
580 return;
581}
582
583bool VBoxUSBDeviceIsCaptured(PDEVICE_OBJECT pdo)
584{
585 bool ret;
586
587 ACQUIRE_LOCK();
588 for (int i=0;i<MAX_ATTACHED_USB_DEVICES;i++)
589 {
590 if (DrvInstance.USBDevice[i].Pdo == pdo)
591 {
592 ret = DrvInstance.USBDevice[i].fCaptured;
593 RELEASE_LOCK();
594 return ret;
595 }
596 }
597 RELEASE_LOCK();
598 return false;
599}
600
601/**
602 * Send USB ioctl
603 *
604 * @returns NT Status
605 * @param pDevObj USB device pointer
606 * @param control_code ioctl
607 * @param buffer Descriptor buffer
608 * @param size size of buffer
609 */
610NTSTATUS VBoxUSBSendIOCTL(PDEVICE_OBJECT pDevObj, ULONG control_code, void *buffer, uint32_t size)
611{
612 IO_STATUS_BLOCK io_status;
613 KEVENT event;
614 NTSTATUS status;
615 IRP *pIrp;
616 PIO_STACK_LOCATION stackloc;
617
618 KeInitializeEvent(&event, NotificationEvent, FALSE);
619
620 pIrp = IoBuildDeviceIoControlRequest(control_code, pDevObj, NULL, 0, NULL, 0, TRUE, &event, &io_status);
621 if (!pIrp)
622 {
623 AssertMsgFailed(("IoBuildDeviceIoControlRequest failed!!\n"));
624 return STATUS_INSUFFICIENT_RESOURCES;
625 }
626
627 /* Get the next stack location as that is used for the new irp */
628 stackloc = IoGetNextIrpStackLocation(pIrp);
629 stackloc->Parameters.Others.Argument1 = buffer;
630 stackloc->Parameters.Others.Argument2 = NULL;
631
632 status = IoCallDriver(pDevObj, pIrp);
633 if (status == STATUS_PENDING)
634 {
635 DebugPrint(("IoCallDriver returned STATUS_PENDING!!\n"));
636 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
637 status = io_status.Status;
638 }
639
640 DebugPrint(("IoCallDriver returned %x\n", status));
641
642 return status;
643}
644
645/**
646 * Get USB descriptor
647 *
648 * @returns NT Status
649 * @param pDevObj USB device pointer
650 * @param buffer Descriptor buffer
651 * @param size size of buffer
652 * @param type descriptor type
653 * @param index descriptor index
654 * @param language_id descriptor language id
655 */
656NTSTATUS VBoxUSBGetDescriptor(PDEVICE_OBJECT pDevObj, void *buffer, int size, int type, int index, int language_id)
657{
658 NTSTATUS rc;
659 PURB urb;
660
661 urb = (PURB)ExAllocatePool(NonPagedPool,sizeof(URB));
662 if(urb == NULL)
663 {
664 DebugPrint(("Failed to alloc mem for urb\n"));
665 return STATUS_INSUFFICIENT_RESOURCES;
666 }
667 memset(urb, 0, sizeof(*urb));
668
669 urb->UrbHeader.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
670 urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
671 urb->UrbControlDescriptorRequest.TransferBufferLength = size;
672 urb->UrbControlDescriptorRequest.TransferBuffer = buffer;
673 urb->UrbControlDescriptorRequest.Index = (UCHAR)index;
674 urb->UrbControlDescriptorRequest.DescriptorType = (UCHAR)type;
675 urb->UrbControlDescriptorRequest.LanguageId = (USHORT)language_id;
676
677 rc = VBoxUSBSendIOCTL(pDevObj, IOCTL_INTERNAL_USB_SUBMIT_URB, urb, sizeof(*urb));
678#ifdef DEBUG
679 if(!NT_SUCCESS(rc) || !USBD_SUCCESS(urb->UrbHeader.Status))
680 DebugPrint(("VBoxUSBGetDescriptor: VBoxUSBSendIOCTL failed with %x (%x)\n", rc, urb->UrbHeader.Status));
681#endif
682
683 ExFreePool(urb);
684 return rc;
685}
686
687/**
688 * Get a valid USB string descriptor language ID (the first ID found).
689 *
690 * @returns NT Status
691 * @param pDevObj USB device pointer
692 * @param lang_id pointer to language id
693 */
694NTSTATUS VBoxUSBGetLangID(PDEVICE_OBJECT pDevObj, int *lang_id)
695{
696 NTSTATUS status;
697 unsigned length;
698 char buffer[MAXIMUM_USB_STRING_LENGTH];
699 PUSB_STRING_DESCRIPTOR pstrdescr = (PUSB_STRING_DESCRIPTOR)&buffer;
700
701 Assert(lang_id);
702 *lang_id = 0;
703
704 length = sizeof(buffer);
705 memset(pstrdescr, 0, length);
706 pstrdescr->bLength = length;
707 pstrdescr->bDescriptorType = USB_STRING_DESCRIPTOR_TYPE;
708
709 status = VBoxUSBGetDescriptor(pDevObj, pstrdescr, length, USB_STRING_DESCRIPTOR_TYPE, 0, 0);
710 if (!NT_SUCCESS(status))
711 {
712 DebugPrint(("VBoxUSBGetLangID: language ID table not present (?)\n"));
713 goto fail;
714 }
715 /* Just grab the first lang ID if available. In 99% cases, it will be US English (0x0409).*/
716 if (pstrdescr->bLength >= sizeof(USB_STRING_DESCRIPTOR))
717 {
718 Assert(sizeof(pstrdescr->bString[0]) == sizeof(uint16_t));
719 *lang_id = pstrdescr->bString[0];
720 status = STATUS_SUCCESS;
721 }
722 else
723 status = STATUS_INVALID_PARAMETER;
724fail:
725 return status;
726}
727
728NTSTATUS VBoxUSBGetStringDescriptor(PDEVICE_OBJECT pDevObj, char *dest, unsigned size, int index, int lang_id)
729{
730 NTSTATUS status;
731 PUSB_STRING_DESCRIPTOR pstrdescr = NULL;
732 unsigned length;
733 UNICODE_STRING ustr;
734 ANSI_STRING astr;
735
736 *dest = '\0';
737 if (index)
738 {
739 /* An entire USB string descriptor is Unicode and can't be longer than 256 bytes.
740 * Hence 128 bytes is enough for an ASCII string.
741 */
742 length = sizeof(USB_STRING_DESCRIPTOR) + MAX_USB_SERIAL_STRING * sizeof(pstrdescr->bString[0]);
743 pstrdescr = (PUSB_STRING_DESCRIPTOR)ExAllocatePool(NonPagedPool, length);
744 if (!pstrdescr)
745 {
746 AssertMsgFailed(("VBoxUSBGetStringDescriptor: ExAllocatePool failed\n"));
747 status = STATUS_INSUFFICIENT_RESOURCES;
748 goto fail;
749 }
750 memset(pstrdescr, 0, length);
751 pstrdescr->bLength = length;
752 pstrdescr->bDescriptorType = USB_STRING_DESCRIPTOR_TYPE;
753
754 status = VBoxUSBGetDescriptor(pDevObj, pstrdescr, length, USB_STRING_DESCRIPTOR_TYPE, index, lang_id);
755 if (!NT_SUCCESS(status))
756 {
757 DebugPrint(("VBoxUSBGetStringDescriptor: requested string not present (?)\n"));
758 status = STATUS_SUCCESS; //not fatal
759 goto fail;
760 }
761 if (pstrdescr->bLength > sizeof(USB_STRING_DESCRIPTOR))
762 {
763 RtlInitUnicodeString(&ustr, pstrdescr->bString);
764 RtlInitAnsiString(&astr, NULL);
765 RtlUnicodeStringToAnsiString(&astr, &ustr, TRUE);
766 strncpy(dest, astr.Buffer, size);
767 RtlFreeAnsiString(&astr);
768 }
769 }
770 status = STATUS_SUCCESS;
771fail:
772 if (pstrdescr)
773 ExFreePool(pstrdescr);
774 return status;
775}
776
777NTSTATUS VBoxUSBGetDeviceIdStrings(PDEVICE_OBJECT pDevObj, PFLTUSB_DEVICE pFltDev)
778{
779 NTSTATUS status;
780 PUSB_DEVICE_DESCRIPTOR devdescr = 0;
781
782 devdescr = (PUSB_DEVICE_DESCRIPTOR)ExAllocatePool(NonPagedPool, sizeof(USB_DEVICE_DESCRIPTOR));
783 if (devdescr == NULL)
784 {
785 DebugPrint(("Failed to alloc mem for urb\n"));
786 status = STATUS_INSUFFICIENT_RESOURCES;
787 goto fail;
788 }
789 memset(devdescr, 0, sizeof(*devdescr));
790
791 status = VBoxUSBGetDescriptor(pDevObj, devdescr, sizeof(*devdescr), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0);
792 if (!NT_SUCCESS(status))
793 {
794 AssertMsgFailed(("VBoxUSBGetDeviceDescription: getting device descriptor failed\n"));
795 goto fail;
796 }
797 DebugPrint(("Device pid=%x vid=%x rev=%x\n", devdescr->idVendor, devdescr->idProduct, devdescr->bcdDevice));
798 pFltDev->idVendor = devdescr->idVendor;
799 pFltDev->idProduct = devdescr->idProduct;
800 pFltDev->bcdDevice = devdescr->bcdDevice;
801 pFltDev->bClass = devdescr->bDeviceClass;
802 pFltDev->bSubClass = devdescr->bDeviceSubClass;
803 pFltDev->bProtocol = devdescr->bDeviceProtocol;
804 pFltDev->szSerial[0] = 0;
805 pFltDev->szMfgName[0] = 0;
806 pFltDev->szProduct[0] = 0;
807
808 /* If there are no strings, don't even try to get any string descriptors. */
809 if (devdescr->iSerialNumber || devdescr->iManufacturer || devdescr->iProduct)
810 {
811 int langId;
812
813 status = VBoxUSBGetLangID(pDevObj, &langId);
814 if (!NT_SUCCESS(status))
815 {
816 AssertMsgFailed(("VBoxUSBGetDeviceDescription: reading language ID failed\n"));
817 goto fail;
818 }
819 status = VBoxUSBGetStringDescriptor(pDevObj, pFltDev->szSerial, sizeof(pFltDev->szSerial), devdescr->iSerialNumber, langId);
820 if (!NT_SUCCESS(status))
821 {
822 AssertMsgFailed(("VBoxUSBGetDeviceDescription: reading serial number failed\n"));
823 goto fail;
824 }
825 status = VBoxUSBGetStringDescriptor(pDevObj, pFltDev->szMfgName, sizeof(pFltDev->szMfgName), devdescr->iManufacturer, langId);
826 if (!NT_SUCCESS(status))
827 {
828 AssertMsgFailed(("VBoxUSBGetDeviceDescription: reading manufacturer name failed\n"));
829 goto fail;
830 }
831 status = VBoxUSBGetStringDescriptor(pDevObj, pFltDev->szProduct, sizeof(pFltDev->szProduct), devdescr->iProduct, langId);
832 if (!NT_SUCCESS(status))
833 {
834 AssertMsgFailed(("VBoxUSBGetDeviceDescription: reading product name failed\n"));
835 goto fail;
836 }
837
838 DebugPrint(("VBoxUSBGetStringDescriptor: strings: '%s':'%s':'%s' (lang ID %x)\n",
839 pFltDev->szMfgName, pFltDev->szProduct, pFltDev->szSerial, langId));
840 }
841 status = STATUS_SUCCESS;
842
843fail:
844 if (devdescr)
845 ExFreePool(devdescr);
846 return status;
847}
848
849/**
850 * Get USB device description
851 *
852 * @returns NT Status
853 * @param pDevObj USB device pointer
854 * @param pusVendorId Vendor id (out)
855 * @param pusProductId Product id (out)
856 * @param pusRevision Revision (out)
857 */
858NTSTATUS VBoxUSBGetDeviceDescription(PDEVICE_OBJECT pDevObj, USHORT *pusVendorId, USHORT *pusProductId, USHORT *pusRevision)
859{
860 NTSTATUS status;
861 PUSB_DEVICE_DESCRIPTOR devdescr = 0;
862
863 devdescr = (PUSB_DEVICE_DESCRIPTOR)ExAllocatePool(NonPagedPool,sizeof(USB_DEVICE_DESCRIPTOR));
864 if(devdescr == NULL)
865 {
866 DebugPrint(("Failed to alloc mem for urb\n"));
867 status = STATUS_INSUFFICIENT_RESOURCES;
868 goto fail;
869 }
870 memset(devdescr, 0, sizeof(*devdescr));
871
872 status = VBoxUSBGetDescriptor(pDevObj, devdescr, sizeof(*devdescr), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0);
873 if (!NT_SUCCESS(status))
874 {
875 DebugPrint(("VBoxUSBGetDeviceDescription: getting device descriptor failed\n"));
876 goto fail;
877 }
878 DebugPrint(("Device pid=%x vid=%x rev=%x\n", devdescr->idVendor, devdescr->idProduct, devdescr->bcdDevice));
879 *pusVendorId = devdescr->idVendor;
880 *pusProductId = devdescr->idProduct;
881 *pusRevision = devdescr->bcdDevice;
882
883 ExFreePool(devdescr);
884 return STATUS_SUCCESS;
885
886fail:
887 if (devdescr)
888 ExFreePool(devdescr);
889 return status;
890}
891
892/**
893 * Unplug and replug the specified USB device
894 *
895 * @returns NT status code
896 * @param usVendorId Vendor id
897 * @param usProductId Product id
898 * @param usRevision Revision
899 * @param fCaptured Already captured or not
900 * @param pfReplugged Replugged or not (out)
901 */
902NTSTATUS VBoxUSBReplugDevice(USHORT usVendorId, USHORT usProductId, USHORT usRevision, bool fCaptured, bool *pfReplugged)
903{
904 NTSTATUS status;
905 UNICODE_STRING szStandardControllerName[RT_ELEMENTS(lpszStandardControllerName)];
906
907 DebugPrint(("VBoxUSBReplugDevice: %04X %04X %04X\n", usVendorId, usProductId, usRevision));
908
909 Assert(pfReplugged);
910 *pfReplugged = false;
911
912 for (int i=0;i<RT_ELEMENTS(lpszStandardControllerName);i++)
913 {
914 szStandardControllerName[i].Length = 0;
915 szStandardControllerName[i].MaximumLength = 0;
916 szStandardControllerName[i].Buffer = 0;
917
918 RtlInitUnicodeString(&szStandardControllerName[i], lpszStandardControllerName[i]);
919 }
920
921 for (int i=0;i<16;i++)
922 {
923 char szHubName[32];
924 UNICODE_STRING UnicodeName;
925 ANSI_STRING AnsiName;
926 PDEVICE_OBJECT pHubDevObj;
927 PFILE_OBJECT pHubFileObj;
928
929 sprintf(szHubName, "\\Device\\USBPDO-%d", i);
930
931 UnicodeName.Length = 0;
932 UnicodeName.MaximumLength = 0;
933 UnicodeName.Buffer = 0;
934
935 RtlInitAnsiString(&AnsiName, szHubName);
936 RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE);
937
938 status = IoGetDeviceObjectPointer(&UnicodeName, FILE_READ_DATA, &pHubFileObj, &pHubDevObj);
939 if (status == STATUS_SUCCESS)
940 {
941 DebugPrint(("IoGetDeviceObjectPointer for %s returned %p %p\n", szHubName, pHubDevObj, pHubFileObj));
942
943 if ( pHubDevObj->DriverObject
944 && pHubDevObj->DriverObject->DriverName.Buffer
945 && pHubDevObj->DriverObject->DriverName.Length
946 )
947 {
948 for (int j=0;j<RT_ELEMENTS(lpszStandardControllerName);j++)
949 {
950 if (!RtlCompareUnicodeString(&szStandardControllerName[j], &pHubDevObj->DriverObject->DriverName, TRUE /* case insensitive */))
951 {
952 PDEVICE_RELATIONS pDevRelations = NULL;
953
954 DebugPrint(("Associated driver %wZ -> related dev obj=%p\n", pHubDevObj->DriverObject->DriverName, IoGetRelatedDeviceObject(pHubFileObj)));
955
956 status = VBoxUSBQueryBusRelations(pHubDevObj, pHubFileObj, &pDevRelations);
957 if ( status == STATUS_SUCCESS
958 && pDevRelations)
959 {
960 for (unsigned k=0;k<pDevRelations->Count;k++)
961 {
962 USHORT usPDOVendorId, usPDOProductId, usPDORevision;
963
964 DebugPrint(("Found existing USB PDO %p\n", pDevRelations->Objects[k]));
965 VBoxUSBGetDeviceDescription(pDevRelations->Objects[k], &usPDOVendorId, &usPDOProductId, &usPDORevision);
966
967 if ( VBoxUSBDeviceIsCaptured(pDevRelations->Objects[k]) == fCaptured
968 && usPDOVendorId == usVendorId
969 && usPDOProductId == usProductId
970 && usPDORevision == usRevision)
971 {
972 DebugPrint(("REPLUG device -> \n"));
973 /* Simulate a device replug */
974 status = VBoxUSBSendIOCTL(pDevRelations->Objects[k], IOCTL_INTERNAL_USB_CYCLE_PORT, NULL, 0);
975
976 *pfReplugged = true;
977 }
978 ObDereferenceObject(pDevRelations->Objects[k]);
979 if (*pfReplugged == true)
980 break;
981 }
982 ExFreePool(pDevRelations);
983 }
984 if (*pfReplugged == true)
985 break;
986 }
987 }
988 }
989 ObDereferenceObject(pHubFileObj);
990 }
991 RtlFreeUnicodeString(&UnicodeName);
992 if (*pfReplugged == true)
993 break;
994 }
995
996 return STATUS_SUCCESS;
997}
998
999/**
1000 * Capture specified USB device
1001 *
1002 * @returns NT status code
1003 * @param usVendorId Vendor id
1004 * @param usProductId Product id
1005 * @param usRevision Revision
1006 */
1007NTSTATUS VBoxUSBReleaseDevice(USHORT usVendorId, USHORT usProductId, USHORT usRevision)
1008{
1009 NTSTATUS status;
1010 bool fReplugged;
1011
1012 DebugPrint(("VBoxUSBReleaseDevice\n"));
1013
1014 DrvInstance.fDisableFilters = true;
1015 status = VBoxUSBReplugDevice(usVendorId, usProductId, usRevision, true, &fReplugged);
1016 if ( status != STATUS_SUCCESS
1017 || !fReplugged)
1018 DrvInstance.fDisableFilters = false;
1019 return status;
1020}
1021
1022/**
1023 * Capture specified USB device
1024 *
1025 * @returns NT status code
1026 * @param usVendorId Vendor id
1027 * @param usProductId Product id
1028 * @param usRevision Revision
1029 */
1030NTSTATUS VBoxUSBGrabDevice(USHORT usVendorId, USHORT usProductId, USHORT usRevision)
1031{
1032 NTSTATUS status;
1033 bool fReplugged;
1034
1035 DebugPrint(("VBoxUSBGrabDevice\n"));
1036
1037 DrvInstance.fForceGrab = true;
1038 status = VBoxUSBReplugDevice(usVendorId, usProductId, usRevision, false, &fReplugged);
1039 if ( status != STATUS_SUCCESS
1040 || !fReplugged)
1041 DrvInstance.fForceGrab = false;
1042 return status;
1043}
1044
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette