VirtualBox

Changeset 48062 in vbox


Ignore:
Timestamp:
Aug 26, 2013 2:12:53 PM (11 years ago)
Author:
vboxsync
Message:

HostDrivers/VBoxUsbMon: Hook to multiple USB drivers on Windows (USB3 port support, #6509)

File:
1 edited

Legend:

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

    r38616 r48062  
    6262} VBOXUSBHUB_PNPHOOK_COMPLETION, *PVBOXUSBHUB_PNPHOOK_COMPLETION;
    6363
     64/*
     65 * Comment out VBOX_USB3PORT definition to disable hooking to multiple drivers (#6509)
     66 */
     67#define VBOX_USB3PORT
     68
     69#ifdef VBOX_USB3PORT
     70#define VBOXUSBMON_MAXDRIVERS 3
     71typedef struct VBOXUSB_PNPDRIVER
     72{
     73    PDRIVER_OBJECT     DriverObject;
     74    VBOXUSBHUB_PNPHOOK UsbHubPnPHook;
     75    PDRIVER_DISPATCH   pfnHookStub;
     76} VBOXUSB_PNPDRIVER, *PVBOXUSB_PNPDRIVER;
     77#endif /* !VBOX_USB3PORT */
     78
    6479typedef struct VBOXUSBMONGLOBALS
    6580{
    6681    PDEVICE_OBJECT pDevObj;
     82#ifdef VBOX_USB3PORT
     83    VBOXUSB_PNPDRIVER pDrivers[VBOXUSBMON_MAXDRIVERS];
     84#else /* !VBOX_USB3PORT */
    6785    VBOXUSBHUB_PNPHOOK UsbHubPnPHook;
     86#endif /* !VBOX_USB3PORT */
    6887    KEVENT OpenSynchEvent;
    6988    IO_REMOVE_LOCK RmLock;
     
    510529{
    511530    NTSTATUS Status = STATUS_UNSUCCESSFUL;
     531#ifndef VBOX_USB3PORT
    512532    UNICODE_STRING szStandardHubName;
    513533    PDRIVER_OBJECT pDrvObj = NULL;
     
    587607        }
    588608    }
     609#else /* VBOX_USB3PORT */
     610    PWSTR szwHubList;
     611    Status = IoGetDeviceInterfaces(&GUID_DEVINTERFACE_USB_HUB, NULL, 0, &szwHubList);
     612    if (Status != STATUS_SUCCESS)
     613    {
     614        LOG(("IoGetDeviceInterfaces failed with %d\n", Status));
     615        return;
     616    }
     617    if (szwHubList)
     618    {
     619        UNICODE_STRING  UnicodeName;
     620        PDEVICE_OBJECT  pHubDevObj;
     621        PFILE_OBJECT    pHubFileObj;
     622        PWSTR           szwHubName = szwHubList;
     623        while (*szwHubName != UNICODE_NULL)
     624        {
     625            RtlInitUnicodeString(&UnicodeName, szwHubName);
     626            Status = IoGetDeviceObjectPointer(&UnicodeName, FILE_READ_DATA, &pHubFileObj, &pHubDevObj);
     627            if (Status == STATUS_SUCCESS)
     628            {
     629                /** @todo Replace %S with something else as it does not work for PWSTR. */
     630                LOG(("IoGetDeviceObjectPointer for %S returned %p %p", szwHubName, pHubDevObj, pHubFileObj));
     631                if (!pfnWalker(pHubFileObj, pHubDevObj, pHubDevObj, pvWalker))
     632                {
     633                    LOG(("the walker said to stop"));
     634                    ObDereferenceObject(pHubFileObj);
     635                    break;
     636                }
     637
     638                LOG(("going forward.."));
     639                ObDereferenceObject(pHubFileObj);
     640            }
     641            szwHubName += wcslen(szwHubName) + 1;
     642        }
     643        ExFreePool(szwHubList);
     644    }
     645#endif /* VBOX_USB3PORT */
    589646}
    590647
     
    9971054    NTSTATUS tmpStatus = pIrp->IoStatus.Status;
    9981055#endif
    999     NTSTATUS Status = VBoxUsbHookRequestComplete(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp, pRequest);
     1056#ifdef VBOX_USB3PORT
     1057    PVBOXUSBHOOK_ENTRY pHook = pRequest->pHook;
     1058#else /* !VBOX_USB3PORT */
     1059    PVBOXUSBHOOK_ENTRY pHook = &g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook;
     1060#endif /* !VBOX_USB3PORT */
     1061    NTSTATUS Status = VBoxUsbHookRequestComplete(pHook, pDevObj, pIrp, pRequest);
    10001062    VBoxUsbMonMemFree(pRequest);
    10011063#ifdef DEBUG_misha
     
    10051067    }
    10061068#endif
    1007     VBoxUsbHookRelease(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
     1069    VBoxUsbHookRelease(pHook);
    10081070    return Status;
    10091071}
     
    10151077 * @param   pIrp         Request packet.
    10161078 */
     1079#ifdef VBOX_USB3PORT
     1080static NTSTATUS vboxUsbMonPnPHook(IN PVBOXUSBHOOK_ENTRY pHook, IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
     1081#else /* !VBOX_USB3PORT */
    10171082NTSTATUS _stdcall VBoxUsbMonPnPHook(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
    1018 {
     1083#endif /* !VBOX_USB3PORT */
     1084{
     1085#ifndef VBOX_USB3PORT
     1086    PVBOXUSBHOOK_ENTRY pHook = &g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook;
     1087#endif /* !VBOX_USB3PORT */
    10191088    LOG(("==>PnP: Mn(%s), PDO(0x%p), IRP(0x%p), Status(0x%x)", vboxUsbDbgStrPnPMn(IoGetCurrentIrpStackLocation(pIrp)->MinorFunction), pDevObj, pIrp, pIrp->IoStatus.Status));
    10201089
    1021     if(!VBoxUsbHookRetain(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook))
     1090    if(!VBoxUsbHookRetain(pHook))
    10221091    {
    10231092        WARN(("VBoxUsbHookRetain failed"));
    1024         return VBoxUsbHookRequestPassDownHookSkip(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp);
     1093        return VBoxUsbHookRequestPassDownHookSkip(pHook, pDevObj, pIrp);
    10251094    }
    10261095
     
    10291098    {
    10301099        WARN(("VBoxUsbMonMemAlloc failed"));
    1031         VBoxUsbHookRelease(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
     1100        VBoxUsbHookRelease(pHook);
    10321101        pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
    10331102        pIrp->IoStatus.Information = 0;
     
    10361105    }
    10371106
    1038     NTSTATUS Status = VBoxUsbHookRequestPassDownHookCompletion(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp, VBoxUsbPnPCompletion, &pCompletion->Rq);
     1107    NTSTATUS Status = VBoxUsbHookRequestPassDownHookCompletion(pHook, pDevObj, pIrp, VBoxUsbPnPCompletion, &pCompletion->Rq);
    10391108#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
    10401109    if (Status != STATUS_PENDING)
    10411110    {
    10421111        LOG(("Request completed, Status(0x%x)", Status));
    1043         VBoxUsbHookVerifyCompletion(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, &pCompletion->Rq, pIrp);
     1112        VBoxUsbHookVerifyCompletion(pHook, &pCompletion->Rq, pIrp);
    10441113    }
    10451114    else
     
    10511120}
    10521121
     1122#ifdef VBOX_USB3PORT
     1123/**
     1124 * Device PnP hook stubs.
     1125 *
     1126 * @param   pDevObj     Device object.
     1127 * @param   pIrp         Request packet.
     1128 */
     1129#define VBOX_PNPHOOKSTUB(n) NTSTATUS _stdcall VBoxUsbMonPnPHook##n(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) \
     1130{ \
     1131    return vboxUsbMonPnPHook(&g_VBoxUsbMonGlobals.pDrivers[n].UsbHubPnPHook.Hook, pDevObj, pIrp); \
     1132}
     1133
     1134#define VBOX_PNPHOOKSTUB_INIT(n) g_VBoxUsbMonGlobals.pDrivers[n].pfnHookStub = VBoxUsbMonPnPHook##n
     1135
     1136VBOX_PNPHOOKSTUB(0)
     1137VBOX_PNPHOOKSTUB(1)
     1138VBOX_PNPHOOKSTUB(2)
     1139AssertCompile(VBOXUSBMON_MAXDRIVERS == 3);
     1140
     1141typedef struct VBOXUSBMONHOOKDRIVERWALKER
     1142{
     1143    PDRIVER_OBJECT pDrvObj;
     1144} VBOXUSBMONHOOKDRIVERWALKER, *PVBOXUSBMONHOOKDRIVERWALKER;
     1145
     1146static DECLCALLBACK(BOOLEAN) vboxUsbMonHookDrvObjWalker(PFILE_OBJECT pFile, PDEVICE_OBJECT pTopDo, PDEVICE_OBJECT pHubDo, PVOID pvContext)
     1147{
     1148    PDRIVER_OBJECT pDrvObj = pHubDo->DriverObject;
     1149
     1150    /* First we try to figure out if we are already hooked to this driver. */
     1151    for (int i = 0; i < VBOXUSBMON_MAXDRIVERS; i++)
     1152        if (pDrvObj == g_VBoxUsbMonGlobals.pDrivers[i].DriverObject)
     1153        {
     1154            LOG(("Found %p at pDrivers[%d]\n", pDrvObj, i));
     1155            /* We've already hooked to this one -- nothing to do. */
     1156            return TRUE;
     1157        }
     1158    /* We are not hooked yet, find an empty slot. */
     1159    for (int i = 0; i < VBOXUSBMON_MAXDRIVERS; i++)
     1160    {
     1161        if (!g_VBoxUsbMonGlobals.pDrivers[i].DriverObject)
     1162        {
     1163            /* Found an emtpy slot, use it. */
     1164            g_VBoxUsbMonGlobals.pDrivers[i].DriverObject = pDrvObj;
     1165            ObReferenceObject(pDrvObj);
     1166            LOG(("pDrivers[%d] = %p, installing the hook...\n", i, pDrvObj));
     1167            VBoxUsbHookInit(&g_VBoxUsbMonGlobals.pDrivers[i].UsbHubPnPHook.Hook,
     1168                            pDrvObj,
     1169                            IRP_MJ_PNP,
     1170                            g_VBoxUsbMonGlobals.pDrivers[i].pfnHookStub);
     1171            VBoxUsbHookInstall(&g_VBoxUsbMonGlobals.pDrivers[i].UsbHubPnPHook.Hook);
     1172            return TRUE; /* Must continue to find all drivers. */
     1173        }
     1174        if (pDrvObj == g_VBoxUsbMonGlobals.pDrivers[i].DriverObject)
     1175        {
     1176            LOG(("Found %p at pDrivers[%d]\n", pDrvObj, i));
     1177            /* We've already hooked to this one -- nothing to do. */
     1178            return TRUE;
     1179        }
     1180    }
     1181    /* No empty slots! No reason to continue. */
     1182    LOG(("No empty slots!\n"));
     1183    return FALSE;
     1184}
     1185
     1186/**
     1187 * Finds all USB drivers in the system and installs hooks if haven't done already.
     1188 */
     1189static NTSTATUS vboxUsbMonInstallAllHooks()
     1190{
     1191    vboxUsbMonHubDevWalk(vboxUsbMonHookDrvObjWalker, NULL, VBOXUSBMONHUBWALK_F_ALL);
     1192    return STATUS_SUCCESS;
     1193}
     1194#endif /* VBOX_USB3PORT */
    10531195
    10541196static NTSTATUS vboxUsbMonHookCheckInit()
     
    10601202        return STATUS_SUCCESS;
    10611203    }
     1204#ifdef VBOX_USB3PORT
     1205    return vboxUsbMonInstallAllHooks();
     1206#else /* !VBOX_USB3PORT */
    10621207    PDRIVER_OBJECT pDrvObj = vboxUsbMonHookFindHubDrvObj();
    10631208    if (pDrvObj)
     
    10701215    WARN(("hub drv obj not found, fail"));
    10711216    return STATUS_UNSUCCESSFUL;
     1217#endif /* !VBOX_USB3PORT */
    10721218}
    10731219
    10741220static NTSTATUS vboxUsbMonHookInstall()
    10751221{
     1222#ifdef VBOX_USB3PORT
     1223    /* Nothing to do here as we have already installed all hooks in vboxUsbMonHookCheckInit(). */
     1224    return STATUS_SUCCESS;
     1225#else /* !VBOX_USB3PORT */
    10761226#ifdef VBOXUSBMON_DBG_NO_PNPHOOK
    10771227    return STATUS_SUCCESS;
     
    10841234    return VBoxUsbHookInstall(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
    10851235#endif
     1236#endif /* !VBOX_USB3PORT */
    10861237}
    10871238
     
    10911242    return STATUS_SUCCESS;
    10921243#else
     1244#ifdef VBOX_USB3PORT
     1245    NTSTATUS Status = STATUS_SUCCESS;
     1246    for (int i = 0; i < VBOXUSBMON_MAXDRIVERS; i++)
     1247    {
     1248        if (g_VBoxUsbMonGlobals.pDrivers[i].DriverObject)
     1249        {
     1250            Assert(g_VBoxUsbMonGlobals.pDrivers[i].DriverObject == g_VBoxUsbMonGlobals.pDrivers[i].UsbHubPnPHook.Hook.pDrvObj);
     1251            LOG(("Unhooking from %p...\n", g_VBoxUsbMonGlobals.pDrivers[i].DriverObject));
     1252            Status = VBoxUsbHookUninstall(&g_VBoxUsbMonGlobals.pDrivers[i].UsbHubPnPHook.Hook);
     1253            if (!NT_SUCCESS(Status))
     1254            {
     1255                /*
     1256                 * We failed to uninstall the hook, so we keep the reference to the driver
     1257                 * in order to prevent another driver re-using this slot because we are
     1258                 * going to mark this hook as fUninitFailed.
     1259                 */
     1260                //AssertMsgFailed(("usbhub pnp unhook failed, setting the fUninitFailed flag, the current value of fUninitFailed (%d)", g_VBoxUsbMonGlobals.UsbHubPnPHook.fUninitFailed));
     1261                LOG(("usbhub pnp unhook failed, setting the fUninitFailed flag, the current value of fUninitFailed (%d)", g_VBoxUsbMonGlobals.pDrivers[i].UsbHubPnPHook.fUninitFailed));
     1262                g_VBoxUsbMonGlobals.pDrivers[i].UsbHubPnPHook.fUninitFailed = true;
     1263            }
     1264            else
     1265            {
     1266                /* The hook was removed successfully, now we can forget about this driver. */
     1267                ObDereferenceObject(g_VBoxUsbMonGlobals.pDrivers[i].DriverObject);
     1268                g_VBoxUsbMonGlobals.pDrivers[i].DriverObject = NULL;
     1269            }
     1270        }
     1271    }
     1272#else /* !VBOX_USB3PORT */
    10931273    NTSTATUS Status = VBoxUsbHookUninstall(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
    10941274    if (!NT_SUCCESS(Status))
     
    10971277        g_VBoxUsbMonGlobals.UsbHubPnPHook.fUninitFailed = true;
    10981278    }
     1279#endif /* !VBOX_USB3PORT */
    10991280    return Status;
    11001281#endif
     
    16751856
    16761857    memset (&g_VBoxUsbMonGlobals, 0, sizeof (g_VBoxUsbMonGlobals));
     1858#ifdef VBOX_USB3PORT
     1859    VBOX_PNPHOOKSTUB_INIT(0);
     1860    VBOX_PNPHOOKSTUB_INIT(1);
     1861    VBOX_PNPHOOKSTUB_INIT(2);
     1862    AssertCompile(VBOXUSBMON_MAXDRIVERS == 3);
     1863#endif /* VBOX_USB3PORT */
    16771864    KeInitializeEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, SynchronizationEvent, TRUE /* signaled */);
    16781865    IoInitializeRemoveLock(&g_VBoxUsbMonGlobals.RmLock, VBOXUSBMON_MEMTAG, 1, 100);
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