VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/mon/VBoxUsbFlt.cpp@ 69496

Last change on this file since 69496 was 69496, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 55.1 KB
Line 
1/* $Id: VBoxUsbFlt.cpp 69496 2017-10-28 14:55:58Z vboxsync $ */
2/** @file
3 * VBox USB Monitor Device Filtering functionality
4 */
5/*
6 * Copyright (C) 2011-2017 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26
27/*********************************************************************************************************************************
28* Header Files *
29*********************************************************************************************************************************/
30#include "VBoxUsbMon.h"
31#include "../cmn/VBoxUsbTool.h"
32
33#include <VBox/cdefs.h>
34#include <VBox/types.h>
35#include <iprt/process.h>
36#include <iprt/assert.h>
37#include <VBox/err.h>
38//#include <VBox/sup.h>
39
40#include <iprt/assert.h>
41#include <stdio.h>
42
43#pragma warning(disable : 4200)
44#include "usbdi.h"
45#pragma warning(default : 4200)
46#include "usbdlib.h"
47#include "VBoxUSBFilterMgr.h"
48#include <VBox/usblib.h>
49#include <devguid.h>
50
51/*
52 * Note: Must match the VID & PID in the USB driver .inf file!!
53 */
54/*
55 BusQueryDeviceID USB\Vid_80EE&Pid_CAFE
56 BusQueryInstanceID 2
57 BusQueryHardwareIDs USB\Vid_80EE&Pid_CAFE&Rev_0100
58 BusQueryHardwareIDs USB\Vid_80EE&Pid_CAFE
59 BusQueryCompatibleIDs USB\Class_ff&SubClass_00&Prot_00
60 BusQueryCompatibleIDs USB\Class_ff&SubClass_00
61 BusQueryCompatibleIDs USB\Class_ff
62*/
63
64#define szBusQueryDeviceId L"USB\\Vid_80EE&Pid_CAFE"
65#define szBusQueryHardwareIDs L"USB\\Vid_80EE&Pid_CAFE&Rev_0100\0USB\\Vid_80EE&Pid_CAFE\0\0"
66#define szBusQueryCompatibleIDs L"USB\\Class_ff&SubClass_00&Prot_00\0USB\\Class_ff&SubClass_00\0USB\\Class_ff\0\0"
67
68#define szDeviceTextDescription L"VirtualBox USB"
69
70/* Possible USB bus driver names. */
71static LPWSTR lpszStandardControllerName[1] =
72{
73 L"\\Driver\\usbhub",
74};
75
76/*
77 * state transitions:
78 *
79 * (we are not filtering this device )
80 * ADDED --> UNCAPTURED ------------------------------->-
81 * | |
82 * | (we are filtering this device, | (the device is being
83 * | waiting for our device driver | re-plugged to perform
84 * | to pick it up) | capture-uncapture transition)
85 * |-> CAPTURING -------------------------------->|---> REPLUGGING -----
86 * ^ | (device driver picked | |
87 * | | up the device) | (remove cased | (device is removed
88 * | ->---> CAPTURED ---------------------->| by "real" removal | the device info is removed form the list)
89 * | | |------------------->->--> REMOVED
90 * | | |
91 * |-----------<->---> USED_BY_GUEST ------->|
92 * | |
93 * |------------------------<-
94 *
95 * NOTE: the order of enums DOES MATTER!!
96 * Do not blindly modify!! as the code assumes the state is ordered this way.
97 */
98typedef enum
99{
100 VBOXUSBFLT_DEVSTATE_UNKNOWN = 0,
101 VBOXUSBFLT_DEVSTATE_REMOVED,
102 VBOXUSBFLT_DEVSTATE_REPLUGGING,
103 VBOXUSBFLT_DEVSTATE_ADDED,
104 VBOXUSBFLT_DEVSTATE_UNCAPTURED,
105 VBOXUSBFLT_DEVSTATE_CAPTURING,
106 VBOXUSBFLT_DEVSTATE_CAPTURED,
107 VBOXUSBFLT_DEVSTATE_USED_BY_GUEST,
108 VBOXUSBFLT_DEVSTATE_32BIT_HACK = 0x7fffffff
109} VBOXUSBFLT_DEVSTATE;
110
111typedef struct VBOXUSBFLT_DEVICE
112{
113 LIST_ENTRY GlobalLe;
114 /* auxiliary list to be used for gathering devices to be re-plugged
115 * only thread that puts the device to the REPLUGGING state can use this list */
116 LIST_ENTRY RepluggingLe;
117 /* Owning session. Each matched device has an owning session. */
118 struct VBOXUSBFLTCTX *pOwner;
119 /* filter id - if NULL AND device has an owner - the filter is destroyed */
120 uintptr_t uFltId;
121 /* true iff device is filtered with a one-shot filter */
122 bool fIsFilterOneShot;
123 /* The device state. If the non-owner session is requesting the state while the device is grabbed,
124 * the USBDEVICESTATE_USED_BY_HOST is returned. */
125 VBOXUSBFLT_DEVSTATE enmState;
126 volatile uint32_t cRefs;
127 PDEVICE_OBJECT Pdo;
128 uint16_t idVendor;
129 uint16_t idProduct;
130 uint16_t bcdDevice;
131 uint8_t bClass;
132 uint8_t bSubClass;
133 uint8_t bProtocol;
134 char szSerial[MAX_USB_SERIAL_STRING];
135 char szMfgName[MAX_USB_SERIAL_STRING];
136 char szProduct[MAX_USB_SERIAL_STRING];
137#if 0
138 char szDrvKeyName[512];
139 BOOLEAN fHighSpeed;
140#endif
141} VBOXUSBFLT_DEVICE, *PVBOXUSBFLT_DEVICE;
142
143#define PVBOXUSBFLT_DEVICE_FROM_LE(_pLe) ( (PVBOXUSBFLT_DEVICE)( ((uint8_t*)(_pLe)) - RT_OFFSETOF(VBOXUSBFLT_DEVICE, GlobalLe) ) )
144#define PVBOXUSBFLT_DEVICE_FROM_REPLUGGINGLE(_pLe) ( (PVBOXUSBFLT_DEVICE)( ((uint8_t*)(_pLe)) - RT_OFFSETOF(VBOXUSBFLT_DEVICE, RepluggingLe) ) )
145#define PVBOXUSBFLTCTX_FROM_LE(_pLe) ( (PVBOXUSBFLTCTX)( ((uint8_t*)(_pLe)) - RT_OFFSETOF(VBOXUSBFLTCTX, ListEntry) ) )
146
147typedef struct VBOXUSBFLT_LOCK
148{
149 KSPIN_LOCK Lock;
150 KIRQL OldIrql;
151} VBOXUSBFLT_LOCK, *PVBOXUSBFLT_LOCK;
152
153#define VBOXUSBFLT_LOCK_INIT() \
154 KeInitializeSpinLock(&g_VBoxUsbFltGlobals.Lock.Lock)
155#define VBOXUSBFLT_LOCK_TERM() do { } while (0)
156#define VBOXUSBFLT_LOCK_ACQUIRE() \
157 KeAcquireSpinLock(&g_VBoxUsbFltGlobals.Lock.Lock, &g_VBoxUsbFltGlobals.Lock.OldIrql);
158#define VBOXUSBFLT_LOCK_RELEASE() \
159 KeReleaseSpinLock(&g_VBoxUsbFltGlobals.Lock.Lock, g_VBoxUsbFltGlobals.Lock.OldIrql);
160
161
162typedef struct VBOXUSBFLT_BLDEV
163{
164 LIST_ENTRY ListEntry;
165 uint16_t idVendor;
166 uint16_t idProduct;
167 uint16_t bcdDevice;
168} VBOXUSBFLT_BLDEV, *PVBOXUSBFLT_BLDEV;
169
170#define PVBOXUSBFLT_BLDEV_FROM_LE(_pLe) ( (PVBOXUSBFLT_BLDEV)( ((uint8_t*)(_pLe)) - RT_OFFSETOF(VBOXUSBFLT_BLDEV, ListEntry) ) )
171
172typedef struct VBOXUSBFLTGLOBALS
173{
174 LIST_ENTRY DeviceList;
175 LIST_ENTRY ContextList;
176 /* devices known to misbehave */
177 LIST_ENTRY BlackDeviceList;
178 VBOXUSBFLT_LOCK Lock;
179} VBOXUSBFLTGLOBALS, *PVBOXUSBFLTGLOBALS;
180static VBOXUSBFLTGLOBALS g_VBoxUsbFltGlobals;
181
182static bool vboxUsbFltBlDevMatchLocked(uint16_t idVendor, uint16_t idProduct, uint16_t bcdDevice)
183{
184 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.BlackDeviceList.Flink;
185 pEntry != &g_VBoxUsbFltGlobals.BlackDeviceList;
186 pEntry = pEntry->Flink)
187 {
188 PVBOXUSBFLT_BLDEV pDev = PVBOXUSBFLT_BLDEV_FROM_LE(pEntry);
189 if (pDev->idVendor != idVendor)
190 continue;
191 if (pDev->idProduct != idProduct)
192 continue;
193 if (pDev->bcdDevice != bcdDevice)
194 continue;
195
196 return true;
197 }
198 return false;
199}
200
201static NTSTATUS vboxUsbFltBlDevAddLocked(uint16_t idVendor, uint16_t idProduct, uint16_t bcdDevice)
202{
203 if (vboxUsbFltBlDevMatchLocked(idVendor, idProduct, bcdDevice))
204 return STATUS_SUCCESS;
205 PVBOXUSBFLT_BLDEV pDev = (PVBOXUSBFLT_BLDEV)VBoxUsbMonMemAllocZ(sizeof (*pDev));
206 if (!pDev)
207 {
208 AssertFailed();
209 return STATUS_INSUFFICIENT_RESOURCES;
210 }
211
212 pDev->idVendor = idVendor;
213 pDev->idProduct = idProduct;
214 pDev->bcdDevice = bcdDevice;
215 InsertHeadList(&g_VBoxUsbFltGlobals.BlackDeviceList, &pDev->ListEntry);
216 return STATUS_SUCCESS;
217}
218
219static void vboxUsbFltBlDevClearLocked()
220{
221 PLIST_ENTRY pNext;
222 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.BlackDeviceList.Flink;
223 pEntry != &g_VBoxUsbFltGlobals.BlackDeviceList;
224 pEntry = pNext)
225 {
226 pNext = pEntry->Flink;
227 VBoxUsbMonMemFree(pEntry);
228 }
229}
230
231static void vboxUsbFltBlDevPopulateWithKnownLocked()
232{
233 /* this one halts when trying to get string descriptors from it */
234 vboxUsbFltBlDevAddLocked(0x5ac, 0x921c, 0x115);
235}
236
237
238DECLINLINE(void) vboxUsbFltDevRetain(PVBOXUSBFLT_DEVICE pDevice)
239{
240 Assert(pDevice->cRefs);
241 ASMAtomicIncU32(&pDevice->cRefs);
242}
243
244static void vboxUsbFltDevDestroy(PVBOXUSBFLT_DEVICE pDevice)
245{
246 Assert(!pDevice->cRefs);
247 Assert(pDevice->enmState == VBOXUSBFLT_DEVSTATE_REMOVED);
248 VBoxUsbMonMemFree(pDevice);
249}
250
251DECLINLINE(void) vboxUsbFltDevRelease(PVBOXUSBFLT_DEVICE pDevice)
252{
253 uint32_t cRefs = ASMAtomicDecU32(&pDevice->cRefs);
254 Assert(cRefs < UINT32_MAX/2);
255 if (!cRefs)
256 {
257 vboxUsbFltDevDestroy(pDevice);
258 }
259}
260
261static void vboxUsbFltDevOwnerSetLocked(PVBOXUSBFLT_DEVICE pDevice, PVBOXUSBFLTCTX pContext, uintptr_t uFltId, bool fIsOneShot)
262{
263 ASSERT_WARN(!pDevice->pOwner, ("device 0x%p has an owner(0x%p)", pDevice, pDevice->pOwner));
264 ++pContext->cActiveFilters;
265 pDevice->pOwner = pContext;
266 pDevice->uFltId = uFltId;
267 pDevice->fIsFilterOneShot = fIsOneShot;
268}
269
270static void vboxUsbFltDevOwnerClearLocked(PVBOXUSBFLT_DEVICE pDevice)
271{
272 ASSERT_WARN(pDevice->pOwner, ("no owner for device 0x%p", pDevice));
273 --pDevice->pOwner->cActiveFilters;
274 ASSERT_WARN(pDevice->pOwner->cActiveFilters < UINT32_MAX/2, ("cActiveFilters (%d)", pDevice->pOwner->cActiveFilters));
275 pDevice->pOwner = NULL;
276 pDevice->uFltId = 0;
277}
278
279static void vboxUsbFltDevOwnerUpdateLocked(PVBOXUSBFLT_DEVICE pDevice, PVBOXUSBFLTCTX pContext, uintptr_t uFltId, bool fIsOneShot)
280{
281 if (pDevice->pOwner != pContext)
282 {
283 if (pDevice->pOwner)
284 vboxUsbFltDevOwnerClearLocked(pDevice);
285 if (pContext)
286 vboxUsbFltDevOwnerSetLocked(pDevice, pContext, uFltId, fIsOneShot);
287 }
288 else if (pContext)
289 {
290 pDevice->uFltId = uFltId;
291 pDevice->fIsFilterOneShot = fIsOneShot;
292 }
293}
294
295static PVBOXUSBFLT_DEVICE vboxUsbFltDevGetLocked(PDEVICE_OBJECT pPdo)
296{
297#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
298 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.DeviceList.Flink;
299 pEntry != &g_VBoxUsbFltGlobals.DeviceList;
300 pEntry = pEntry->Flink)
301 {
302 PVBOXUSBFLT_DEVICE pDevice = PVBOXUSBFLT_DEVICE_FROM_LE(pEntry);
303 for (PLIST_ENTRY pEntry2 = pEntry->Flink;
304 pEntry2 != &g_VBoxUsbFltGlobals.DeviceList;
305 pEntry2 = pEntry2->Flink)
306 {
307 PVBOXUSBFLT_DEVICE pDevice2 = PVBOXUSBFLT_DEVICE_FROM_LE(pEntry2);
308 ASSERT_WARN( pDevice->idVendor != pDevice2->idVendor
309 || pDevice->idProduct != pDevice2->idProduct
310 || pDevice->bcdDevice != pDevice2->bcdDevice, ("duplicate devices in a list!!"));
311 }
312 }
313#endif
314 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.DeviceList.Flink;
315 pEntry != &g_VBoxUsbFltGlobals.DeviceList;
316 pEntry = pEntry->Flink)
317 {
318 PVBOXUSBFLT_DEVICE pDevice = PVBOXUSBFLT_DEVICE_FROM_LE(pEntry);
319 ASSERT_WARN( pDevice->enmState == VBOXUSBFLT_DEVSTATE_REPLUGGING
320 || pDevice->enmState == VBOXUSBFLT_DEVSTATE_UNCAPTURED
321 || pDevice->enmState == VBOXUSBFLT_DEVSTATE_CAPTURING
322 || pDevice->enmState == VBOXUSBFLT_DEVSTATE_CAPTURED
323 || pDevice->enmState == VBOXUSBFLT_DEVSTATE_USED_BY_GUEST,
324 ("Invalid device state(%d) for device(0x%p) PDO(0x%p)", pDevice->enmState, pDevice, pDevice->Pdo));
325 if (pDevice->Pdo == pPdo)
326 return pDevice;
327 }
328 return NULL;
329}
330
331PVBOXUSBFLT_DEVICE vboxUsbFltDevGet(PDEVICE_OBJECT pPdo)
332{
333 PVBOXUSBFLT_DEVICE pDevice;
334
335 VBOXUSBFLT_LOCK_ACQUIRE();
336 pDevice = vboxUsbFltDevGetLocked(pPdo);
337 /*
338 * Prevent a host crash when vboxUsbFltDevGetLocked fails to locate the matching PDO
339 * in g_VBoxUsbFltGlobals.DeviceList (see @bugref{6509}).
340 */
341 if (pDevice == NULL)
342 {
343 WARN(("failed to get device for PDO(0x%p)", pPdo));
344 }
345 else if (pDevice->enmState > VBOXUSBFLT_DEVSTATE_ADDED)
346 {
347 vboxUsbFltDevRetain(pDevice);
348 LOG(("found device (0x%p), state(%d) for PDO(0x%p)", pDevice, pDevice->enmState, pPdo));
349 }
350 else
351 {
352 LOG(("found replugging device (0x%p), state(%d) for PDO(0x%p)", pDevice, pDevice->enmState, pPdo));
353 pDevice = NULL;
354 }
355 VBOXUSBFLT_LOCK_RELEASE();
356
357 return pDevice;
358}
359
360static NTSTATUS vboxUsbFltPdoReplug(PDEVICE_OBJECT pDo)
361{
362 LOG(("Replugging PDO(0x%p)", pDo));
363 NTSTATUS Status = VBoxUsbToolIoInternalCtlSendSync(pDo, IOCTL_INTERNAL_USB_CYCLE_PORT, NULL, NULL);
364 ASSERT_WARN(Status == STATUS_SUCCESS, ("replugging PDO(0x%p) failed Status(0x%x)", pDo, Status));
365 LOG(("Replugging PDO(0x%p) done with Status(0x%x)", pDo, Status));
366 return Status;
367}
368
369static bool vboxUsbFltDevCanBeCaptured(PVBOXUSBFLT_DEVICE pDevice)
370{
371 if (pDevice->bClass == USB_DEVICE_CLASS_HUB)
372 {
373 LOG(("device (0x%p), pdo (0x%p) is a hub, can not be captured", pDevice, pDevice->Pdo));
374 return false;
375 }
376 return true;
377}
378
379static PVBOXUSBFLTCTX vboxUsbFltDevMatchLocked(PVBOXUSBFLT_DEVICE pDevice, uintptr_t *puId, bool fRemoveFltIfOneShot, bool *pfFilter, bool *pfIsOneShot)
380{
381 *puId = 0;
382 *pfFilter = false;
383 *pfIsOneShot = false;
384 if (!vboxUsbFltDevCanBeCaptured(pDevice))
385 {
386 LOG(("vboxUsbFltDevCanBeCaptured returned false"));
387 return NULL;
388 }
389
390 USBFILTER DevFlt;
391 USBFilterInit(&DevFlt, USBFILTERTYPE_CAPTURE);
392 USBFilterSetNumExact(&DevFlt, USBFILTERIDX_VENDOR_ID, pDevice->idVendor, true);
393 USBFilterSetNumExact(&DevFlt, USBFILTERIDX_PRODUCT_ID, pDevice->idProduct, true);
394 USBFilterSetNumExact(&DevFlt, USBFILTERIDX_DEVICE_REV, pDevice->bcdDevice, true);
395 USBFilterSetNumExact(&DevFlt, USBFILTERIDX_DEVICE_CLASS, pDevice->bClass, true);
396 USBFilterSetNumExact(&DevFlt, USBFILTERIDX_DEVICE_SUB_CLASS, pDevice->bSubClass, true);
397 USBFilterSetNumExact(&DevFlt, USBFILTERIDX_DEVICE_PROTOCOL, pDevice->bProtocol, true);
398 USBFilterSetStringExact(&DevFlt, USBFILTERIDX_MANUFACTURER_STR, pDevice->szMfgName, true /*fMustBePresent*/, true /*fPurge*/);
399 USBFilterSetStringExact(&DevFlt, USBFILTERIDX_PRODUCT_STR, pDevice->szProduct, true /*fMustBePresent*/, true /*fPurge*/);
400 USBFilterSetStringExact(&DevFlt, USBFILTERIDX_SERIAL_NUMBER_STR, pDevice->szSerial, true /*fMustBePresent*/, true /*fPurge*/);
401
402 /* Run filters on the thing. */
403 PVBOXUSBFLTCTX pOwner = VBoxUSBFilterMatchEx(&DevFlt, puId, fRemoveFltIfOneShot, pfFilter, pfIsOneShot);
404 USBFilterDelete(&DevFlt);
405 return pOwner;
406}
407
408static void vboxUsbFltDevStateMarkReplugLocked(PVBOXUSBFLT_DEVICE pDevice)
409{
410 vboxUsbFltDevOwnerUpdateLocked(pDevice, NULL, 0, false);
411 pDevice->enmState = VBOXUSBFLT_DEVSTATE_REPLUGGING;
412}
413
414static bool vboxUsbFltDevStateIsNotFiltered(PVBOXUSBFLT_DEVICE pDevice)
415{
416 return pDevice->enmState == VBOXUSBFLT_DEVSTATE_UNCAPTURED;
417}
418
419static bool vboxUsbFltDevStateIsFiltered(PVBOXUSBFLT_DEVICE pDevice)
420{
421 return pDevice->enmState >= VBOXUSBFLT_DEVSTATE_CAPTURING;
422}
423
424#define VBOXUSBMON_POPULATE_REQUEST_TIMEOUT_MS 10000
425
426static NTSTATUS vboxUsbFltDevPopulate(PVBOXUSBFLT_DEVICE pDevice, PDEVICE_OBJECT pDo /*, BOOLEAN bPopulateNonFilterProps*/)
427{
428 NTSTATUS Status;
429 PUSB_DEVICE_DESCRIPTOR pDevDr = 0;
430
431 pDevice->Pdo = pDo;
432
433 LOG(("Populating Device(0x%p) for PDO(0x%p)", pDevice, pDo));
434
435 pDevDr = (PUSB_DEVICE_DESCRIPTOR)VBoxUsbMonMemAllocZ(sizeof(*pDevDr));
436 if (pDevDr == NULL)
437 {
438 WARN(("Failed to alloc mem for urb"));
439 return STATUS_INSUFFICIENT_RESOURCES;
440 }
441
442 do
443 {
444 Status = VBoxUsbToolGetDescriptor(pDo, pDevDr, sizeof(*pDevDr), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, VBOXUSBMON_POPULATE_REQUEST_TIMEOUT_MS);
445 if (!NT_SUCCESS(Status))
446 {
447 WARN(("getting device descriptor failed, Status (0x%x)", Status));
448 break;
449 }
450
451 if (vboxUsbFltBlDevMatchLocked(pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice))
452 {
453 WARN(("found a known black list device, vid(0x%x), pid(0x%x), rev(0x%x)", pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice));
454 Status = STATUS_UNSUCCESSFUL;
455 break;
456 }
457
458 LOG(("Device pid=%x vid=%x rev=%x", pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice));
459 pDevice->idVendor = pDevDr->idVendor;
460 pDevice->idProduct = pDevDr->idProduct;
461 pDevice->bcdDevice = pDevDr->bcdDevice;
462 pDevice->bClass = pDevDr->bDeviceClass;
463 pDevice->bSubClass = pDevDr->bDeviceSubClass;
464 pDevice->bProtocol = pDevDr->bDeviceProtocol;
465 pDevice->szSerial[0] = 0;
466 pDevice->szMfgName[0] = 0;
467 pDevice->szProduct[0] = 0;
468
469 /* If there are no strings, don't even try to get any string descriptors. */
470 if (pDevDr->iSerialNumber || pDevDr->iManufacturer || pDevDr->iProduct)
471 {
472 int langId;
473
474 Status = VBoxUsbToolGetLangID(pDo, &langId, VBOXUSBMON_POPULATE_REQUEST_TIMEOUT_MS);
475 if (!NT_SUCCESS(Status))
476 {
477 WARN(("reading language ID failed"));
478 if (Status == STATUS_CANCELLED)
479 {
480 WARN(("found a new black list device, vid(0x%x), pid(0x%x), rev(0x%x)", pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice));
481 vboxUsbFltBlDevAddLocked(pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice);
482 Status = STATUS_UNSUCCESSFUL;
483 }
484 break;
485 }
486
487 if (pDevDr->iSerialNumber)
488 {
489 Status = VBoxUsbToolGetStringDescriptor(pDo, pDevice->szSerial, sizeof (pDevice->szSerial), pDevDr->iSerialNumber, langId, VBOXUSBMON_POPULATE_REQUEST_TIMEOUT_MS);
490 if (!NT_SUCCESS(Status))
491 {
492 WARN(("reading serial number failed"));
493 ASSERT_WARN(pDevice->szSerial[0] == '\0', ("serial is not zero!!"));
494 if (Status == STATUS_CANCELLED)
495 {
496 WARN(("found a new black list device, vid(0x%x), pid(0x%x), rev(0x%x)", pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice));
497 vboxUsbFltBlDevAddLocked(pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice);
498 Status = STATUS_UNSUCCESSFUL;
499 break;
500 }
501 LOG(("pretending success.."));
502 Status = STATUS_SUCCESS;
503 }
504 }
505
506 if (pDevDr->iManufacturer)
507 {
508 Status = VBoxUsbToolGetStringDescriptor(pDo, pDevice->szMfgName, sizeof (pDevice->szMfgName), pDevDr->iManufacturer, langId, VBOXUSBMON_POPULATE_REQUEST_TIMEOUT_MS);
509 if (!NT_SUCCESS(Status))
510 {
511 WARN(("reading manufacturer name failed"));
512 ASSERT_WARN(pDevice->szMfgName[0] == '\0', ("szMfgName is not zero!!"));
513 if (Status == STATUS_CANCELLED)
514 {
515 WARN(("found a new black list device, vid(0x%x), pid(0x%x), rev(0x%x)", pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice));
516 vboxUsbFltBlDevAddLocked(pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice);
517 Status = STATUS_UNSUCCESSFUL;
518 break;
519 }
520 LOG(("pretending success.."));
521 Status = STATUS_SUCCESS;
522 }
523 }
524
525 if (pDevDr->iProduct)
526 {
527 Status = VBoxUsbToolGetStringDescriptor(pDo, pDevice->szProduct, sizeof (pDevice->szProduct), pDevDr->iProduct, langId, VBOXUSBMON_POPULATE_REQUEST_TIMEOUT_MS);
528 if (!NT_SUCCESS(Status))
529 {
530 WARN(("reading product name failed"));
531 ASSERT_WARN(pDevice->szProduct[0] == '\0', ("szProduct is not zero!!"));
532 if (Status == STATUS_CANCELLED)
533 {
534 WARN(("found a new black list device, vid(0x%x), pid(0x%x), rev(0x%x)", pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice));
535 vboxUsbFltBlDevAddLocked(pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice);
536 Status = STATUS_UNSUCCESSFUL;
537 break;
538 }
539 LOG(("pretending success.."));
540 Status = STATUS_SUCCESS;
541 }
542 }
543
544#if 0
545 if (bPopulateNonFilterProps)
546 {
547 WCHAR RegKeyBuf[512];
548 ULONG cbRegKeyBuf = sizeof (RegKeyBuf);
549 Status = IoGetDeviceProperty(pDo,
550 DevicePropertyDriverKeyName,
551 cbRegKeyBuf,
552 RegKeyBuf,
553 &cbRegKeyBuf);
554 if (!NT_SUCCESS(Status))
555 {
556 AssertMsgFailed((__FUNCTION__": IoGetDeviceProperty failed Status (0x%x)", Status));
557 break;
558 }
559
560 ANSI_STRING Ansi;
561 UNICODE_STRING Unicode;
562 Ansi.Buffer = pDevice->szDrvKeyName;
563 Ansi.Length = 0;
564 Ansi.MaximumLength = sizeof(pDevice->szDrvKeyName);
565 RtlInitUnicodeString(&Unicode, RegKeyBuf);
566
567 Status = RtlUnicodeStringToAnsiString(&Ansi, &Unicode, FALSE /* do not allocate */);
568 if (!NT_SUCCESS(Status))
569 {
570 AssertMsgFailed((__FUNCTION__": RtlUnicodeStringToAnsiString failed Status (0x%x)", Status));
571 break;
572 }
573
574 pDevice->fHighSpend = FALSE;
575 Status = VBoxUsbToolGetDeviceSpeed(pDo, &pDevice->fHighSpend);
576 if (!NT_SUCCESS(Status))
577 {
578 AssertMsgFailed((__FUNCTION__": VBoxUsbToolGetDeviceSpeed failed Status (0x%x)", Status));
579 break;
580 }
581 }
582#endif
583 LOG((": strings: '%s':'%s':'%s' (lang ID %x)",
584 pDevice->szMfgName, pDevice->szProduct, pDevice->szSerial, langId));
585 }
586
587 LOG(("Populating Device(0x%p) for PDO(0x%p) Succeeded", pDevice, pDo));
588 Status = STATUS_SUCCESS;
589 } while (0);
590
591 VBoxUsbMonMemFree(pDevDr);
592 LOG(("Populating Device(0x%p) for PDO(0x%p) Done, Status (0x%x)", pDevice, pDo, Status));
593 return Status;
594}
595
596static void vboxUsbFltSignalChangeLocked()
597{
598 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.ContextList.Flink;
599 pEntry != &g_VBoxUsbFltGlobals.ContextList;
600 pEntry = pEntry->Flink)
601 {
602 PVBOXUSBFLTCTX pCtx = PVBOXUSBFLTCTX_FROM_LE(pEntry);
603 /* the removed context can not be in a list */
604 Assert(!pCtx->bRemoved);
605 if (pCtx->pChangeEvent)
606 {
607 KeSetEvent(pCtx->pChangeEvent,
608 0, /* increment*/
609 FALSE /* wait */);
610 }
611 }
612}
613
614static bool vboxUsbFltDevCheckReplugLocked(PVBOXUSBFLT_DEVICE pDevice, PVBOXUSBFLTCTX pContext)
615{
616 ASSERT_WARN(pContext, ("context is NULL!"));
617
618 LOG(("Current context is (0x%p)", pContext));
619 LOG(("Current Device owner is (0x%p)", pDevice->pOwner));
620
621 /* check if device is already replugging */
622 if (pDevice->enmState <= VBOXUSBFLT_DEVSTATE_ADDED)
623 {
624 LOG(("Device (0x%p) is already replugging, return..", pDevice));
625 /* it is, do nothing */
626 ASSERT_WARN(pDevice->enmState == VBOXUSBFLT_DEVSTATE_REPLUGGING,
627 ("Device (0x%p) state is NOT REPLUGGING (%d)", pDevice, pDevice->enmState));
628 return false;
629 }
630
631 if (pDevice->pOwner && pContext != pDevice->pOwner)
632 {
633 LOG(("Device (0x%p) is owned by another context(0x%p), current is(0x%p)", pDevice, pDevice->pOwner, pContext));
634 /* this device is owned by another context, we're not allowed to do anything */
635 return false;
636 }
637
638 uintptr_t uId = 0;
639 bool bNeedReplug = false;
640 bool fFilter = false;
641 bool fIsOneShot = false;
642 PVBOXUSBFLTCTX pNewOwner = vboxUsbFltDevMatchLocked(pDevice, &uId,
643 false, /* do not remove a one-shot filter */
644 &fFilter, &fIsOneShot);
645 LOG(("Matching Info: Filter (0x%p), NewOwner(0x%p), fFilter(%d), fIsOneShot(%d)", uId, pNewOwner, (int)fFilter, (int)fIsOneShot));
646 if (pDevice->pOwner && pNewOwner && pDevice->pOwner != pNewOwner)
647 {
648 LOG(("Matching: Device (0x%p) is requested another owner(0x%p), current is(0x%p)", pDevice, pNewOwner, pDevice->pOwner));
649 /* the device is owned by another owner, we can not change the owner here */
650 return false;
651 }
652
653 if (!fFilter)
654 {
655 LOG(("Matching: Device (0x%p) should NOT be filtered", pDevice));
656 /* the device should NOT be filtered, check the current state */
657 if (vboxUsbFltDevStateIsNotFiltered(pDevice))
658 {
659 LOG(("Device (0x%p) is NOT filtered", pDevice));
660 /* no changes */
661 if (fIsOneShot)
662 {
663 ASSERT_WARN(pNewOwner, ("no new owner"));
664 LOG(("Matching: This is a one-shot filter (0x%p), removing..", uId));
665 /* remove a one-shot filter and keep the original filter data */
666 int tmpRc = VBoxUSBFilterRemove(pNewOwner, uId);
667 ASSERT_WARN(RT_SUCCESS(tmpRc), ("remove filter failed, rc (%d)", tmpRc));
668 if (!pDevice->pOwner)
669 {
670 LOG(("Matching: updating the one-shot owner to (0x%p), fltId(0x%p)", pNewOwner, uId));
671 /* update owner for one-shot if the owner is changed (i.e. assigned) */
672 vboxUsbFltDevOwnerUpdateLocked(pDevice, pNewOwner, uId, true);
673 }
674 else
675 {
676 LOG(("Matching: device already has owner (0x%p) assigned", pDevice->pOwner));
677 }
678 }
679 else
680 {
681 LOG(("Matching: This is NOT a one-shot filter (0x%p), newOwner(0x%p)", uId, pNewOwner));
682 if (pNewOwner)
683 {
684 vboxUsbFltDevOwnerUpdateLocked(pDevice, pNewOwner, uId, false);
685 }
686 }
687 }
688 else
689 {
690 LOG(("Device (0x%p) IS filtered", pDevice));
691 /* the device is currently filtered, we should release it only if
692 * 1. device does not have an owner
693 * or
694 * 2. it should be released bue to a one-shot filter
695 * or
696 * 3. it is NOT grabbed by a one-shot filter */
697 if (!pDevice->pOwner || fIsOneShot || !pDevice->fIsFilterOneShot)
698 {
699 LOG(("Matching: Need replug"));
700 bNeedReplug = true;
701 }
702 }
703 }
704 else
705 {
706 LOG(("Matching: Device (0x%p) SHOULD be filtered", pDevice));
707 /* the device should be filtered, check the current state */
708 ASSERT_WARN(uId, ("zero uid"));
709 ASSERT_WARN(pNewOwner, ("zero pNewOwner"));
710 if (vboxUsbFltDevStateIsFiltered(pDevice))
711 {
712 LOG(("Device (0x%p) IS filtered", pDevice));
713 /* the device is filtered */
714 if (pNewOwner == pDevice->pOwner)
715 {
716 LOG(("Device owner match"));
717 /* no changes */
718 if (fIsOneShot)
719 {
720 LOG(("Matching: This is a one-shot filter (0x%p), removing..", uId));
721 /* remove a one-shot filter and keep the original filter data */
722 int tmpRc = VBoxUSBFilterRemove(pNewOwner, uId);
723 ASSERT_WARN(RT_SUCCESS(tmpRc), ("remove filter failed, rc (%d)", tmpRc));
724 }
725 else
726 {
727 LOG(("Matching: This is NOT a one-shot filter (0x%p), Owner(0x%p)", uId, pDevice->pOwner));
728 vboxUsbFltDevOwnerUpdateLocked(pDevice, pDevice->pOwner, uId, false);
729 }
730 }
731 else
732 {
733 ASSERT_WARN(!pDevice->pOwner, ("device should NOT have owner"));
734 LOG(("Matching: Need replug"));
735 /* the device needs to be filtered, but the owner changes, replug needed */
736 bNeedReplug = true;
737 }
738 }
739 else
740 {
741 /* the device is currently NOT filtered,
742 * we should replug it only if
743 * 1. device does not have an owner
744 * or
745 * 2. it should be captured due to a one-shot filter
746 * or
747 * 3. it is NOT released by a one-shot filter */
748 if (!pDevice->pOwner || fIsOneShot || !pDevice->fIsFilterOneShot)
749 {
750 bNeedReplug = true;
751 LOG(("Matching: Need replug"));
752 }
753 }
754 }
755
756 if (bNeedReplug)
757 {
758 LOG(("Matching: Device needs replugging, marking as such"));
759 vboxUsbFltDevStateMarkReplugLocked(pDevice);
760 }
761 else
762 {
763 LOG(("Matching: Device does NOT need replugging"));
764 }
765
766 return bNeedReplug;
767}
768
769static void vboxUsbFltReplugList(PLIST_ENTRY pList)
770{
771 PLIST_ENTRY pNext;
772 for (PLIST_ENTRY pEntry = pList->Flink;
773 pEntry != pList;
774 pEntry = pNext)
775 {
776 pNext = pEntry->Flink;
777 PVBOXUSBFLT_DEVICE pDevice = PVBOXUSBFLT_DEVICE_FROM_REPLUGGINGLE(pEntry);
778 LOG(("replugging matched PDO(0x%p), pDevice(0x%p)", pDevice->Pdo, pDevice));
779 ASSERT_WARN(pDevice->enmState == VBOXUSBFLT_DEVSTATE_REPLUGGING
780 || pDevice->enmState == VBOXUSBFLT_DEVSTATE_REMOVED,
781 ("invalid state(0x%x) for device(0x%p)", pDevice->enmState, pDevice));
782
783 vboxUsbFltPdoReplug(pDevice->Pdo);
784 ObDereferenceObject(pDevice->Pdo);
785 vboxUsbFltDevRelease(pDevice);
786 }
787}
788
789typedef struct VBOXUSBFLTCHECKWALKER
790{
791 PVBOXUSBFLTCTX pContext;
792} VBOXUSBFLTCHECKWALKER, *PVBOXUSBFLTCHECKWALKER;
793
794static DECLCALLBACK(BOOLEAN) vboxUsbFltFilterCheckWalker(PFILE_OBJECT pFile, PDEVICE_OBJECT pTopDo,
795 PDEVICE_OBJECT pHubDo, PVOID pvContext)
796{
797 RT_NOREF1(pHubDo);
798 PVBOXUSBFLTCHECKWALKER pData = (PVBOXUSBFLTCHECKWALKER)pvContext;
799 PVBOXUSBFLTCTX pContext = pData->pContext;
800
801 LOG(("Visiting pFile(0x%p), pTopDo(0x%p), pHubDo(0x%p), oContext(0x%p)", pFile, pTopDo, pHubDo, pContext));
802 KIRQL Irql = KeGetCurrentIrql();
803 ASSERT_WARN(Irql == PASSIVE_LEVEL, ("unexpected IRQL (%d)", Irql));
804
805 PDEVICE_RELATIONS pDevRelations = NULL;
806
807 NTSTATUS Status = VBoxUsbMonQueryBusRelations(pTopDo, pFile, &pDevRelations);
808 if (Status == STATUS_SUCCESS && pDevRelations)
809 {
810 ULONG cReplugPdos = pDevRelations->Count;
811 LIST_ENTRY ReplugDevList;
812 InitializeListHead(&ReplugDevList);
813 for (ULONG k = 0; k < pDevRelations->Count; ++k)
814 {
815 PDEVICE_OBJECT pDevObj = pDevRelations->Objects[k];
816
817 LOG(("Found existing USB PDO 0x%p", pDevObj));
818 VBOXUSBFLT_LOCK_ACQUIRE();
819 PVBOXUSBFLT_DEVICE pDevice = vboxUsbFltDevGetLocked(pDevObj);
820 if (pDevice)
821 {
822 LOG(("Found existing device info (0x%p) for PDO 0x%p", pDevice, pDevObj));
823 bool bReplug = vboxUsbFltDevCheckReplugLocked(pDevice, pContext);
824 if (bReplug)
825 {
826 LOG(("Replug needed for device (0x%p)", pDevice));
827 InsertHeadList(&ReplugDevList, &pDevice->RepluggingLe);
828 vboxUsbFltDevRetain(pDevice);
829 /* do not dereference object since we will use it later */
830 }
831 else
832 {
833 LOG(("Replug NOT needed for device (0x%p)", pDevice));
834 ObDereferenceObject(pDevObj);
835 }
836
837 VBOXUSBFLT_LOCK_RELEASE();
838
839 pDevRelations->Objects[k] = NULL;
840 --cReplugPdos;
841 ASSERT_WARN((uint32_t)cReplugPdos < UINT32_MAX/2, ("cReplugPdos(%d) state broken", cReplugPdos));
842 continue;
843 }
844 VBOXUSBFLT_LOCK_RELEASE();
845
846 LOG(("NO device info found for PDO 0x%p", pDevObj));
847 VBOXUSBFLT_DEVICE Device;
848 Status = vboxUsbFltDevPopulate(&Device, pDevObj /*, FALSE /* only need filter properties */);
849 if (NT_SUCCESS(Status))
850 {
851 uintptr_t uId = 0;
852 bool fFilter = false;
853 bool fIsOneShot = false;
854 VBOXUSBFLT_LOCK_ACQUIRE();
855 PVBOXUSBFLTCTX pCtx = vboxUsbFltDevMatchLocked(&Device, &uId,
856 false, /* do not remove a one-shot filter */
857 &fFilter, &fIsOneShot);
858 VBOXUSBFLT_LOCK_RELEASE();
859 NOREF(pCtx);
860 LOG(("Matching Info: Filter (0x%p), pCtx(0x%p), fFilter(%d), fIsOneShot(%d)", uId, pCtx, (int)fFilter, (int)fIsOneShot));
861 if (fFilter)
862 {
863 LOG(("Matching: This device SHOULD be filtered"));
864 /* this device needs to be filtered, but it's not,
865 * leave the PDO in array to issue a replug request for it
866 * later on */
867 continue;
868 }
869 }
870 else
871 {
872 WARN(("vboxUsbFltDevPopulate for PDO 0x%p failed with Status 0x%x", pDevObj, Status));
873 }
874
875 LOG(("Matching: This device should NOT be filtered"));
876 /* this device should not be filtered, and it's not */
877 ObDereferenceObject(pDevObj);
878 pDevRelations->Objects[k] = NULL;
879 --cReplugPdos;
880 ASSERT_WARN((uint32_t)cReplugPdos < UINT32_MAX/2, ("cReplugPdos is %d", cReplugPdos));
881 }
882
883 LOG(("(%d) non-matched PDOs to be replugged", cReplugPdos));
884
885 if (cReplugPdos)
886 {
887 for (ULONG k = 0; k < pDevRelations->Count; ++k)
888 {
889 if (!pDevRelations->Objects[k])
890 continue;
891
892 Status = vboxUsbFltPdoReplug(pDevRelations->Objects[k]);
893 ASSERT_WARN(Status == STATUS_SUCCESS, ("vboxUsbFltPdoReplug ailed Status(0x%x)", Status));
894 ObDereferenceObject(pDevRelations->Objects[k]);
895 if (!--cReplugPdos)
896 break;
897 }
898
899 ASSERT_WARN(!cReplugPdos, ("cReplugPdosreached zero!"));
900 }
901
902 vboxUsbFltReplugList(&ReplugDevList);
903
904 ExFreePool(pDevRelations);
905 }
906 else
907 {
908 WARN(("VBoxUsbMonQueryBusRelations failed for DO(0x%p), Status(0x%x), pDevRelations(0x%p)",
909 pTopDo, Status, pDevRelations));
910 }
911
912 LOG(("Done Visiting pFile(0x%p), pTopDo(0x%p), pHubDo(0x%p), oContext(0x%p)", pFile, pTopDo, pHubDo, pContext));
913
914 return TRUE;
915}
916
917NTSTATUS VBoxUsbFltFilterCheck(PVBOXUSBFLTCTX pContext)
918{
919 KIRQL Irql = KeGetCurrentIrql();
920 ASSERT_WARN(Irql == PASSIVE_LEVEL, ("unexpected IRQL (%d)", Irql));
921
922 LOG(("Running filters, Context (0x%p)..", pContext));
923
924 VBOXUSBFLTCHECKWALKER Data;
925 Data.pContext = pContext;
926 vboxUsbMonHubDevWalk(vboxUsbFltFilterCheckWalker, &Data, VBOXUSBMONHUBWALK_F_FDO);
927
928 LOG(("DONE Running filters, Context (0x%p)", pContext));
929
930 return STATUS_SUCCESS;
931}
932
933NTSTATUS VBoxUsbFltClose(PVBOXUSBFLTCTX pContext)
934{
935 LOG(("Closing context(0x%p)", pContext));
936 LIST_ENTRY ReplugDevList;
937 InitializeListHead(&ReplugDevList);
938
939 ASSERT_WARN(pContext, ("null context"));
940
941 KIRQL Irql = KeGetCurrentIrql();
942 ASSERT_WARN(Irql == PASSIVE_LEVEL, ("irql==(%d)", Irql));
943
944 VBOXUSBFLT_LOCK_ACQUIRE();
945
946 pContext->bRemoved = TRUE;
947 if (pContext->pChangeEvent)
948 {
949 LOG(("seting & closing change event (0x%p)", pContext->pChangeEvent));
950 KeSetEvent(pContext->pChangeEvent,
951 0, /* increment*/
952 FALSE /* wait */);
953 ObDereferenceObject(pContext->pChangeEvent);
954 pContext->pChangeEvent = NULL;
955 }
956 else
957 LOG(("no change event"));
958 RemoveEntryList(&pContext->ListEntry);
959
960 LOG(("removing owner filters"));
961 /* now re-arrange the filters */
962 /* 1. remove filters */
963 VBoxUSBFilterRemoveOwner(pContext);
964
965 LOG(("enumerating devices.."));
966 /* 2. check if there are devices owned */
967 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.DeviceList.Flink;
968 pEntry != &g_VBoxUsbFltGlobals.DeviceList;
969 pEntry = pEntry->Flink)
970 {
971 PVBOXUSBFLT_DEVICE pDevice = PVBOXUSBFLT_DEVICE_FROM_LE(pEntry);
972 if (pDevice->pOwner != pContext)
973 continue;
974
975 LOG(("found device(0x%p), pdo(0x%p), state(%d), filter id(0x%p), oneshot(%d)",
976 pDevice, pDevice->Pdo, pDevice->enmState, pDevice->uFltId, (int)pDevice->fIsFilterOneShot));
977 ASSERT_WARN(pDevice->enmState != VBOXUSBFLT_DEVSTATE_ADDED, ("VBOXUSBFLT_DEVSTATE_ADDED state for device(0x%p)", pDevice));
978 ASSERT_WARN(pDevice->enmState != VBOXUSBFLT_DEVSTATE_REMOVED, ("VBOXUSBFLT_DEVSTATE_REMOVED state for device(0x%p)", pDevice));
979
980 vboxUsbFltDevOwnerClearLocked(pDevice);
981
982 if (vboxUsbFltDevCheckReplugLocked(pDevice, pContext))
983 {
984 LOG(("device needs replug"));
985 InsertHeadList(&ReplugDevList, &pDevice->RepluggingLe);
986 /* retain to ensure the device is not removed before we issue a replug */
987 vboxUsbFltDevRetain(pDevice);
988 /* keep the PDO alive */
989 ObReferenceObject(pDevice->Pdo);
990 }
991 else
992 {
993 LOG(("device does NOT need replug"));
994 }
995 }
996
997 VBOXUSBFLT_LOCK_RELEASE();
998
999 /* this should replug all devices that were either skipped or grabbed due to the context's */
1000 vboxUsbFltReplugList(&ReplugDevList);
1001
1002 LOG(("SUCCESS done context(0x%p)", pContext));
1003 return STATUS_SUCCESS;
1004}
1005
1006NTSTATUS VBoxUsbFltCreate(PVBOXUSBFLTCTX pContext)
1007{
1008 LOG(("Creating context(0x%p)", pContext));
1009 memset(pContext, 0, sizeof (*pContext));
1010 pContext->Process = RTProcSelf();
1011 VBOXUSBFLT_LOCK_ACQUIRE();
1012 InsertHeadList(&g_VBoxUsbFltGlobals.ContextList, &pContext->ListEntry);
1013 VBOXUSBFLT_LOCK_RELEASE();
1014 LOG(("SUCCESS context(0x%p)", pContext));
1015 return STATUS_SUCCESS;
1016}
1017
1018int VBoxUsbFltAdd(PVBOXUSBFLTCTX pContext, PUSBFILTER pFilter, uintptr_t *pId)
1019{
1020 LOG(("adding filter, Context (0x%p)..", pContext));
1021 *pId = 0;
1022 /* LOG the filter details. */
1023 LOG((__FUNCTION__": %s %s %s",
1024 USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) : "<null>",
1025 USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) : "<null>",
1026 USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) : "<null>"));
1027#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
1028 LOG(("VBoxUSBClient::addFilter: idVendor=%#x idProduct=%#x bcdDevice=%#x bDeviceClass=%#x bDeviceSubClass=%#x bDeviceProtocol=%#x bBus=%#x bPort=%#x Type%#x",
1029 USBFilterGetNum(pFilter, USBFILTERIDX_VENDOR_ID),
1030 USBFilterGetNum(pFilter, USBFILTERIDX_PRODUCT_ID),
1031 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_REV),
1032 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_CLASS),
1033 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_SUB_CLASS),
1034 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_PROTOCOL),
1035 USBFilterGetNum(pFilter, USBFILTERIDX_BUS),
1036 USBFilterGetNum(pFilter, USBFILTERIDX_PORT),
1037 USBFilterGetFilterType(pFilter)));
1038#endif
1039
1040 /* We can't get the bus/port numbers. Ignore them while matching. */
1041 USBFilterSetMustBePresent(pFilter, USBFILTERIDX_BUS, false);
1042 USBFilterSetMustBePresent(pFilter, USBFILTERIDX_PORT, false);
1043
1044 uintptr_t uId = 0;
1045 VBOXUSBFLT_LOCK_ACQUIRE();
1046 /* Add the filter. */
1047 int rc = VBoxUSBFilterAdd(pFilter, pContext, &uId);
1048 VBOXUSBFLT_LOCK_RELEASE();
1049 if (RT_SUCCESS(rc))
1050 {
1051 LOG(("ADDED filer id 0x%p", uId));
1052 ASSERT_WARN(uId, ("uid is NULL"));
1053#ifdef VBOX_USBMON_WITH_FILTER_AUTOAPPLY
1054 VBoxUsbFltFilterCheck();
1055#endif
1056 }
1057 else
1058 {
1059 WARN(("VBoxUSBFilterAdd failed rc (%d)", rc));
1060 ASSERT_WARN(!uId, ("uid is not NULL"));
1061 }
1062
1063 *pId = uId;
1064 return rc;
1065}
1066
1067int VBoxUsbFltRemove(PVBOXUSBFLTCTX pContext, uintptr_t uId)
1068{
1069 LOG(("removing filter id(0x%p), Context (0x%p)..", pContext, uId));
1070 Assert(uId);
1071
1072 VBOXUSBFLT_LOCK_ACQUIRE();
1073 int rc = VBoxUSBFilterRemove(pContext, uId);
1074 if (!RT_SUCCESS(rc))
1075 {
1076 WARN(("VBoxUSBFilterRemove failed rc (%d)", rc));
1077 VBOXUSBFLT_LOCK_RELEASE();
1078 return rc;
1079 }
1080
1081 LOG(("enumerating devices.."));
1082 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.DeviceList.Flink;
1083 pEntry != &g_VBoxUsbFltGlobals.DeviceList;
1084 pEntry = pEntry->Flink)
1085 {
1086 PVBOXUSBFLT_DEVICE pDevice = PVBOXUSBFLT_DEVICE_FROM_LE(pEntry);
1087 if (pDevice->fIsFilterOneShot)
1088 {
1089 ASSERT_WARN(!pDevice->uFltId, ("oneshot filter on device(0x%p): unexpected uFltId(%d)", pDevice, pDevice->uFltId));
1090 }
1091
1092 if (pDevice->uFltId != uId)
1093 continue;
1094
1095 ASSERT_WARN(pDevice->pOwner == pContext, ("Device(0x%p) owner(0x%p) not match to (0x%p)", pDevice, pDevice->pOwner, pContext));
1096 if (pDevice->pOwner != pContext)
1097 continue;
1098
1099 LOG(("found device(0x%p), pdo(0x%p), state(%d), filter id(0x%p), oneshot(%d)",
1100 pDevice, pDevice->Pdo, pDevice->enmState, pDevice->uFltId, (int)pDevice->fIsFilterOneShot));
1101 ASSERT_WARN(!pDevice->fIsFilterOneShot, ("device(0x%p) is filtered with a oneshot filter", pDevice));
1102 pDevice->uFltId = 0;
1103 /* clear the fIsFilterOneShot flag to ensure the device is replugged on the next VBoxUsbFltFilterCheck call */
1104 pDevice->fIsFilterOneShot = false;
1105 }
1106 VBOXUSBFLT_LOCK_RELEASE();
1107
1108 LOG(("done enumerating devices"));
1109
1110 if (RT_SUCCESS(rc))
1111 {
1112#ifdef VBOX_USBMON_WITH_FILTER_AUTOAPPLY
1113 VBoxUsbFltFilterCheck();
1114#endif
1115 }
1116 return rc;
1117}
1118
1119NTSTATUS VBoxUsbFltSetNotifyEvent(PVBOXUSBFLTCTX pContext, HANDLE hEvent)
1120{
1121 NTSTATUS Status = STATUS_SUCCESS;
1122 PKEVENT pEvent = NULL;
1123 PKEVENT pOldEvent = NULL;
1124 if (hEvent)
1125 {
1126 Status = ObReferenceObjectByHandle(hEvent,
1127 EVENT_MODIFY_STATE,
1128 *ExEventObjectType, UserMode,
1129 (PVOID*)&pEvent,
1130 NULL);
1131 Assert(Status == STATUS_SUCCESS);
1132 if (!NT_SUCCESS(Status))
1133 return Status;
1134 }
1135
1136 VBOXUSBFLT_LOCK_ACQUIRE();
1137 pOldEvent = pContext->pChangeEvent;
1138 pContext->pChangeEvent = pEvent;
1139 VBOXUSBFLT_LOCK_RELEASE();
1140
1141 if (pOldEvent)
1142 {
1143 ObDereferenceObject(pOldEvent);
1144 }
1145
1146 return STATUS_SUCCESS;
1147}
1148
1149static USBDEVICESTATE vboxUsbDevGetUserState(PVBOXUSBFLTCTX pContext, PVBOXUSBFLT_DEVICE pDevice)
1150{
1151 if (vboxUsbFltDevStateIsNotFiltered(pDevice))
1152 return USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
1153
1154 /* the device is filtered, or replugging */
1155 if (pDevice->enmState == VBOXUSBFLT_DEVSTATE_REPLUGGING)
1156 {
1157 ASSERT_WARN(!pDevice->pOwner, ("replugging device(0x%p) still has an owner(0x%p)", pDevice, pDevice->pOwner));
1158 ASSERT_WARN(!pDevice->uFltId, ("replugging device(0x%p) still has filter(0x%p)", pDevice, pDevice->uFltId));
1159 /* no user state for this, we should not return it tu the user */
1160 return USBDEVICESTATE_USED_BY_HOST;
1161 }
1162
1163 /* the device is filtered, if owner differs from the context, return as USED_BY_HOST */
1164 ASSERT_WARN(pDevice->pOwner, ("device(0x%p) has noowner", pDevice));
1165 /* the id can be null if a filter is removed */
1166// Assert(pDevice->uFltId);
1167
1168 if (pDevice->pOwner != pContext)
1169 {
1170 LOG(("Device owner differs from the current context, returning used by host"));
1171 return USBDEVICESTATE_USED_BY_HOST;
1172 }
1173
1174 switch (pDevice->enmState)
1175 {
1176 case VBOXUSBFLT_DEVSTATE_UNCAPTURED:
1177 case VBOXUSBFLT_DEVSTATE_CAPTURING:
1178 return USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
1179 case VBOXUSBFLT_DEVSTATE_CAPTURED:
1180 return USBDEVICESTATE_HELD_BY_PROXY;
1181 case VBOXUSBFLT_DEVSTATE_USED_BY_GUEST:
1182 return USBDEVICESTATE_USED_BY_GUEST;
1183 default:
1184 WARN(("unexpected device state(%d) for device(0x%p)", pDevice->enmState, pDevice));
1185 return USBDEVICESTATE_UNSUPPORTED;
1186 }
1187}
1188
1189static void vboxUsbDevToUserInfo(PVBOXUSBFLTCTX pContext, PVBOXUSBFLT_DEVICE pDevice, PUSBSUP_DEVINFO pDevInfo)
1190{
1191#if 0
1192 pDevInfo->usVendorId = pDevice->idVendor;
1193 pDevInfo->usProductId = pDevice->idProduct;
1194 pDevInfo->usRevision = pDevice->bcdDevice;
1195 pDevInfo->enmState = vboxUsbDevGetUserState(pContext, pDevice);
1196
1197 strcpy(pDevInfo->szDrvKeyName, pDevice->szDrvKeyName);
1198 if (pDevInfo->enmState == USBDEVICESTATE_HELD_BY_PROXY
1199 || pDevInfo->enmState == USBDEVICESTATE_USED_BY_GUEST)
1200 {
1201 /* this is the only case where we return the obj name to the client */
1202 strcpy(pDevInfo->szObjName, pDevice->szObjName);
1203 }
1204 pDevInfo->fHighSpeed = pDevice->fHighSpeed;
1205#else
1206 RT_NOREF3(pContext, pDevice, pDevInfo);
1207#endif
1208}
1209
1210NTSTATUS VBoxUsbFltGetDevice(PVBOXUSBFLTCTX pContext, HVBOXUSBDEVUSR hDevice, PUSBSUP_GETDEV_MON pInfo)
1211{
1212 Assert(hDevice);
1213
1214 memset (pInfo, 0, sizeof (*pInfo));
1215 VBOXUSBFLT_LOCK_ACQUIRE();
1216 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.DeviceList.Flink;
1217 pEntry != &g_VBoxUsbFltGlobals.DeviceList;
1218 pEntry = pEntry->Flink)
1219 {
1220 PVBOXUSBFLT_DEVICE pDevice = PVBOXUSBFLT_DEVICE_FROM_LE(pEntry);
1221 Assert(pDevice->enmState != VBOXUSBFLT_DEVSTATE_REMOVED);
1222 Assert(pDevice->enmState != VBOXUSBFLT_DEVSTATE_ADDED);
1223
1224 if (pDevice != hDevice)
1225 continue;
1226
1227 USBDEVICESTATE enmUsrState = vboxUsbDevGetUserState(pContext, pDevice);
1228 pInfo->enmState = enmUsrState;
1229 VBOXUSBFLT_LOCK_RELEASE();
1230 return STATUS_SUCCESS;
1231 }
1232
1233 VBOXUSBFLT_LOCK_RELEASE();
1234
1235 /* this should not occur */
1236 AssertFailed();
1237
1238 return STATUS_INVALID_PARAMETER;
1239}
1240
1241NTSTATUS VBoxUsbFltPdoAdd(PDEVICE_OBJECT pPdo, BOOLEAN *pbFiltered)
1242{
1243 *pbFiltered = FALSE;
1244 PVBOXUSBFLT_DEVICE pDevice;
1245
1246 /* first check if device is in the a already */
1247 VBOXUSBFLT_LOCK_ACQUIRE();
1248 pDevice = vboxUsbFltDevGetLocked(pPdo);
1249 if (pDevice)
1250 {
1251 LOG(("found device (0x%p), state(%d) for PDO(0x%p)", pDevice, pDevice->enmState, pPdo));
1252 ASSERT_WARN(pDevice->enmState != VBOXUSBFLT_DEVSTATE_ADDED, ("VBOXUSBFLT_DEVSTATE_ADDED state for device(0x%p)", pDevice));
1253 ASSERT_WARN(pDevice->enmState != VBOXUSBFLT_DEVSTATE_REMOVED, ("VBOXUSBFLT_DEVSTATE_REMOVED state for device(0x%p)", pDevice));
1254 *pbFiltered = pDevice->enmState >= VBOXUSBFLT_DEVSTATE_CAPTURING;
1255 VBOXUSBFLT_LOCK_RELEASE();
1256 return STATUS_SUCCESS;
1257 }
1258 VBOXUSBFLT_LOCK_RELEASE();
1259 pDevice = (PVBOXUSBFLT_DEVICE)VBoxUsbMonMemAllocZ(sizeof (*pDevice));
1260 if (!pDevice)
1261 {
1262 WARN(("VBoxUsbMonMemAllocZ failed"));
1263 return STATUS_NO_MEMORY;
1264 }
1265
1266 pDevice->enmState = VBOXUSBFLT_DEVSTATE_ADDED;
1267 pDevice->cRefs = 1;
1268 NTSTATUS Status = vboxUsbFltDevPopulate(pDevice, pPdo /* , TRUE /* need all props */);
1269 if (!NT_SUCCESS(Status))
1270 {
1271 WARN(("vboxUsbFltDevPopulate failed, Status 0x%x", Status));
1272 VBoxUsbMonMemFree(pDevice);
1273 return Status;
1274 }
1275
1276 uintptr_t uId;
1277 bool fFilter = false;
1278 bool fIsOneShot = false;
1279 PVBOXUSBFLTCTX pCtx;
1280 PVBOXUSBFLT_DEVICE pTmpDev;
1281 VBOXUSBFLT_LOCK_ACQUIRE();
1282 /* (paranoia) re-check the device is still not here */
1283 pTmpDev = vboxUsbFltDevGetLocked(pPdo);
1284 if (pTmpDev)
1285 {
1286 LOG(("second try: found device (0x%p), state(%d) for PDO(0x%p)", pDevice, pDevice->enmState, pPdo));
1287 ASSERT_WARN(pDevice->enmState != VBOXUSBFLT_DEVSTATE_ADDED, ("second try: VBOXUSBFLT_DEVSTATE_ADDED state for device(0x%p)", pDevice));
1288 ASSERT_WARN(pDevice->enmState != VBOXUSBFLT_DEVSTATE_REMOVED, ("second try: VBOXUSBFLT_DEVSTATE_REMOVED state for device(0x%p)", pDevice));
1289 *pbFiltered = pTmpDev->enmState >= VBOXUSBFLT_DEVSTATE_CAPTURING;
1290 VBOXUSBFLT_LOCK_RELEASE();
1291 VBoxUsbMonMemFree(pDevice);
1292 return STATUS_SUCCESS;
1293 }
1294
1295 LOG(("Created Device 0x%p for PDO 0x%p", pDevice, pPdo));
1296
1297 pCtx = vboxUsbFltDevMatchLocked(pDevice, &uId,
1298 true, /* remove a one-shot filter */
1299 &fFilter, &fIsOneShot);
1300 LOG(("Matching Info: Filter (0x%p), pCtx(0x%p), fFilter(%d), fIsOneShot(%d)", uId, pCtx, (int)fFilter, (int)fIsOneShot));
1301 if (fFilter)
1302 {
1303 LOG(("Created Device 0x%p should be filtered", pDevice));
1304 ASSERT_WARN(pCtx, ("zero ctx"));
1305 ASSERT_WARN(uId, ("zero uId"));
1306 pDevice->enmState = VBOXUSBFLT_DEVSTATE_CAPTURING;
1307 }
1308 else
1309 {
1310 LOG(("Created Device 0x%p should NOT be filtered", pDevice));
1311 ASSERT_WARN(!uId == !pCtx, ("invalid uid(0x%p) - ctx(0x%p) pair", uId, pCtx)); /* either both zero or both not */
1312 pDevice->enmState = VBOXUSBFLT_DEVSTATE_UNCAPTURED;
1313 }
1314
1315 if (pCtx)
1316 vboxUsbFltDevOwnerSetLocked(pDevice, pCtx, fIsOneShot ? 0 : uId, fIsOneShot);
1317
1318 InsertHeadList(&g_VBoxUsbFltGlobals.DeviceList, &pDevice->GlobalLe);
1319
1320 /* do not need to signal anything here -
1321 * going to do that once the proxy device object starts */
1322 VBOXUSBFLT_LOCK_RELEASE();
1323
1324 *pbFiltered = fFilter;
1325
1326 return STATUS_SUCCESS;
1327}
1328
1329NTSTATUS VBoxUsbFltPdoAddCompleted(PDEVICE_OBJECT pPdo)
1330{
1331 RT_NOREF1(pPdo);
1332 VBOXUSBFLT_LOCK_ACQUIRE();
1333 vboxUsbFltSignalChangeLocked();
1334 VBOXUSBFLT_LOCK_RELEASE();
1335 return STATUS_SUCCESS;
1336}
1337
1338BOOLEAN VBoxUsbFltPdoIsFiltered(PDEVICE_OBJECT pPdo)
1339{
1340 VBOXUSBFLT_DEVSTATE enmState = VBOXUSBFLT_DEVSTATE_REMOVED;
1341 VBOXUSBFLT_LOCK_ACQUIRE();
1342
1343 PVBOXUSBFLT_DEVICE pDevice = vboxUsbFltDevGetLocked(pPdo);
1344 if (pDevice)
1345 enmState = pDevice->enmState;
1346
1347 VBOXUSBFLT_LOCK_RELEASE();
1348
1349 return enmState >= VBOXUSBFLT_DEVSTATE_CAPTURING;
1350}
1351
1352NTSTATUS VBoxUsbFltPdoRemove(PDEVICE_OBJECT pPdo)
1353{
1354 PVBOXUSBFLT_DEVICE pDevice;
1355 VBOXUSBFLT_DEVSTATE enmOldState;
1356
1357 VBOXUSBFLT_LOCK_ACQUIRE();
1358 pDevice = vboxUsbFltDevGetLocked(pPdo);
1359 if (pDevice)
1360 {
1361 RemoveEntryList(&pDevice->GlobalLe);
1362 enmOldState = pDevice->enmState;
1363 pDevice->enmState = VBOXUSBFLT_DEVSTATE_REMOVED;
1364 if (enmOldState != VBOXUSBFLT_DEVSTATE_REPLUGGING)
1365 {
1366 vboxUsbFltSignalChangeLocked();
1367 }
1368 else
1369 {
1370 /* the device *should* reappear, do signlling on re-appear only
1371 * to avoid extra signaling. still there might be a situation
1372 * when the device will not re-appear if it gets physically removed
1373 * before it re-appears
1374 * @todo: set a timer callback to do a notification from it */
1375 }
1376 }
1377 VBOXUSBFLT_LOCK_RELEASE();
1378 if (pDevice)
1379 vboxUsbFltDevRelease(pDevice);
1380 return STATUS_SUCCESS;
1381}
1382
1383HVBOXUSBFLTDEV VBoxUsbFltProxyStarted(PDEVICE_OBJECT pPdo)
1384{
1385 PVBOXUSBFLT_DEVICE pDevice;
1386 VBOXUSBFLT_LOCK_ACQUIRE();
1387 pDevice = vboxUsbFltDevGetLocked(pPdo);
1388 /*
1389 * Prevent a host crash when vboxUsbFltDevGetLocked fails to locate the matching PDO
1390 * in g_VBoxUsbFltGlobals.DeviceList (see @bugref{6509}).
1391 */
1392 if (pDevice == NULL)
1393 {
1394 WARN(("failed to get device for PDO(0x%p)", pPdo));
1395 }
1396 else if (pDevice->enmState = VBOXUSBFLT_DEVSTATE_CAPTURING)
1397 {
1398 pDevice->enmState = VBOXUSBFLT_DEVSTATE_CAPTURED;
1399 LOG(("The proxy notified proxy start for the captured device 0x%x", pDevice));
1400 vboxUsbFltDevRetain(pDevice);
1401 vboxUsbFltSignalChangeLocked();
1402 }
1403 else
1404 {
1405 WARN(("invalid state, %d", pDevice->enmState));
1406 pDevice = NULL;
1407 }
1408 VBOXUSBFLT_LOCK_RELEASE();
1409 return pDevice;
1410}
1411
1412void VBoxUsbFltProxyStopped(HVBOXUSBFLTDEV hDev)
1413{
1414 PVBOXUSBFLT_DEVICE pDevice = (PVBOXUSBFLT_DEVICE)hDev;
1415 /*
1416 * Prevent a host crash when VBoxUsbFltProxyStarted fails, returning NULL.
1417 * See @bugref{6509}.
1418 */
1419 if (pDevice == NULL)
1420 {
1421 WARN(("VBoxUsbFltProxyStopped called with NULL device pointer"));
1422 return;
1423 }
1424 VBOXUSBFLT_LOCK_ACQUIRE();
1425 if (pDevice->enmState == VBOXUSBFLT_DEVSTATE_CAPTURED
1426 || pDevice->enmState == VBOXUSBFLT_DEVSTATE_USED_BY_GUEST)
1427 {
1428 /* this is due to devie was physically removed */
1429 LOG(("The proxy notified proxy stop for the captured device 0x%x, current state %d", pDevice, pDevice->enmState));
1430 pDevice->enmState = VBOXUSBFLT_DEVSTATE_CAPTURING;
1431 vboxUsbFltSignalChangeLocked();
1432 }
1433 else
1434 {
1435 if (pDevice->enmState != VBOXUSBFLT_DEVSTATE_REPLUGGING)
1436 {
1437 WARN(("invalid state, %d", pDevice->enmState));
1438 }
1439 }
1440 VBOXUSBFLT_LOCK_RELEASE();
1441
1442 vboxUsbFltDevRelease(pDevice);
1443}
1444
1445NTSTATUS VBoxUsbFltInit()
1446{
1447 int rc = VBoxUSBFilterInit();
1448 if (RT_FAILURE(rc))
1449 {
1450 WARN(("VBoxUSBFilterInit failed, rc (%d)", rc));
1451 return STATUS_UNSUCCESSFUL;
1452 }
1453
1454 memset(&g_VBoxUsbFltGlobals, 0, sizeof (g_VBoxUsbFltGlobals));
1455 InitializeListHead(&g_VBoxUsbFltGlobals.DeviceList);
1456 InitializeListHead(&g_VBoxUsbFltGlobals.ContextList);
1457 InitializeListHead(&g_VBoxUsbFltGlobals.BlackDeviceList);
1458 vboxUsbFltBlDevPopulateWithKnownLocked();
1459 VBOXUSBFLT_LOCK_INIT();
1460 return STATUS_SUCCESS;
1461}
1462
1463NTSTATUS VBoxUsbFltTerm()
1464{
1465 bool bBusy = false;
1466 VBOXUSBFLT_LOCK_ACQUIRE();
1467 do
1468 {
1469 if (!IsListEmpty(&g_VBoxUsbFltGlobals.ContextList))
1470 {
1471 AssertFailed();
1472 bBusy = true;
1473 break;
1474 }
1475
1476 PLIST_ENTRY pNext = NULL;
1477 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.DeviceList.Flink;
1478 pEntry != &g_VBoxUsbFltGlobals.DeviceList;
1479 pEntry = pNext)
1480 {
1481 pNext = pEntry->Flink;
1482 PVBOXUSBFLT_DEVICE pDevice = PVBOXUSBFLT_DEVICE_FROM_LE(pEntry);
1483 Assert(!pDevice->uFltId);
1484 Assert(!pDevice->pOwner);
1485 if (pDevice->cRefs != 1)
1486 {
1487 AssertFailed();
1488 bBusy = true;
1489 break;
1490 }
1491 }
1492 } while (0);
1493
1494 VBOXUSBFLT_LOCK_RELEASE()
1495
1496 if (bBusy)
1497 {
1498 return STATUS_DEVICE_BUSY;
1499 }
1500
1501 for (PLIST_ENTRY pEntry = g_VBoxUsbFltGlobals.DeviceList.Flink;
1502 pEntry != &g_VBoxUsbFltGlobals.DeviceList;
1503 pEntry = g_VBoxUsbFltGlobals.DeviceList.Flink)
1504 {
1505 RemoveEntryList(pEntry);
1506 PVBOXUSBFLT_DEVICE pDevice = PVBOXUSBFLT_DEVICE_FROM_LE(pEntry);
1507 pDevice->enmState = VBOXUSBFLT_DEVSTATE_REMOVED;
1508 vboxUsbFltDevRelease(pDevice);
1509 }
1510
1511 vboxUsbFltBlDevClearLocked();
1512
1513 VBOXUSBFLT_LOCK_TERM();
1514
1515 VBoxUSBFilterTerm();
1516
1517 return STATUS_SUCCESS;
1518}
1519
Note: See TracBrowser for help on using the repository browser.

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