VirtualBox

Ignore:
Timestamp:
Sep 30, 2019 3:35:52 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133689
Message:

USB/win: Drill down to PDO base when looking up device objects. Solves problems with capturing when USBPcap is installed.

Location:
trunk/src/VBox/HostDrivers/VBoxUSB/win/mon
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/VBoxUSB/win/mon/VBoxUsbFlt.cpp

    r81078 r81083  
    4747#include <devguid.h>
    4848
     49
     50/* We should be including ntifs.h but that's not as easy as it sounds. */
     51extern "C" {
     52NTKERNELAPI PDEVICE_OBJECT IoGetDeviceAttachmentBaseRef(__in PDEVICE_OBJECT DeviceObject);
     53}
    4954
    5055/*
     
    905910        for (ULONG k = 0; k < pDevRelations->Count; ++k)
    906911        {
    907             PDEVICE_OBJECT pDevObj = pDevRelations->Objects[k];
     912            PDEVICE_OBJECT pDevObj;
     913
     914            /* Grab the PDO+reference. We won't need the upper layer device object
     915             * anymore, so dereference that right here, and drop the PDO ref later.
     916             */
     917            pDevObj = IoGetDeviceAttachmentBaseRef(pDevRelations->Objects[k]);
     918            LOG(("DevObj=%p, PDO=%p\n", pDevRelations->Objects[k], pDevObj));
     919            ObDereferenceObject(pDevRelations->Objects[k]);
     920            pDevRelations->Objects[k] = pDevObj;
    908921
    909922            LOG(("Found existing USB PDO 0x%p", pDevObj));
     
    12991312    PVBOXUSBFLT_DEVICE pDevice;
    13001313
     1314    /* Find the real PDO+reference. Dereference when we're done with it. Note that
     1315     * the input pPdo was not explicitly referenced so we're not dropping its ref.
     1316     */
     1317    PDEVICE_OBJECT pDevObj = IoGetDeviceAttachmentBaseRef(pPdo);
     1318    LOG(("DevObj=%p, real PDO=%p\n", pPdo, pDevObj));
     1319    pPdo = pDevObj;
     1320
    13011321    /* first check if device is in the a already */
    13021322    VBOXUSBFLT_LOCK_ACQUIRE();
     
    13091329        *pbFiltered = pDevice->enmState >= VBOXUSBFLT_DEVSTATE_CAPTURING;
    13101330        VBOXUSBFLT_LOCK_RELEASE();
     1331        ObDereferenceObject(pPdo);
    13111332        return STATUS_SUCCESS;
    13121333    }
     
    13161337    {
    13171338        WARN(("VBoxUsbMonMemAllocZ failed"));
     1339        ObDereferenceObject(pPdo);
    13181340        return STATUS_NO_MEMORY;
    13191341    }
     
    13251347    {
    13261348        WARN(("vboxUsbFltDevPopulate failed, Status 0x%x", Status));
     1349        ObDereferenceObject(pPdo);
    13271350        VBoxUsbMonMemFree(pDevice);
    13281351        return Status;
     
    13371360    /* (paranoia) re-check the device is still not here */
    13381361    pTmpDev = vboxUsbFltDevGetLocked(pPdo);
     1362
     1363    /* Drop the PDO ref, now we won't need it anymore. */
     1364    ObDereferenceObject(pPdo);
     1365
    13391366    if (pTmpDev)
    13401367    {
     
    13851412{
    13861413    VBOXUSBFLT_DEVSTATE enmState = VBOXUSBFLT_DEVSTATE_REMOVED;
     1414
     1415    /* Find the real PDO+reference. Dereference when we're done with it. Note that
     1416     * the input pPdo was not explicitly referenced so we're not dropping its ref.
     1417     */
     1418    PDEVICE_OBJECT pDevObj = IoGetDeviceAttachmentBaseRef(pPdo);
     1419    LOG(("DevObj=%p, real PDO=%p\n", pPdo, pDevObj));
     1420    pPdo = pDevObj;
     1421
    13871422    VBOXUSBFLT_LOCK_ACQUIRE();
    13881423
     
    13921427
    13931428    VBOXUSBFLT_LOCK_RELEASE();
     1429    ObDereferenceObject(pPdo);
    13941430
    13951431    return enmState >= VBOXUSBFLT_DEVSTATE_CAPTURING;
     
    14001436    PVBOXUSBFLT_DEVICE pDevice;
    14011437    VBOXUSBFLT_DEVSTATE enmOldState;
     1438
     1439    /* Find the real PDO+reference. Dereference when we're done with it. Note that
     1440     * the input pPdo was not explicitly referenced so we're not dropping its ref.
     1441     */
     1442    PDEVICE_OBJECT pDevObj = IoGetDeviceAttachmentBaseRef(pPdo);
     1443    LOG(("DevObj=%p, real PDO=%p\n", pPdo, pDevObj));
     1444    pPdo = pDevObj;
    14021445
    14031446    VBOXUSBFLT_LOCK_ACQUIRE();
     
    14101453    }
    14111454    VBOXUSBFLT_LOCK_RELEASE();
     1455    ObDereferenceObject(pPdo);
    14121456    if (pDevice)
    14131457        vboxUsbFltDevRelease(pDevice);
     
    14191463    PVBOXUSBFLT_DEVICE pDevice;
    14201464    VBOXUSBFLT_LOCK_ACQUIRE();
     1465
     1466    /* NB: The USB proxy (VBoxUSB.sys) passes us the real PDO, not anything above that. */
    14211467    pDevice = vboxUsbFltDevGetLocked(pPdo);
    14221468    /*
  • trunk/src/VBox/HostDrivers/VBoxUSB/win/mon/VBoxUsbMon.cpp

    r81070 r81083  
    2323 * You may elect to license modified versions of this file under the
    2424 * terms and conditions of either the GPL or the CDDL or both.
     25 */
     26
     27
     28/*
     29 *
     30 *                        Theory of Operation
     31 *                              - or -
     32 *        The Document I Wish The Original Author Had Written
     33 *
     34 *
     35 * The USB Monitor (VBoxUSBMon.sys) serves to capture and uncapture USB
     36 * devices. Its job is to ensure that the USB proxy (VBoxUSB.sys) gets installed
     37 * for captured devices and removed again when not needed, restoring the regular
     38 * driver (if any).
     39 *
     40 * The USB Monitor does not handle any actual USB traffic; that is the role of
     41 * VBoxUSB.sys, the USB proxy. A typical solution for installing such USB proxy
     42 * is using a filter driver, but that approach was rejected because filter drivers
     43 * cannot be dynamically added and removed. What VBoxUSBMon does instead is hook
     44 * into the dispatch routine of the bus driver, i.e. USB hub driver, and alter
     45 * the PnP information returned by the bus driver.
     46 *
     47 * The key functionality for capturing is cycling a USB port (which causes a USB
     48 * device reset and triggers re-enumeration in the Windows USB driver stack), and
     49 * then modifying IRP_MN_QUERY_ID / BusQueryHardwareIDs and related requests so
     50 * that they return the synthetic USB VID/PID that VBoxUSB.sys handles rather than
     51 * the true hardware VID/PID. That causes Windows to install VBoxUSB.sys for the
     52 * device.
     53 *
     54 * Uncapturing again cycles the USB port but returns unmodified hardware IDs,
     55 * causing Windows to load the normal driver for the device.
     56 *
     57 * Identifying devices to capture or release (uncapture) is done through USB filters,
     58 * a cross-platform concept which matches USB device based on their VID/PID, class,
     59 * and other criteria.
     60 *
     61 * There is an IOCTL interface for adding/removing USB filters and applying them.
     62 * The IOCTLs are normally issued by VBoxSVC.
     63 *
     64 * USB devices are enumerated by finding all USB hubs (GUID_DEVINTERFACE_USB_HUB)
     65 * and querying their child devices (i.e. USB devices or other hubs) by sending
     66 * IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations. This is done when
     67 * applying existing filters.
     68 *
     69 * Newly arrived USB devices are intercepted early in their PnP enumeration
     70 * through the hooked bus driver dispatch routine. Devices which satisty the
     71 * filter matching criteria are morphed (see above) such that VBoxUSB.sys loads
     72 * for them before any default driver does.
     73 *
     74 * There is an IDC interface to VBoxUSB.sys which allows the USB proxy to report
     75 * that it's installed for a given USB device, and also report when the USB proxy
     76 * is unloaded (typically caused by either unplugging the device or uncapturing
     77 * and cycling the port). VBoxUSBMon.sys relies on these IDC calls to track
     78 * captured devices and be informed when VBoxUSB.sys unloads.
     79 *
     80 * Windows 8+ complicates the USB Monitor's life by automatically putting some
     81 * USB devices to a low-power state where they are unable to respond to any USB
     82 * requests and VBoxUSBMon can't read any of their descriptors (note that in
     83 * userland, the device descriptor can always be read, but string descriptors
     84 * can't). Such devices'  USB VID/PID/revision is recovered using the Windows
     85 * PnP Manager from their DevicePropertyHardwareID, but their USB class/subclass
     86 * and protocol unfortunately cannot be unambiguously recovered from their
     87 * DevicePropertyCompatibleIDs.
     88 *
     89 * Filter drivers add another complication. With filter drivers in place, the
     90 * device objects returned by the BusRelations query (or passing through the PnP
     91 * hooks) may not be PDOs but rather filter DOs higher in the stack. To avoid
     92 * confusion, we flatten the references to their base, i.e. the real PDO, which
     93 * should remain the same for the lifetime of a device. Note that VBoxUSB.sys
     94 * always passes its own PDO in the proxy startup IOCTL.
    2595 */
    2696
Note: See TracChangeset for help on using the changeset viewer.

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