Changeset 80631 in vbox for trunk/src/VBox/HostDrivers/VBoxUSB
- Timestamp:
- Sep 6, 2019 1:39:33 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/VBoxUSB/win/lib/VBoxUsbLib-win.cpp
r80480 r80631 59 59 #ifdef VBOX_USB_USE_DEVICE_NOTIFICATION 60 60 # include <Dbt.h> 61 #endif 62 63 #ifdef VBOX_WITH_NEW_USB_ENUM 64 # include <cfgmgr32.h> 61 65 #endif 62 66 … … 899 903 } 900 904 905 #ifdef VBOX_WITH_NEW_USB_ENUM 906 907 /* Get a registry property for a device given its HDEVINFO + SP_DEVINFO_DATA. */ 908 static void *usbLibGetRegistryProperty(HDEVINFO InfoSet, const PSP_DEVINFO_DATA DevData, DWORD Property) 909 { 910 BOOL rc; 911 DWORD dwReqLen; 912 void *PropertyData; 913 914 /* How large a buffer do we need? */ 915 rc = SetupDiGetDeviceRegistryProperty(InfoSet, DevData, Property, 916 NULL, NULL, 0, &dwReqLen); 917 if (!rc && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) 918 { 919 LogRelFunc(("Failed to query buffer size, error %ld\n", GetLastError())); 920 AssertFailed(); 921 return NULL; 922 } 923 924 PropertyData = RTMemAlloc(dwReqLen); 925 if (!PropertyData) 926 return NULL; 927 928 /* Get the actual property data. */ 929 rc = SetupDiGetDeviceRegistryProperty(InfoSet, DevData, Property, 930 NULL, (PBYTE)PropertyData, dwReqLen, &dwReqLen); 931 if (!rc) 932 { 933 LogRelFunc(("Failed to get property data, error %ld\n", GetLastError())); 934 RTMemFree(PropertyData); 935 return NULL; 936 } 937 return PropertyData; 938 } 939 940 /* Given a HDEVINFO and SP_DEVICE_INTERFACE_DATA, get the interface detail data. */ 941 static PSP_DEVICE_INTERFACE_DETAIL_DATA usbLibGetDevDetail(HDEVINFO InfoSet, PSP_DEVICE_INTERFACE_DATA InterfaceData) 942 { 943 BOOL rc; 944 DWORD dwReqLen; 945 PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData; 946 947 rc = SetupDiGetDeviceInterfaceDetail(InfoSet, InterfaceData, NULL, 0, &dwReqLen, NULL); 948 if (!rc && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) 949 { 950 LogRelFunc(("Failed to get interface detail size, error %ld\n", GetLastError())); 951 return NULL; 952 } 953 954 DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)RTMemAlloc(dwReqLen); 955 if (!DetailData) 956 return NULL; 957 958 memset(DetailData, 0, dwReqLen); 959 DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 960 961 rc = SetupDiGetDeviceInterfaceDetail(InfoSet, InterfaceData, DetailData, dwReqLen, &dwReqLen, NULL); 962 if (!rc) 963 { 964 LogRelFunc(("Failed to get interface detail, error %ld\n", GetLastError())); 965 RTMemFree(DetailData); 966 } 967 968 return DetailData; 969 } 970 971 /* Given a hub's PnP device instance, find its device path (file name). */ 972 static LPCSTR usbLibGetHubPathFromDevInst(LPCSTR DevInst) 973 { 974 HDEVINFO InfoSet; 975 SP_DEVINFO_DATA DeviceData; 976 SP_DEVICE_INTERFACE_DATA InterfaceData; 977 PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData; 978 BOOL rc; 979 LPSTR DevicePath = NULL; 980 981 /* Enumerate the DevInst's USB hub interface. */ 982 InfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_HUB, DevInst, NULL, 983 DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); 984 if (InfoSet == INVALID_HANDLE_VALUE) 985 { 986 LogRelFunc(("Failed to get interface, error %ld\n", GetLastError())); 987 return NULL; 988 } 989 990 memset(&DeviceData, 0, sizeof(DeviceData)); 991 DeviceData.cbSize = sizeof(DeviceData); 992 rc = SetupDiEnumDeviceInterfaces(InfoSet, 0, &GUID_DEVINTERFACE_USB_HUB, 0, &InterfaceData); 993 if (!rc) 994 { 995 LogRelFunc(("Failed to get interface data, error %ld\n", GetLastError())); 996 SetupDiDestroyDeviceInfoList(InfoSet); 997 return NULL; 998 } 999 1000 DetailData = usbLibGetDevDetail(InfoSet, &InterfaceData); 1001 if (!DetailData) 1002 { 1003 SetupDiDestroyDeviceInfoList(InfoSet); 1004 return NULL; 1005 } 1006 1007 /* Copy the device path out of the interface detail. */ 1008 DevicePath = RTStrDup(DetailData->DevicePath); 1009 RTMemFree(DetailData); 1010 SetupDiDestroyDeviceInfoList(InfoSet); 1011 1012 return DevicePath; 1013 } 1014 1015 1016 /* Use the Configuration Manager (CM) to get a devices's parent given its DEVINST and 1017 * turn it into a PnP device instance ID string. 1018 */ 1019 static LPCSTR usbLibGetParentInstanceID(DEVINST DevInst) 1020 { 1021 LPSTR InstanceID; 1022 DEVINST ParentInst; 1023 ULONG ulReqChars; 1024 ULONG ulReqBytes; 1025 CONFIGRET cr; 1026 1027 /* First get the parent DEVINST. */ 1028 cr = CM_Get_Parent( &ParentInst, DevInst, 0); 1029 if (cr != CR_SUCCESS) 1030 { 1031 LogRelFunc(("Failed to get parent instance, error %ld\n", GetLastError())); 1032 return NULL; 1033 } 1034 1035 /* Then convert it to the instance ID string. */ 1036 cr = CM_Get_Device_ID_Size(&ulReqChars, ParentInst, 0); 1037 if (cr != CR_SUCCESS) 1038 { 1039 LogRelFunc(("Failed to get device ID size, error %ld\n", GetLastError())); 1040 return NULL; 1041 } 1042 1043 /* CM_Get_Device_ID_Size gives us the size in characters without terminating null. */ 1044 ulReqBytes = (ulReqChars + 1) * sizeof(char); 1045 InstanceID = (LPSTR)RTMemAlloc(ulReqBytes); 1046 if (!InstanceID) 1047 return NULL; 1048 1049 cr = CM_Get_Device_ID(ParentInst, InstanceID, ulReqBytes, 0); 1050 if (cr != CR_SUCCESS) 1051 { 1052 LogRelFunc(("Failed to get device ID, error %ld\n", GetLastError())); 1053 RTMemFree(InstanceID); 1054 return NULL; 1055 } 1056 1057 return InstanceID; 1058 } 1059 1060 /* 1061 * Enumerate the USB devices in the host system. Since we do not care about the hierarchical 1062 * structure of root hubs, other hubs, and devices, we just use ask the USB PnP enumerator to 1063 * give us all it has. This includes hubs (though not root hubs) which we filter out. It also 1064 * includes USB devices with no driver, which is notably something we cannot get by enumerating 1065 * via GUID_DEVINTERFACE_USB_DEVICE. 1066 * 1067 * This approach also saves us some trouble relative to enumerating via hub IOCTLs and then 1068 * hunting through the PnP manager to find them. Instead, we look up the device's parent which 1069 * is inevitably a hub, and that allows us to obtain USB-specific data (descriptors, speeds, 1070 * etc.) when combined with the devices PnP "address" (USB port on parent hub). 1071 * 1072 * NB: Every USB device known to the Windows PnP Manager will have a device instance ID. Typically 1073 * it also has a DriverKey but only if it has a driver installed. Hence we ignore the DriverKey, at 1074 * least prior to capturing (once VBoxUSB.sys is installed, a DriverKey must by definition be 1075 * present). Also note that the device instance ID changes for captured devices since we change 1076 * their USB VID/PID, though it is unique at any given point. 1077 * 1078 * The location information should be a reliable way of identifying a device and does not change 1079 * with driver installs, capturing, etc. It is only available on Windows Vista and later; earlier 1080 * Windows version had no reliable way of cross-referencing the USB IOCTL and PnP Manager data. 1081 */ 1082 static int usbLibDevGetDevices(PUSBDEVICE *ppDevs, uint32_t *pcDevs) 1083 { 1084 HDEVINFO InfoSet; 1085 DWORD DeviceIndex; 1086 SP_DEVINFO_DATA DeviceData; 1087 LPSTR ClassGUID; 1088 1089 /* Ask for the USB PnP enumerator for all it has. */ 1090 InfoSet = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT); 1091 1092 memset(&DeviceData, 0, sizeof(DeviceData)); 1093 DeviceData.cbSize = sizeof(DeviceData); 1094 DeviceIndex = 0; 1095 1096 /* Enumerate everything in the info set. */ 1097 while (SetupDiEnumDeviceInfo(InfoSet, DeviceIndex, &DeviceData)) 1098 { 1099 /* Grab the class GUID. If it's a USB hub, we aren't interested. */ 1100 ClassGUID = (LPSTR)usbLibGetRegistryProperty(InfoSet, &DeviceData, SPDRP_CLASSGUID); 1101 if (ClassGUID && strcmp(ClassGUID, "{36fc9e60-c465-11cf-8056-444553540000}")) 1102 { 1103 /* There is a class GUID and it's not a hub. Should be a USB device then. */ 1104 RTMemFree(ClassGUID); 1105 } 1106 1107 ++DeviceIndex; 1108 memset(&DeviceData, 0, sizeof(DeviceData)); 1109 DeviceData.cbSize = sizeof(DeviceData); 1110 } 1111 1112 if (InfoSet) 1113 SetupDiDestroyDeviceInfoList(InfoSet); 1114 1115 return VINF_SUCCESS; 1116 } 1117 1118 #else 901 1119 static int usbLibDevGetDevices(PUSBDEVICE *ppDevs, uint32_t *pcDevs) 902 1120 { … … 926 1144 return VINF_SUCCESS; 927 1145 } 1146 #endif 928 1147 929 1148 static int usbLibMonDevicesCmp(PUSBDEVICE pDev, PVBOXUSB_DEV pDevInfo)
Note:
See TracChangeset
for help on using the changeset viewer.