g1g2hardwarechecker/USB/enum.c

3836 lines
114 KiB
C
Raw Normal View History

2024-01-08 10:06:47 +00:00
/*++
Copyright (c) 1997-2011 Microsoft Corporation
Module Name:
ENUM.C
Abstract:
This source file contains the routines which enumerate the USB bus
and populate the TreeView control.
The enumeration process goes like this:
(1) Enumerate Host Controllers and Root Hubs
EnumerateHostControllers()
EnumerateHostController()
Host controllers currently have symbolic link names of the form HCDx,
where x starts at 0. Use CreateFile() to open each host controller
symbolic link. Create a node in the TreeView to represent each host
controller.
GetRootHubName()
After a host controller has been opened, send the host controller an
IOCTL_USB_GET_ROOT_HUB_NAME request to get the symbolic link name of
the root hub that is part of the host controller.
(2) Enumerate Hubs (Root Hubs and External Hubs)
EnumerateHub()
Given the name of a hub, use CreateFile() to map the hub. Send the
hub an IOCTL_USB_GET_NODE_INFORMATION request to get info about the
hub, such as the number of downstream ports. Create a node in the
TreeView to represent each hub.
(3) Enumerate Downstream Ports
EnumerateHubPorts()
Given an handle to an open hub and the number of downstream ports on
the hub, send the hub an IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX
request for each downstream port of the hub to get info about the
device (if any) attached to each port. If there is a device attached
to a port, send the hub an IOCTL_USB_GET_NODE_CONNECTION_NAME request
to get the symbolic link name of the hub attached to the downstream
port. If there is a hub attached to the downstream port, recurse to
step (2).
GetAllStringDescriptors()
GetConfigDescriptor()
Create a node in the TreeView to represent each hub port
and attached device.
Environment:
user mode
Revision History:
04-25-97 : created
--*/
//*****************************************************************************
// I N C L U D E S
//*****************************************************************************
#include "enum.h"
//*****************************************************************************
// D E F I N E S
//*****************************************************************************
#define NUM_STRING_DESC_TO_GET 32
//*****************************************************************************
// L O C A L F U N C T I O N P R O T O T Y P E S
//*****************************************************************************
VOID
EnumerateHostControllers (
HTREEITEM hTreeParent,
ULONG *DevicesConnected
);
VOID
EnumerateHostController (
HTREEITEM hTreeParent,
HANDLE hHCDev,
_Inout_ PCHAR leafName,
_In_ HANDLE deviceInfo,
_In_ PSP_DEVINFO_DATA deviceInfoData
);
VOID
EnumerateHub (
HTREEITEM hTreeParent,
_In_reads_(cbHubName) PCHAR HubName,
_In_ size_t cbHubName,
_In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo,
_In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2,
_In_opt_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps,
_In_opt_ PUSB_DESCRIPTOR_REQUEST ConfigDesc,
_In_opt_ PUSB_DESCRIPTOR_REQUEST BosDesc,
_In_opt_ PSTRING_DESCRIPTOR_NODE StringDescs,
_In_opt_ PUSB_DEVICE_PNP_STRINGS DevProps
);
VOID
EnumerateHubPorts (
HTREEITEM hTreeParent,
HANDLE hHubDevice,
ULONG NumPorts
);
PCHAR GetRootHubName (
HANDLE HostController
);
PCHAR GetExternalHubName (
HANDLE Hub,
ULONG ConnectionIndex
);
PCHAR GetHCDDriverKeyName (
HANDLE HCD
);
PCHAR GetDriverKeyName (
HANDLE Hub,
ULONG ConnectionIndex
);
PUSB_DESCRIPTOR_REQUEST
GetConfigDescriptor (
HANDLE hHubDevice,
ULONG ConnectionIndex,
UCHAR DescriptorIndex
);
PUSB_DESCRIPTOR_REQUEST
GetBOSDescriptor (
HANDLE hHubDevice,
ULONG ConnectionIndex
);
DWORD
GetHostControllerPowerMap(
HANDLE hHCDev,
PUSBHOSTCONTROLLERINFO hcInfo);
DWORD
GetHostControllerInfo(
HANDLE hHCDev,
PUSBHOSTCONTROLLERINFO hcInfo);
PCHAR WideStrToMultiStr (
_In_reads_bytes_(cbWideStr) PWCHAR WideStr,
_In_ size_t cbWideStr
);
BOOL
AreThereStringDescriptors (
PUSB_DEVICE_DESCRIPTOR DeviceDesc,
PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc
);
PSTRING_DESCRIPTOR_NODE
GetAllStringDescriptors (
HANDLE hHubDevice,
ULONG ConnectionIndex,
PUSB_DEVICE_DESCRIPTOR DeviceDesc,
PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc
);
PSTRING_DESCRIPTOR_NODE
GetStringDescriptor (
HANDLE hHubDevice,
ULONG ConnectionIndex,
UCHAR DescriptorIndex,
USHORT LanguageID
);
HRESULT
GetStringDescriptors (
_In_ HANDLE hHubDevice,
_In_ ULONG ConnectionIndex,
_In_ UCHAR DescriptorIndex,
_In_ ULONG NumLanguageIDs,
_In_reads_(NumLanguageIDs) USHORT *LanguageIDs,
_In_ PSTRING_DESCRIPTOR_NODE StringDescNodeHead
);
void
EnumerateAllDevices();
void
EnumerateAllDevicesWithGuid(
PDEVICE_GUID_LIST DeviceList,
LPGUID Guid
);
void
FreeDeviceInfoNode(
_In_ PDEVICE_INFO_NODE *ppNode
);
PDEVICE_INFO_NODE
FindMatchingDeviceNodeForDriverName(
_In_ PSTR DriverKeyName,
_In_ BOOLEAN IsHub
);
//*****************************************************************************
// G L O B A L S
//*****************************************************************************
// List of enumerated host controllers.
//
LIST_ENTRY EnumeratedHCListHead =
{
&EnumeratedHCListHead,
&EnumeratedHCListHead
};
DEVICE_GUID_LIST gHubList;
DEVICE_GUID_LIST gDeviceList;
//*****************************************************************************
// G L O B A L S P R I V A T E T O T H I S F I L E
//*****************************************************************************
PCHAR ConnectionStatuses[] =
{
"", // 0 - NoDeviceConnected
"", // 1 - DeviceConnected
"FailedEnumeration", // 2 - DeviceFailedEnumeration
"GeneralFailure", // 3 - DeviceGeneralFailure
"Overcurrent", // 4 - DeviceCausedOvercurrent
"NotEnoughPower", // 5 - DeviceNotEnoughPower
"NotEnoughBandwidth", // 6 - DeviceNotEnoughBandwidth
"HubNestedTooDeeply", // 7 - DeviceHubNestedTooDeeply
"InLegacyHub", // 8 - DeviceInLegacyHub
"Enumerating", // 9 - DeviceEnumerating
"Reset" // 10 - DeviceReset
};
ULONG TotalDevicesConnected;
//*****************************************************************************
//
// EnumerateHostControllers()
//
// hTreeParent - Handle of the TreeView item under which host controllers
// should be added.
//
//*****************************************************************************
VOID
EnumerateHostControllers (
HTREEITEM hTreeParent,
ULONG *DevicesConnected
)
{
HANDLE hHCDev = NULL;
HDEVINFO deviceInfo = NULL;
SP_DEVINFO_DATA deviceInfoData;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetailData = NULL;
ULONG index = 0;
ULONG requiredLength = 0;
BOOL success;
TotalDevicesConnected = 0;
TotalHubs = 0;
EnumerateAllDevices();
// Iterate over host controllers using the new GUID based interface
//
deviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_CLASS_USB_HOST_CONTROLLER,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (index=0;
SetupDiEnumDeviceInfo(deviceInfo,
index,
&deviceInfoData);
index++)
{
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
success = SetupDiEnumDeviceInterfaces(deviceInfo,
0,
(LPGUID)&GUID_CLASS_USB_HOST_CONTROLLER,
index,
&deviceInterfaceData);
if (!success)
{
OOPS();
break;
}
success = SetupDiGetDeviceInterfaceDetail(deviceInfo,
&deviceInterfaceData,
NULL,
0,
&requiredLength,
NULL);
if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
OOPS();
break;
}
deviceDetailData = ALLOC(requiredLength);
if (deviceDetailData == NULL)
{
OOPS();
break;
}
deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
success = SetupDiGetDeviceInterfaceDetail(deviceInfo,
&deviceInterfaceData,
deviceDetailData,
requiredLength,
&requiredLength,
NULL);
if (!success)
{
OOPS();
break;
}
hHCDev = CreateFile(deviceDetailData->DevicePath,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
// If the handle is valid, then we've successfully opened a Host
// Controller. Display some info about the Host Controller itself,
// then enumerate the Root Hub attached to the Host Controller.
//
if (hHCDev != INVALID_HANDLE_VALUE)
{
EnumerateHostController(hTreeParent,
hHCDev,
deviceDetailData->DevicePath,
deviceInfo,
&deviceInfoData);
CloseHandle(hHCDev);
}
FREE(deviceDetailData);
}
SetupDiDestroyDeviceInfoList(deviceInfo);
*DevicesConnected = TotalDevicesConnected;
return;
}
//*****************************************************************************
//
// EnumerateHostController()
//
// hTreeParent - Handle of the TreeView item under which host controllers
// should be added.
//
//*****************************************************************************
VOID
EnumerateHostController (
HTREEITEM hTreeParent,
HANDLE hHCDev, _Inout_ PCHAR leafName,
_In_ HANDLE deviceInfo,
_In_ PSP_DEVINFO_DATA deviceInfoData
)
{
PCHAR driverKeyName = NULL;
HTREEITEM hHCItem = NULL;
PCHAR rootHubName = NULL;
PLIST_ENTRY listEntry = NULL;
PUSBHOSTCONTROLLERINFO hcInfo = NULL;
PUSBHOSTCONTROLLERINFO hcInfoInList = NULL;
DWORD dwSuccess;
BOOL success = FALSE;
ULONG deviceAndFunction = 0;
PUSB_DEVICE_PNP_STRINGS DevProps = NULL;
// Allocate a structure to hold information about this host controller.
//
hcInfo = (PUSBHOSTCONTROLLERINFO)ALLOC(sizeof(USBHOSTCONTROLLERINFO));
// just return if could not alloc memory
if (NULL == hcInfo)
return;
hcInfo->DeviceInfoType = HostControllerInfo;
// Obtain the driver key name for this host controller.
//
driverKeyName = GetHCDDriverKeyName(hHCDev);
if (NULL == driverKeyName)
{
// Failure obtaining driver key name.
OOPS();
FREE(hcInfo);
return;
}
// Don't enumerate this host controller again if it already
// on the list of enumerated host controllers.
//
listEntry = EnumeratedHCListHead.Flink;
while (listEntry != &EnumeratedHCListHead)
{
hcInfoInList = CONTAINING_RECORD(listEntry,
USBHOSTCONTROLLERINFO,
ListEntry);
if (strcmp(driverKeyName, hcInfoInList->DriverKey) == 0)
{
// Already on the list, exit
//
FREE(driverKeyName);
FREE(hcInfo);
return;
}
listEntry = listEntry->Flink;
}
// Obtain host controller device properties
{
size_t cbDriverName = 0;
HRESULT hr = S_OK;
hr = StringCbLength(driverKeyName, MAX_DRIVER_KEY_NAME, &cbDriverName);
if (SUCCEEDED(hr))
{
DevProps = DriverNameToDeviceProperties(driverKeyName, cbDriverName);
}
}
hcInfo->DriverKey = driverKeyName;
if (DevProps)
{
ULONG ven, dev, subsys, rev;
ven = dev = subsys = rev = 0;
if (sscanf_s(DevProps->DeviceId,
"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x",
&ven, &dev, &subsys, &rev) != 4)
{
OOPS();
}
hcInfo->VendorID = ven;
hcInfo->DeviceID = dev;
hcInfo->SubSysID = subsys;
hcInfo->Revision = rev;
hcInfo->UsbDeviceProperties = DevProps;
}
else
{
OOPS();
}
if (DevProps != NULL && DevProps->DeviceDesc != NULL)
{
leafName = DevProps->DeviceDesc;
}
else
{
OOPS();
}
// Get the USB Host Controller power map
dwSuccess = GetHostControllerPowerMap(hHCDev, hcInfo);
if (ERROR_SUCCESS != dwSuccess)
{
OOPS();
}
// Get bus, device, and function
//
hcInfo->BusDeviceFunctionValid = FALSE;
success = SetupDiGetDeviceRegistryProperty(deviceInfo,
deviceInfoData,
SPDRP_BUSNUMBER,
NULL,
(PBYTE)&hcInfo->BusNumber,
sizeof(hcInfo->BusNumber),
NULL);
if (success)
{
success = SetupDiGetDeviceRegistryProperty(deviceInfo,
deviceInfoData,
SPDRP_ADDRESS,
NULL,
(PBYTE)&deviceAndFunction,
sizeof(deviceAndFunction),
NULL);
}
if (success)
{
hcInfo->BusDevice = deviceAndFunction >> 16;
hcInfo->BusFunction = deviceAndFunction & 0xffff;
hcInfo->BusDeviceFunctionValid = TRUE;
}
// Get the USB Host Controller info
dwSuccess = GetHostControllerInfo(hHCDev, hcInfo);
if (ERROR_SUCCESS != dwSuccess)
{
OOPS();
}
// Add this host controller to the USB device tree view.
//
//hHCItem = AddLeaf(hTreeParent,
// (LPARAM)hcInfo,
// leafName,
// hcInfo->Revision == UsbSuperSpeed ? GoodSsDeviceIcon : GoodDeviceIcon);
//if (NULL == hHCItem)
//{
// // Failure adding host controller to USB device tree
// // view.
// OOPS();
// FREE(driverKeyName);
// FREE(hcInfo);
// return;
//}
// Add this host controller to the list of enumerated
// host controllers.
//
InsertTailList(&EnumeratedHCListHead,
&hcInfo->ListEntry);
// Get the name of the root hub for this host
// controller and then enumerate the root hub.
//
rootHubName = GetRootHubName(hHCDev);
if (rootHubName != NULL)
{
size_t cbHubName = 0;
HRESULT hr = S_OK;
hr = StringCbLength(rootHubName, MAX_DRIVER_KEY_NAME, &cbHubName);
if (SUCCEEDED(hr))
{
EnumerateHub(hHCItem,
rootHubName,
cbHubName,
NULL, // ConnectionInfo
NULL, // ConnectionInfoV2
NULL, // PortConnectorProps
NULL, // ConfigDesc
NULL, // BosDesc
NULL, // StringDescs
NULL); // We do not pass DevProps for RootHub
}
}
else
{
// Failure obtaining root hub name.
OOPS();
}
return;
}
//*****************************************************************************
//
// EnumerateHub()
//
// hTreeParent - Handle of the TreeView item under which this hub should be
// added.
//
// HubName - Name of this hub. This pointer is kept so the caller can neither
// free nor reuse this memory.
//
// ConnectionInfo - NULL if this is a root hub, else this is the connection
// info for an external hub. This pointer is kept so the caller can neither
// free nor reuse this memory.
//
// ConfigDesc - NULL if this is a root hub, else this is the Configuration
// Descriptor for an external hub. This pointer is kept so the caller can
// neither free nor reuse this memory.
//
// StringDescs - NULL if this is a root hub.
//
// DevProps - Device properties of the hub
//
//*****************************************************************************
VOID
EnumerateHub (
HTREEITEM hTreeParent,
_In_reads_(cbHubName) PCHAR HubName,
_In_ size_t cbHubName,
_In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo,
_In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2,
_In_opt_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps,
_In_opt_ PUSB_DESCRIPTOR_REQUEST ConfigDesc,
_In_opt_ PUSB_DESCRIPTOR_REQUEST BosDesc,
_In_opt_ PSTRING_DESCRIPTOR_NODE StringDescs,
_In_opt_ PUSB_DEVICE_PNP_STRINGS DevProps
)
{
// Initialize locals to not allocated state so the error cleanup routine
// only tries to cleanup things that were successfully allocated.
//
PUSB_NODE_INFORMATION hubInfo = NULL;
PUSB_HUB_INFORMATION_EX hubInfoEx = NULL;
PUSB_HUB_CAPABILITIES_EX hubCapabilityEx = NULL;
HANDLE hHubDevice = INVALID_HANDLE_VALUE;
HTREEITEM hItem = NULL;
PVOID info = NULL;
PCHAR deviceName = NULL;
ULONG nBytes = 0;
BOOL success = 0;
DWORD dwSizeOfLeafName = 0;
CHAR leafName[512] = {0};
HRESULT hr = S_OK;
size_t cchHeader = 0;
size_t cchFullHubName = 0;
// Allocate some space for a USBDEVICEINFO structure to hold the
// hub info, hub name, and connection info pointers. GPTR zero
// initializes the structure for us.
//
info = ALLOC(sizeof(USBEXTERNALHUBINFO));
if (info == NULL)
{
OOPS();
goto EnumerateHubError;
}
// Allocate some space for a USB_NODE_INFORMATION structure for this Hub
//
hubInfo = (PUSB_NODE_INFORMATION)ALLOC(sizeof(USB_NODE_INFORMATION));
if (hubInfo == NULL)
{
OOPS();
goto EnumerateHubError;
}
hubInfoEx = (PUSB_HUB_INFORMATION_EX)ALLOC(sizeof(USB_HUB_INFORMATION_EX));
if (hubInfoEx == NULL)
{
OOPS();
goto EnumerateHubError;
}
hubCapabilityEx = (PUSB_HUB_CAPABILITIES_EX)ALLOC(sizeof(USB_HUB_CAPABILITIES_EX));
if(hubCapabilityEx == NULL)
{
OOPS();
goto EnumerateHubError;
}
// Keep copies of the Hub Name, Connection Info, and Configuration
// Descriptor pointers
//
((PUSBROOTHUBINFO)info)->HubInfo = hubInfo;
((PUSBROOTHUBINFO)info)->HubName = HubName;
if (ConnectionInfo != NULL)
{
((PUSBEXTERNALHUBINFO)info)->DeviceInfoType = ExternalHubInfo;
((PUSBEXTERNALHUBINFO)info)->ConnectionInfo = ConnectionInfo;
((PUSBEXTERNALHUBINFO)info)->ConfigDesc = ConfigDesc;
((PUSBEXTERNALHUBINFO)info)->StringDescs = StringDescs;
((PUSBEXTERNALHUBINFO)info)->PortConnectorProps = PortConnectorProps;
((PUSBEXTERNALHUBINFO)info)->HubInfoEx = hubInfoEx;
((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx = hubCapabilityEx;
((PUSBEXTERNALHUBINFO)info)->BosDesc = BosDesc;
((PUSBEXTERNALHUBINFO)info)->ConnectionInfoV2 = ConnectionInfoV2;
((PUSBEXTERNALHUBINFO)info)->UsbDeviceProperties = DevProps;
}
else
{
((PUSBROOTHUBINFO)info)->DeviceInfoType = RootHubInfo;
((PUSBROOTHUBINFO)info)->HubInfoEx = hubInfoEx;
((PUSBROOTHUBINFO)info)->HubCapabilityEx = hubCapabilityEx;
((PUSBROOTHUBINFO)info)->PortConnectorProps = PortConnectorProps;
((PUSBROOTHUBINFO)info)->UsbDeviceProperties = DevProps;
}
// Allocate a temp buffer for the full hub device name.
//
hr = StringCbLength("\\\\.\\", MAX_DEVICE_PROP, &cchHeader);
if (FAILED(hr))
{
goto EnumerateHubError;
}
cchFullHubName = cchHeader + cbHubName + 1;
deviceName = (PCHAR)ALLOC((DWORD) cchFullHubName);
if (deviceName == NULL)
{
OOPS();
goto EnumerateHubError;
}
// Create the full hub device name
//
hr = StringCchCopyN(deviceName, cchFullHubName, "\\\\.\\", cchHeader);
if (FAILED(hr))
{
goto EnumerateHubError;
}
hr = StringCchCatN(deviceName, cchFullHubName, HubName, cbHubName);
if (FAILED(hr))
{
goto EnumerateHubError;
}
// Try to hub the open device
//
hHubDevice = CreateFile(deviceName,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
// Done with temp buffer for full hub device name
//
FREE(deviceName);
if (hHubDevice == INVALID_HANDLE_VALUE)
{
OOPS();
goto EnumerateHubError;
}
//
// Now query USBHUB for the USB_NODE_INFORMATION structure for this hub.
// This will tell us the number of downstream ports to enumerate, among
// other things.
//
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_INFORMATION,
hubInfo,
sizeof(USB_NODE_INFORMATION),
hubInfo,
sizeof(USB_NODE_INFORMATION),
&nBytes,
NULL);
if (!success)
{
OOPS();
goto EnumerateHubError;
}
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_HUB_INFORMATION_EX,
hubInfoEx,
sizeof(USB_HUB_INFORMATION_EX),
hubInfoEx,
sizeof(USB_HUB_INFORMATION_EX),
&nBytes,
NULL);
//
// Fail gracefully for downlevel OS's from Win8
//
if (!success || nBytes < sizeof(USB_HUB_INFORMATION_EX))
{
FREE(hubInfoEx);
hubInfoEx = NULL;
if (ConnectionInfo != NULL)
{
((PUSBEXTERNALHUBINFO)info)->HubInfoEx = NULL;
}
else
{
((PUSBROOTHUBINFO)info)->HubInfoEx = NULL;
}
}
//
// Obtain Hub Capabilities
//
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_HUB_CAPABILITIES_EX,
hubCapabilityEx,
sizeof(USB_HUB_CAPABILITIES_EX),
hubCapabilityEx,
sizeof(USB_HUB_CAPABILITIES_EX),
&nBytes,
NULL);
//
// Fail gracefully
//
if (!success || nBytes < sizeof(USB_HUB_CAPABILITIES_EX))
{
FREE(hubCapabilityEx);
hubCapabilityEx = NULL;
if (ConnectionInfo != NULL)
{
((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx = NULL;
}
else
{
((PUSBROOTHUBINFO)info)->HubCapabilityEx = NULL;
}
}
// Build the leaf name from the port number and the device description
//
dwSizeOfLeafName = sizeof(leafName);
if (ConnectionInfo)
{
StringCchPrintf(leafName, dwSizeOfLeafName, "[Port%d] ", ConnectionInfo->ConnectionIndex);
StringCchCat(leafName,
dwSizeOfLeafName,
ConnectionStatuses[ConnectionInfo->ConnectionStatus]);
StringCchCatN(leafName,
dwSizeOfLeafName,
" : ",
sizeof(" : "));
}
if (DevProps)
{
size_t cbDeviceDesc = 0;
hr = StringCbLength(DevProps->DeviceDesc, MAX_DRIVER_KEY_NAME, &cbDeviceDesc);
if(SUCCEEDED(hr))
{
StringCchCatN(leafName,
dwSizeOfLeafName,
DevProps->DeviceDesc,
cbDeviceDesc);
}
}
else
{
if(ConnectionInfo != NULL)
{
// External hub
StringCchCatN(leafName,
dwSizeOfLeafName,
HubName,
cbHubName);
}
else
{
// Root hub
StringCchCatN(leafName,
dwSizeOfLeafName,
"RootHub",
sizeof("RootHub"));
}
}
// Now add an item to the TreeView with the PUSBDEVICEINFO pointer info
// as the LPARAM reference value containing everything we know about the
// hub.
//
//hItem = AddLeaf(hTreeParent,
// (LPARAM)info,
// leafName,
// HubIcon);
//if (hItem == NULL)
//{
// OOPS();
// goto EnumerateHubError;
//}
// Now recursively enumerate the ports of this hub.
//
EnumerateHubPorts(
hItem,
hHubDevice,
hubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts
);
CloseHandle(hHubDevice);
return;
EnumerateHubError:
//
// Clean up any stuff that got allocated
//
if (hHubDevice != INVALID_HANDLE_VALUE)
{
CloseHandle(hHubDevice);
hHubDevice = INVALID_HANDLE_VALUE;
}
if (hubInfo)
{
FREE(hubInfo);
}
if (hubInfoEx)
{
FREE(hubInfoEx);
}
if (info)
{
FREE(info);
}
if (HubName)
{
FREE(HubName);
}
if (ConnectionInfo)
{
FREE(ConnectionInfo);
}
if (ConfigDesc)
{
FREE(ConfigDesc);
}
if (BosDesc)
{
FREE(BosDesc);
}
if (StringDescs != NULL)
{
PSTRING_DESCRIPTOR_NODE Next;
do {
Next = StringDescs->Next;
FREE(StringDescs);
StringDescs = Next;
} while (StringDescs != NULL);
}
}
//*****************************************************************************
//
// EnumerateHubPorts()
//
// hTreeParent - Handle of the TreeView item under which the hub port should
// be added.
//
// hHubDevice - Handle of the hub device to enumerate.
//
// NumPorts - Number of ports on the hub.
//
//*****************************************************************************
VOID
EnumerateHubPorts (
HTREEITEM hTreeParent,
HANDLE hHubDevice,
ULONG NumPorts
)
{
ULONG index = 0;
BOOL success = 0;
HRESULT hr = S_OK;
PCHAR driverKeyName = NULL;
PUSB_DEVICE_PNP_STRINGS DevProps;
DWORD dwSizeOfLeafName = 0;
CHAR leafName[512];
int icon = 0;
PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfoEx;
PUSB_PORT_CONNECTOR_PROPERTIES pPortConnectorProps;
USB_PORT_CONNECTOR_PROPERTIES portConnectorProps;
PUSB_DESCRIPTOR_REQUEST configDesc;
PUSB_DESCRIPTOR_REQUEST bosDesc;
PSTRING_DESCRIPTOR_NODE stringDescs;
PUSBDEVICEINFO info;
PUSB_NODE_CONNECTION_INFORMATION_EX_V2 connectionInfoExV2;
PDEVICE_INFO_NODE pNode;
// Loop over all ports of the hub.
//
// Port indices are 1 based, not 0 based.
//
for (index = 1; index <= NumPorts; index++)
{
ULONG nBytesEx;
ULONG nBytes = 0;
connectionInfoEx = NULL;
pPortConnectorProps = NULL;
ZeroMemory(&portConnectorProps, sizeof(portConnectorProps));
configDesc = NULL;
bosDesc = NULL;
stringDescs = NULL;
info = NULL;
connectionInfoExV2 = NULL;
pNode = NULL;
DevProps = NULL;
ZeroMemory(leafName, sizeof(leafName));
//
// Allocate space to hold the connection info for this port.
// For now, allocate it big enough to hold info for 30 pipes.
//
// Endpoint numbers are 0-15. Endpoint number 0 is the standard
// control endpoint which is not explicitly listed in the Configuration
// Descriptor. There can be an IN endpoint and an OUT endpoint at
// endpoint numbers 1-15 so there can be a maximum of 30 endpoints
// per device configuration.
//
// Should probably size this dynamically at some point.
//
nBytesEx = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) +
(sizeof(USB_PIPE_INFO) * 30);
connectionInfoEx = (PUSB_NODE_CONNECTION_INFORMATION_EX)ALLOC(nBytesEx);
if (connectionInfoEx == NULL)
{
OOPS();
break;
}
connectionInfoExV2 = (PUSB_NODE_CONNECTION_INFORMATION_EX_V2)
ALLOC(sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2));
if (connectionInfoExV2 == NULL)
{
OOPS();
FREE(connectionInfoEx);
break;
}
//
// Now query USBHUB for the structures
// for this port. This will tell us if a device is attached to this
// port, among other things.
// The fault tolerate code is executed first.
//
portConnectorProps.ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES,
&portConnectorProps,
sizeof(USB_PORT_CONNECTOR_PROPERTIES),
&portConnectorProps,
sizeof(USB_PORT_CONNECTOR_PROPERTIES),
&nBytes,
NULL);
if (success && nBytes == sizeof(USB_PORT_CONNECTOR_PROPERTIES))
{
pPortConnectorProps = (PUSB_PORT_CONNECTOR_PROPERTIES)
ALLOC(portConnectorProps.ActualLength);
if (pPortConnectorProps != NULL)
{
pPortConnectorProps->ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES,
pPortConnectorProps,
portConnectorProps.ActualLength,
pPortConnectorProps,
portConnectorProps.ActualLength,
&nBytes,
NULL);
if (!success || nBytes < portConnectorProps.ActualLength)
{
FREE(pPortConnectorProps);
pPortConnectorProps = NULL;
}
}
}
connectionInfoExV2->ConnectionIndex = index;
connectionInfoExV2->Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2);
connectionInfoExV2->SupportedUsbProtocols.Usb300 = 1;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
connectionInfoExV2,
sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2),
connectionInfoExV2,
sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2),
&nBytes,
NULL);
if (!success || nBytes < sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2))
{
FREE(connectionInfoExV2);
connectionInfoExV2 = NULL;
}
connectionInfoEx->ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
connectionInfoEx,
nBytesEx,
connectionInfoEx,
nBytesEx,
&nBytesEx,
NULL);
if (success)
{
//
// Since the USB_NODE_CONNECTION_INFORMATION_EX is used to display
// the device speed, but the hub driver doesn't support indication
// of superspeed, we overwrite the value if the super speed
// data structures are available and indicate the device is operating
// at SuperSpeed.
//
if (connectionInfoEx->Speed == UsbHighSpeed
&& connectionInfoExV2 != NULL
&& (connectionInfoExV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher ||
connectionInfoExV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher))
{
connectionInfoEx->Speed = UsbSuperSpeed;
}
}
else
{
PUSB_NODE_CONNECTION_INFORMATION connectionInfo = NULL;
// Try using IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
// instead of IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX
//
nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) +
sizeof(USB_PIPE_INFO) * 30;
connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)ALLOC(nBytes);
if (connectionInfo == NULL)
{
OOPS();
FREE(connectionInfoEx);
if (pPortConnectorProps != NULL)
{
FREE(pPortConnectorProps);
}
if (connectionInfoExV2 != NULL)
{
FREE(connectionInfoExV2);
}
continue;
}
connectionInfo->ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
connectionInfo,
nBytes,
connectionInfo,
nBytes,
&nBytes,
NULL);
if (!success)
{
OOPS();
FREE(connectionInfo);
FREE(connectionInfoEx);
if (pPortConnectorProps != NULL)
{
FREE(pPortConnectorProps);
}
if (connectionInfoExV2 != NULL)
{
FREE(connectionInfoExV2);
}
continue;
}
// Copy IOCTL_USB_GET_NODE_CONNECTION_INFORMATION into
// IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX structure.
//
connectionInfoEx->ConnectionIndex = connectionInfo->ConnectionIndex;
connectionInfoEx->DeviceDescriptor = connectionInfo->DeviceDescriptor;
connectionInfoEx->CurrentConfigurationValue = connectionInfo->CurrentConfigurationValue;
connectionInfoEx->Speed = connectionInfo->LowSpeed ? UsbLowSpeed : UsbFullSpeed;
connectionInfoEx->DeviceIsHub = connectionInfo->DeviceIsHub;
connectionInfoEx->DeviceAddress = connectionInfo->DeviceAddress;
connectionInfoEx->NumberOfOpenPipes = connectionInfo->NumberOfOpenPipes;
connectionInfoEx->ConnectionStatus = connectionInfo->ConnectionStatus;
memcpy(&connectionInfoEx->PipeList[0],
&connectionInfo->PipeList[0],
sizeof(USB_PIPE_INFO) * 30);
FREE(connectionInfo);
}
// Update the count of connected devices
//
if (connectionInfoEx->ConnectionStatus == DeviceConnected)
{
TotalDevicesConnected++;
}
if (connectionInfoEx->DeviceIsHub)
{
TotalHubs++;
}
// If there is a device connected, get the Device Description
//
if (connectionInfoEx->ConnectionStatus != NoDeviceConnected)
{
driverKeyName = GetDriverKeyName(hHubDevice, index);
if (driverKeyName)
{
size_t cbDriverName = 0;
hr = StringCbLength(driverKeyName, MAX_DRIVER_KEY_NAME, &cbDriverName);
if (SUCCEEDED(hr))
{
DevProps = DriverNameToDeviceProperties(driverKeyName, cbDriverName);
pNode = FindMatchingDeviceNodeForDriverName(driverKeyName, connectionInfoEx->DeviceIsHub);
}
FREE(driverKeyName);
}
}
// If there is a device connected to the port, try to retrieve the
// Configuration Descriptor from the device.
//
if (gDoConfigDesc &&
connectionInfoEx->ConnectionStatus == DeviceConnected)
{
configDesc = GetConfigDescriptor(hHubDevice,
index,
0);
}
else
{
configDesc = NULL;
}
if (configDesc != NULL &&
connectionInfoEx->DeviceDescriptor.bcdUSB > 0x0200)
{
bosDesc = GetBOSDescriptor(hHubDevice,
index);
}
else
{
bosDesc = NULL;
}
if (configDesc != NULL &&
AreThereStringDescriptors(&connectionInfoEx->DeviceDescriptor,
(PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1)))
{
stringDescs = GetAllStringDescriptors (
hHubDevice,
index,
&connectionInfoEx->DeviceDescriptor,
(PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1));
}
else
{
stringDescs = NULL;
}
// If the device connected to the port is an external hub, get the
// name of the external hub and recursively enumerate it.
//
if (connectionInfoEx->DeviceIsHub)
{
PCHAR extHubName;
size_t cbHubName = 0;
extHubName = GetExternalHubName(hHubDevice, index);
if (extHubName != NULL)
{
hr = StringCbLength(extHubName, MAX_DRIVER_KEY_NAME, &cbHubName);
if (SUCCEEDED(hr))
{
EnumerateHub(hTreeParent, //hPortItem,
extHubName,
cbHubName,
connectionInfoEx,
connectionInfoExV2,
pPortConnectorProps,
configDesc,
bosDesc,
stringDescs,
DevProps);
}
}
}
else
{
// Allocate some space for a USBDEVICEINFO structure to hold the
// hub info, hub name, and connection info pointers. GPTR zero
// initializes the structure for us.
//
info = (PUSBDEVICEINFO) ALLOC(sizeof(USBDEVICEINFO));
if (info == NULL)
{
OOPS();
if (configDesc != NULL)
{
FREE(configDesc);
}
if (bosDesc != NULL)
{
FREE(bosDesc);
}
FREE(connectionInfoEx);
if (pPortConnectorProps != NULL)
{
FREE(pPortConnectorProps);
}
if (connectionInfoExV2 != NULL)
{
FREE(connectionInfoExV2);
}
break;
}
info->DeviceInfoType = DeviceInfo;
info->ConnectionInfo = connectionInfoEx;
info->PortConnectorProps = pPortConnectorProps;
info->ConfigDesc = configDesc;
info->StringDescs = stringDescs;
info->BosDesc = bosDesc;
info->ConnectionInfoV2 = connectionInfoExV2;
info->UsbDeviceProperties = DevProps;
info->DeviceInfoNode = pNode;
StringCchPrintf(leafName, sizeof(leafName), "[Port%d] ", index);
// Add error description if ConnectionStatus is other than NoDeviceConnected / DeviceConnected
StringCchCat(leafName,
sizeof(leafName),
ConnectionStatuses[connectionInfoEx->ConnectionStatus]);
if (DevProps)
{
size_t cchDeviceDesc = 0;
hr = StringCbLength(DevProps->DeviceDesc, MAX_DEVICE_PROP, &cchDeviceDesc);
if (FAILED(hr))
{
OOPS();
}
dwSizeOfLeafName = sizeof(leafName);
StringCchCatN(leafName,
dwSizeOfLeafName - 1,
" : ",
sizeof(" : "));
StringCchCatN(leafName,
dwSizeOfLeafName - 1,
DevProps->DeviceDesc,
cchDeviceDesc );
}
if (connectionInfoEx->ConnectionStatus == NoDeviceConnected)
{
if (connectionInfoExV2 != NULL &&
connectionInfoExV2->SupportedUsbProtocols.Usb300 == 1)
{
icon = NoSsDeviceIcon;
}
else
{
icon = NoDeviceIcon;
}
}
else if (connectionInfoEx->CurrentConfigurationValue)
{
if (connectionInfoEx->Speed == UsbSuperSpeed)
{
icon = GoodSsDeviceIcon;
}
else
{
icon = GoodDeviceIcon;
}
}
else
{
icon = BadDeviceIcon;
}
//AddLeaf(hTreeParent, //hPortItem,
// (LPARAM)info,
// leafName,
// icon);
}
} // for
}
//*****************************************************************************
//
// WideStrToMultiStr()
//
//*****************************************************************************
PCHAR WideStrToMultiStr (
_In_reads_bytes_(cbWideStr) PWCHAR WideStr,
_In_ size_t cbWideStr
)
{
ULONG nBytes = 0;
PCHAR MultiStr = NULL;
PWCHAR pWideStr = NULL;
// Use local string to guarantee zero termination
pWideStr = (PWCHAR) ALLOC((DWORD) cbWideStr + sizeof(WCHAR));
if (NULL == pWideStr)
{
return NULL;
}
memset(pWideStr, 0, cbWideStr + sizeof(WCHAR));
memcpy(pWideStr, WideStr, cbWideStr);
// Get the length of the converted string
//
nBytes = WideCharToMultiByte(
CP_ACP,
WC_NO_BEST_FIT_CHARS,
pWideStr,
-1,
NULL,
0,
NULL,
NULL);
if (nBytes == 0)
{
FREE(pWideStr);
return NULL;
}
// Allocate space to hold the converted string
//
MultiStr = ALLOC(nBytes);
if (MultiStr == NULL)
{
FREE(pWideStr);
return NULL;
}
// Convert the string
//
nBytes = WideCharToMultiByte(
CP_ACP,
WC_NO_BEST_FIT_CHARS,
pWideStr,
-1,
MultiStr,
nBytes,
NULL,
NULL);
if (nBytes == 0)
{
FREE(MultiStr);
FREE(pWideStr);
return NULL;
}
FREE(pWideStr);
return MultiStr;
}
//*****************************************************************************
//
// GetRootHubName()
//
//*****************************************************************************
PCHAR GetRootHubName (
HANDLE HostController
)
{
BOOL success = 0;
ULONG nBytes = 0;
USB_ROOT_HUB_NAME rootHubName;
PUSB_ROOT_HUB_NAME rootHubNameW = NULL;
PCHAR rootHubNameA = NULL;
// Get the length of the name of the Root Hub attached to the
// Host Controller
//
success = DeviceIoControl(HostController,
IOCTL_USB_GET_ROOT_HUB_NAME,
0,
0,
&rootHubName,
sizeof(rootHubName),
&nBytes,
NULL);
if (!success)
{
OOPS();
goto GetRootHubNameError;
}
// Allocate space to hold the Root Hub name
//
nBytes = rootHubName.ActualLength;
rootHubNameW = ALLOC(nBytes);
if (rootHubNameW == NULL)
{
OOPS();
goto GetRootHubNameError;
}
// Get the name of the Root Hub attached to the Host Controller
//
success = DeviceIoControl(HostController,
IOCTL_USB_GET_ROOT_HUB_NAME,
NULL,
0,
rootHubNameW,
nBytes,
&nBytes,
NULL);
if (!success)
{
OOPS();
goto GetRootHubNameError;
}
// Convert the Root Hub name
//
rootHubNameA = WideStrToMultiStr(rootHubNameW->RootHubName, nBytes - sizeof(USB_ROOT_HUB_NAME) + sizeof(WCHAR));
// All done, free the uncoverted Root Hub name and return the
// converted Root Hub name
//
FREE(rootHubNameW);
return rootHubNameA;
GetRootHubNameError:
// There was an error, free anything that was allocated
//
if (rootHubNameW != NULL)
{
FREE(rootHubNameW);
rootHubNameW = NULL;
}
return NULL;
}
//*****************************************************************************
//
// GetExternalHubName()
//
//*****************************************************************************
PCHAR GetExternalHubName (
HANDLE Hub,
ULONG ConnectionIndex
)
{
BOOL success = 0;
ULONG nBytes = 0;
USB_NODE_CONNECTION_NAME extHubName;
PUSB_NODE_CONNECTION_NAME extHubNameW = NULL;
PCHAR extHubNameA = NULL;
// Get the length of the name of the external hub attached to the
// specified port.
//
extHubName.ConnectionIndex = ConnectionIndex;
success = DeviceIoControl(Hub,
IOCTL_USB_GET_NODE_CONNECTION_NAME,
&extHubName,
sizeof(extHubName),
&extHubName,
sizeof(extHubName),
&nBytes,
NULL);
if (!success)
{
OOPS();
goto GetExternalHubNameError;
}
// Allocate space to hold the external hub name
//
nBytes = extHubName.ActualLength;
if (nBytes <= sizeof(extHubName))
{
OOPS();
goto GetExternalHubNameError;
}
extHubNameW = ALLOC(nBytes);
if (extHubNameW == NULL)
{
OOPS();
goto GetExternalHubNameError;
}
// Get the name of the external hub attached to the specified port
//
extHubNameW->ConnectionIndex = ConnectionIndex;
success = DeviceIoControl(Hub,
IOCTL_USB_GET_NODE_CONNECTION_NAME,
extHubNameW,
nBytes,
extHubNameW,
nBytes,
&nBytes,
NULL);
if (!success)
{
OOPS();
goto GetExternalHubNameError;
}
// Convert the External Hub name
//
extHubNameA = WideStrToMultiStr(extHubNameW->NodeName, nBytes - sizeof(USB_NODE_CONNECTION_NAME) + sizeof(WCHAR));
// All done, free the uncoverted external hub name and return the
// converted external hub name
//
FREE(extHubNameW);
return extHubNameA;
GetExternalHubNameError:
// There was an error, free anything that was allocated
//
if (extHubNameW != NULL)
{
FREE(extHubNameW);
extHubNameW = NULL;
}
return NULL;
}
//*****************************************************************************
//
// GetDriverKeyName()
//
//*****************************************************************************
PCHAR GetDriverKeyName (
HANDLE Hub,
ULONG ConnectionIndex
)
{
BOOL success = 0;
ULONG nBytes = 0;
USB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyName;
PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyNameW = NULL;
PCHAR driverKeyNameA = NULL;
// Get the length of the name of the driver key of the device attached to
// the specified port.
//
driverKeyName.ConnectionIndex = ConnectionIndex;
success = DeviceIoControl(Hub,
IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
&driverKeyName,
sizeof(driverKeyName),
&driverKeyName,
sizeof(driverKeyName),
&nBytes,
NULL);
if (!success)
{
OOPS();
goto GetDriverKeyNameError;
}
// Allocate space to hold the driver key name
//
nBytes = driverKeyName.ActualLength;
if (nBytes <= sizeof(driverKeyName))
{
OOPS();
goto GetDriverKeyNameError;
}
driverKeyNameW = ALLOC(nBytes);
if (driverKeyNameW == NULL)
{
OOPS();
goto GetDriverKeyNameError;
}
// Get the name of the driver key of the device attached to
// the specified port.
//
driverKeyNameW->ConnectionIndex = ConnectionIndex;
success = DeviceIoControl(Hub,
IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
driverKeyNameW,
nBytes,
driverKeyNameW,
nBytes,
&nBytes,
NULL);
if (!success)
{
OOPS();
goto GetDriverKeyNameError;
}
// Convert the driver key name
//
driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName, nBytes - sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME) + sizeof(WCHAR));
// All done, free the uncoverted driver key name and return the
// converted driver key name
//
FREE(driverKeyNameW);
return driverKeyNameA;
GetDriverKeyNameError:
// There was an error, free anything that was allocated
//
if (driverKeyNameW != NULL)
{
FREE(driverKeyNameW);
driverKeyNameW = NULL;
}
return NULL;
}
//*****************************************************************************
//
// GetHCDDriverKeyName()
//
//*****************************************************************************
PCHAR GetHCDDriverKeyName (
HANDLE HCD
)
{
BOOL success = 0;
ULONG nBytes = 0;
USB_HCD_DRIVERKEY_NAME driverKeyName = {0};
PUSB_HCD_DRIVERKEY_NAME driverKeyNameW = NULL;
PCHAR driverKeyNameA = NULL;
ZeroMemory(&driverKeyName, sizeof(driverKeyName));
// Get the length of the name of the driver key of the HCD
//
success = DeviceIoControl(HCD,
IOCTL_GET_HCD_DRIVERKEY_NAME,
&driverKeyName,
sizeof(driverKeyName),
&driverKeyName,
sizeof(driverKeyName),
&nBytes,
NULL);
if (!success)
{
OOPS();
goto GetHCDDriverKeyNameError;
}
// Allocate space to hold the driver key name
//
nBytes = driverKeyName.ActualLength;
if (nBytes <= sizeof(driverKeyName))
{
OOPS();
goto GetHCDDriverKeyNameError;
}
driverKeyNameW = ALLOC(nBytes);
if (driverKeyNameW == NULL)
{
OOPS();
goto GetHCDDriverKeyNameError;
}
// Get the name of the driver key of the device attached to
// the specified port.
//
success = DeviceIoControl(HCD,
IOCTL_GET_HCD_DRIVERKEY_NAME,
driverKeyNameW,
nBytes,
driverKeyNameW,
nBytes,
&nBytes,
NULL);
if (!success)
{
OOPS();
goto GetHCDDriverKeyNameError;
}
//
// Convert the driver key name
// Pass the length of the DriverKeyName string
//
driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName, nBytes - sizeof(USB_HCD_DRIVERKEY_NAME) + sizeof(WCHAR));
// All done, free the uncoverted driver key name and return the
// converted driver key name
//
FREE(driverKeyNameW);
return driverKeyNameA;
GetHCDDriverKeyNameError:
// There was an error, free anything that was allocated
//
if (driverKeyNameW != NULL)
{
FREE(driverKeyNameW);
driverKeyNameW = NULL;
}
return NULL;
}
//*****************************************************************************
//
// GetConfigDescriptor()
//
// hHubDevice - Handle of the hub device containing the port from which the
// Configuration Descriptor will be requested.
//
// ConnectionIndex - Identifies the port on the hub to which a device is
// attached from which the Configuration Descriptor will be requested.
//
// DescriptorIndex - Configuration Descriptor index, zero based.
//
//*****************************************************************************
PUSB_DESCRIPTOR_REQUEST
GetConfigDescriptor (
HANDLE hHubDevice,
ULONG ConnectionIndex,
UCHAR DescriptorIndex
)
{
BOOL success = 0;
ULONG nBytes = 0;
ULONG nBytesReturned = 0;
UCHAR configDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) +
sizeof(USB_CONFIGURATION_DESCRIPTOR)];
PUSB_DESCRIPTOR_REQUEST configDescReq = NULL;
PUSB_CONFIGURATION_DESCRIPTOR configDesc = NULL;
// Request the Configuration Descriptor the first time using our
// local buffer, which is just big enough for the Cofiguration
// Descriptor itself.
//
nBytes = sizeof(configDescReqBuf);
configDescReq = (PUSB_DESCRIPTOR_REQUEST)configDescReqBuf;
configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1);
// Zero fill the entire request structure
//
memset(configDescReq, 0, nBytes);
// Indicate the port from which the descriptor will be requested
//
configDescReq->ConnectionIndex = ConnectionIndex;
//
// USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
// IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
//
// USBD will automatically initialize these fields:
// bmRequest = 0x80
// bRequest = 0x06
//
// We must inititialize these fields:
// wValue = Descriptor Type (high) and Descriptor Index (low byte)
// wIndex = Zero (or Language ID for String Descriptors)
// wLength = Length of descriptor buffer
//
configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8)
| DescriptorIndex;
configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
// Now issue the get descriptor request.
//
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
configDescReq,
nBytes,
configDescReq,
nBytes,
&nBytesReturned,
NULL);
if (!success)
{
OOPS();
return NULL;
}
if (nBytes != nBytesReturned)
{
OOPS();
return NULL;
}
if (configDesc->wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
{
OOPS();
return NULL;
}
// Now request the entire Configuration Descriptor using a dynamically
// allocated buffer which is sized big enough to hold the entire descriptor
//
nBytes = sizeof(USB_DESCRIPTOR_REQUEST) + configDesc->wTotalLength;
configDescReq = (PUSB_DESCRIPTOR_REQUEST)ALLOC(nBytes);
if (configDescReq == NULL)
{
OOPS();
return NULL;
}
configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1);
// Indicate the port from which the descriptor will be requested
//
configDescReq->ConnectionIndex = ConnectionIndex;
//
// USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
// IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
//
// USBD will automatically initialize these fields:
// bmRequest = 0x80
// bRequest = 0x06
//
// We must inititialize these fields:
// wValue = Descriptor Type (high) and Descriptor Index (low byte)
// wIndex = Zero (or Language ID for String Descriptors)
// wLength = Length of descriptor buffer
//
configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8)
| DescriptorIndex;
configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
// Now issue the get descriptor request.
//
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
configDescReq,
nBytes,
configDescReq,
nBytes,
&nBytesReturned,
NULL);
if (!success)
{
OOPS();
FREE(configDescReq);
return NULL;
}
if (nBytes != nBytesReturned)
{
OOPS();
FREE(configDescReq);
return NULL;
}
if (configDesc->wTotalLength != (nBytes - sizeof(USB_DESCRIPTOR_REQUEST)))
{
OOPS();
FREE(configDescReq);
return NULL;
}
return configDescReq;
}
//*****************************************************************************
//
// GetBOSDescriptor()
//
// hHubDevice - Handle of the hub device containing the port from which the
// Configuration Descriptor will be requested.
//
// ConnectionIndex - Identifies the port on the hub to which a device is
// attached from which the BOS Descriptor will be requested.
//
//*****************************************************************************
PUSB_DESCRIPTOR_REQUEST
GetBOSDescriptor (
HANDLE hHubDevice,
ULONG ConnectionIndex
)
{
BOOL success = 0;
ULONG nBytes = 0;
ULONG nBytesReturned = 0;
UCHAR bosDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) +
sizeof(USB_BOS_DESCRIPTOR)];
PUSB_DESCRIPTOR_REQUEST bosDescReq = NULL;
PUSB_BOS_DESCRIPTOR bosDesc = NULL;
// Request the BOS Descriptor the first time using our
// local buffer, which is just big enough for the BOS
// Descriptor itself.
//
nBytes = sizeof(bosDescReqBuf);
bosDescReq = (PUSB_DESCRIPTOR_REQUEST)bosDescReqBuf;
bosDesc = (PUSB_BOS_DESCRIPTOR)(bosDescReq+1);
// Zero fill the entire request structure
//
memset(bosDescReq, 0, nBytes);
// Indicate the port from which the descriptor will be requested
//
bosDescReq->ConnectionIndex = ConnectionIndex;
//
// USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
// IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
//
// USBD will automatically initialize these fields:
// bmRequest = 0x80
// bRequest = 0x06
//
// We must inititialize these fields:
// wValue = Descriptor Type (high) and Descriptor Index (low byte)
// wIndex = Zero (or Language ID for String Descriptors)
// wLength = Length of descriptor buffer
//
bosDescReq->SetupPacket.wValue = (USB_BOS_DESCRIPTOR_TYPE << 8);
bosDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
// Now issue the get descriptor request.
//
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
bosDescReq,
nBytes,
bosDescReq,
nBytes,
&nBytesReturned,
NULL);
if (!success)
{
OOPS();
return NULL;
}
if (nBytes != nBytesReturned)
{
OOPS();
return NULL;
}
if (bosDesc->wTotalLength < sizeof(USB_BOS_DESCRIPTOR))
{
OOPS();
return NULL;
}
// Now request the entire BOS Descriptor using a dynamically
// allocated buffer which is sized big enough to hold the entire descriptor
//
nBytes = sizeof(USB_DESCRIPTOR_REQUEST) + bosDesc->wTotalLength;
bosDescReq = (PUSB_DESCRIPTOR_REQUEST)ALLOC(nBytes);
if (bosDescReq == NULL)
{
OOPS();
return NULL;
}
bosDesc = (PUSB_BOS_DESCRIPTOR)(bosDescReq+1);
// Indicate the port from which the descriptor will be requested
//
bosDescReq->ConnectionIndex = ConnectionIndex;
//
// USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
// IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
//
// USBD will automatically initialize these fields:
// bmRequest = 0x80
// bRequest = 0x06
//
// We must inititialize these fields:
// wValue = Descriptor Type (high) and Descriptor Index (low byte)
// wIndex = Zero (or Language ID for String Descriptors)
// wLength = Length of descriptor buffer
//
bosDescReq->SetupPacket.wValue = (USB_BOS_DESCRIPTOR_TYPE << 8);
bosDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
// Now issue the get descriptor request.
//
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
bosDescReq,
nBytes,
bosDescReq,
nBytes,
&nBytesReturned,
NULL);
if (!success)
{
OOPS();
FREE(bosDescReq);
return NULL;
}
if (nBytes != nBytesReturned)
{
OOPS();
FREE(bosDescReq);
return NULL;
}
if (bosDesc->wTotalLength != (nBytes - sizeof(USB_DESCRIPTOR_REQUEST)))
{
OOPS();
FREE(bosDescReq);
return NULL;
}
return bosDescReq;
}
//*****************************************************************************
//
// AreThereStringDescriptors()
//
// DeviceDesc - Device Descriptor for which String Descriptors should be
// checked.
//
// ConfigDesc - Configuration Descriptor (also containing Interface Descriptor)
// for which String Descriptors should be checked.
//
//*****************************************************************************
BOOL
AreThereStringDescriptors (
PUSB_DEVICE_DESCRIPTOR DeviceDesc,
PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc
)
{
PUCHAR descEnd = NULL;
PUSB_COMMON_DESCRIPTOR commonDesc = NULL;
//
// Check Device Descriptor strings
//
if (DeviceDesc->iManufacturer ||
DeviceDesc->iProduct ||
DeviceDesc->iSerialNumber
)
{
return TRUE;
}
//
// Check the Configuration and Interface Descriptor strings
//
descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength;
commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc;
while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
(PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
{
switch (commonDesc->bDescriptorType)
{
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE:
if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR))
{
OOPS();
break;
}
if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration)
{
return TRUE;
}
commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength);
continue;
case USB_INTERFACE_DESCRIPTOR_TYPE:
if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) &&
commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))
{
OOPS();
break;
}
if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface)
{
return TRUE;
}
commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength);
continue;
default:
commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength);
continue;
}
break;
}
return FALSE;
}
//*****************************************************************************
//
// GetAllStringDescriptors()
//
// hHubDevice - Handle of the hub device containing the port from which the
// String Descriptors will be requested.
//
// ConnectionIndex - Identifies the port on the hub to which a device is
// attached from which the String Descriptors will be requested.
//
// DeviceDesc - Device Descriptor for which String Descriptors should be
// requested.
//
// ConfigDesc - Configuration Descriptor (also containing Interface Descriptor)
// for which String Descriptors should be requested.
//
//*****************************************************************************
PSTRING_DESCRIPTOR_NODE
GetAllStringDescriptors (
HANDLE hHubDevice,
ULONG ConnectionIndex,
PUSB_DEVICE_DESCRIPTOR DeviceDesc,
PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc
)
{
PSTRING_DESCRIPTOR_NODE supportedLanguagesString = NULL;
ULONG numLanguageIDs = 0;
USHORT *languageIDs = NULL;
PUCHAR descEnd = NULL;
PUSB_COMMON_DESCRIPTOR commonDesc = NULL;
UCHAR uIndex = 1;
UCHAR bInterfaceClass = 0;
BOOL getMoreStrings = FALSE;
HRESULT hr = S_OK;
//
// Get the array of supported Language IDs, which is returned
// in String Descriptor 0
//
supportedLanguagesString = GetStringDescriptor(hHubDevice,
ConnectionIndex,
0,
0);
if (supportedLanguagesString == NULL)
{
return NULL;
}
numLanguageIDs = (supportedLanguagesString->StringDescriptor->bLength - 2) / 2;
languageIDs = &supportedLanguagesString->StringDescriptor->bString[0];
//
// Get the Device Descriptor strings
//
if (DeviceDesc->iManufacturer)
{
GetStringDescriptors(hHubDevice,
ConnectionIndex,
DeviceDesc->iManufacturer,
numLanguageIDs,
languageIDs,
supportedLanguagesString);
}
if (DeviceDesc->iProduct)
{
GetStringDescriptors(hHubDevice,
ConnectionIndex,
DeviceDesc->iProduct,
numLanguageIDs,
languageIDs,
supportedLanguagesString);
}
if (DeviceDesc->iSerialNumber)
{
GetStringDescriptors(hHubDevice,
ConnectionIndex,
DeviceDesc->iSerialNumber,
numLanguageIDs,
languageIDs,
supportedLanguagesString);
}
//
// Get the Configuration and Interface Descriptor strings
//
descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength;
commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc;
while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
(PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
{
switch (commonDesc->bDescriptorType)
{
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR))
{
OOPS();
break;
}
if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration)
{
GetStringDescriptors(hHubDevice,
ConnectionIndex,
((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration,
numLanguageIDs,
languageIDs,
supportedLanguagesString);
}
commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength);
continue;
case USB_IAD_DESCRIPTOR_TYPE:
if (commonDesc->bLength < sizeof(USB_IAD_DESCRIPTOR))
{
OOPS();
break;
}
if (((PUSB_IAD_DESCRIPTOR)commonDesc)->iFunction)
{
GetStringDescriptors(hHubDevice,
ConnectionIndex,
((PUSB_IAD_DESCRIPTOR)commonDesc)->iFunction,
numLanguageIDs,
languageIDs,
supportedLanguagesString);
}
commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength);
continue;
case USB_INTERFACE_DESCRIPTOR_TYPE:
if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) &&
commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))
{
OOPS();
break;
}
if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface)
{
GetStringDescriptors(hHubDevice,
ConnectionIndex,
((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface,
numLanguageIDs,
languageIDs,
supportedLanguagesString);
}
//
// We need to display more string descriptors for the following
// interface classes
//
bInterfaceClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceClass;
if (bInterfaceClass == USB_DEVICE_CLASS_VIDEO)
{
getMoreStrings = TRUE;
}
commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength);
continue;
default:
commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength);
continue;
}
break;
}
if (getMoreStrings)
{
//
// We might need to display strings later that are referenced only in
// class-specific descriptors. Get String Descriptors 1 through 32 (an
// arbitrary upper limit for Strings needed due to "bad devices"
// returning an infinite repeat of Strings 0 through 4) until one is not
// found.
//
// There are also "bad devices" that have issues even querying 1-32, but
// historically USBView made this query, so the query should be safe for
// video devices.
//
for (uIndex = 1; SUCCEEDED(hr) && (uIndex < NUM_STRING_DESC_TO_GET); uIndex++)
{
hr = GetStringDescriptors(hHubDevice,
ConnectionIndex,
uIndex,
numLanguageIDs,
languageIDs,
supportedLanguagesString);
}
}
return supportedLanguagesString;
}
//*****************************************************************************
//
// GetStringDescriptor()
//
// hHubDevice - Handle of the hub device containing the port from which the
// String Descriptor will be requested.
//
// ConnectionIndex - Identifies the port on the hub to which a device is
// attached from which the String Descriptor will be requested.
//
// DescriptorIndex - String Descriptor index.
//
// LanguageID - Language in which the string should be requested.
//
//*****************************************************************************
PSTRING_DESCRIPTOR_NODE
GetStringDescriptor (
HANDLE hHubDevice,
ULONG ConnectionIndex,
UCHAR DescriptorIndex,
USHORT LanguageID
)
{
BOOL success = 0;
ULONG nBytes = 0;
ULONG nBytesReturned = 0;
UCHAR stringDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) +
MAXIMUM_USB_STRING_LENGTH];
PUSB_DESCRIPTOR_REQUEST stringDescReq = NULL;
PUSB_STRING_DESCRIPTOR stringDesc = NULL;
PSTRING_DESCRIPTOR_NODE stringDescNode = NULL;
nBytes = sizeof(stringDescReqBuf);
stringDescReq = (PUSB_DESCRIPTOR_REQUEST)stringDescReqBuf;
stringDesc = (PUSB_STRING_DESCRIPTOR)(stringDescReq+1);
// Zero fill the entire request structure
//
memset(stringDescReq, 0, nBytes);
// Indicate the port from which the descriptor will be requested
//
stringDescReq->ConnectionIndex = ConnectionIndex;
//
// USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
// IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
//
// USBD will automatically initialize these fields:
// bmRequest = 0x80
// bRequest = 0x06
//
// We must inititialize these fields:
// wValue = Descriptor Type (high) and Descriptor Index (low byte)
// wIndex = Zero (or Language ID for String Descriptors)
// wLength = Length of descriptor buffer
//
stringDescReq->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8)
| DescriptorIndex;
stringDescReq->SetupPacket.wIndex = LanguageID;
stringDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
// Now issue the get descriptor request.
//
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
stringDescReq,
nBytes,
stringDescReq,
nBytes,
&nBytesReturned,
NULL);
//
// Do some sanity checks on the return from the get descriptor request.
//
if (!success)
{
OOPS();
return NULL;
}
if (nBytesReturned < 2)
{
OOPS();
return NULL;
}
if (stringDesc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE)
{
OOPS();
return NULL;
}
if (stringDesc->bLength != nBytesReturned - sizeof(USB_DESCRIPTOR_REQUEST))
{
OOPS();
return NULL;
}
if (stringDesc->bLength % 2 != 0)
{
OOPS();
return NULL;
}
//
// Looks good, allocate some (zero filled) space for the string descriptor
// node and copy the string descriptor to it.
//
stringDescNode = (PSTRING_DESCRIPTOR_NODE)ALLOC(sizeof(STRING_DESCRIPTOR_NODE) +
stringDesc->bLength);
if (stringDescNode == NULL)
{
OOPS();
return NULL;
}
stringDescNode->DescriptorIndex = DescriptorIndex;
stringDescNode->LanguageID = LanguageID;
memcpy(stringDescNode->StringDescriptor,
stringDesc,
stringDesc->bLength);
return stringDescNode;
}
//*****************************************************************************
//
// GetStringDescriptors()
//
// hHubDevice - Handle of the hub device containing the port from which the
// String Descriptor will be requested.
//
// ConnectionIndex - Identifies the port on the hub to which a device is
// attached from which the String Descriptor will be requested.
//
// DescriptorIndex - String Descriptor index.
//
// NumLanguageIDs - Number of languages in which the string should be
// requested.
//
// LanguageIDs - Languages in which the string should be requested.
//
// StringDescNodeHead - First node in linked list of device's string descriptors
//
// Return Value: HRESULT indicating whether the string is on the list
//
//*****************************************************************************
HRESULT
GetStringDescriptors (
_In_ HANDLE hHubDevice,
_In_ ULONG ConnectionIndex,
_In_ UCHAR DescriptorIndex,
_In_ ULONG NumLanguageIDs,
_In_reads_(NumLanguageIDs) USHORT *LanguageIDs,
_In_ PSTRING_DESCRIPTOR_NODE StringDescNodeHead
)
{
PSTRING_DESCRIPTOR_NODE tail = NULL;
PSTRING_DESCRIPTOR_NODE trailing = NULL;
ULONG i = 0;
//
// Go to the end of the linked list, searching for the requested index to
// see if we've already retrieved it
//
for (tail = StringDescNodeHead; tail != NULL; tail = tail->Next)
{
if (tail->DescriptorIndex == DescriptorIndex)
{
return S_OK;
}
trailing = tail;
}
tail = trailing;
//
// Get the next String Descriptor. If this is NULL, then we're done (return)
// Otherwise, loop through all Language IDs
//
for (i = 0; (tail != NULL) && (i < NumLanguageIDs); i++)
{
tail->Next = GetStringDescriptor(hHubDevice,
ConnectionIndex,
DescriptorIndex,
LanguageIDs[i]);
tail = tail->Next;
}
if (tail == NULL)
{
return E_FAIL;
} else {
return S_OK;
}
}
//*****************************************************************************
//
// CleanupItem()
//
//*****************************************************************************
VOID
CleanupItem (
HWND hTreeWnd,
HTREEITEM hTreeItem,
PVOID pContext
)
{
TV_ITEM tvi;
PVOID info = NULL;
UNREFERENCED_PARAMETER(pContext);
tvi.mask = TVIF_HANDLE | TVIF_PARAM;
tvi.hItem = hTreeItem;
TreeView_GetItem(hTreeWnd,
&tvi);
info = (PVOID)tvi.lParam;
if (info)
{
PCHAR DriverKey = NULL;
PUSB_NODE_INFORMATION HubInfo = NULL;
PCHAR HubName = NULL;
PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfoEx = NULL;
PUSB_DESCRIPTOR_REQUEST ConfigDesc = NULL;
PUSB_DESCRIPTOR_REQUEST BosDesc = NULL;
PSTRING_DESCRIPTOR_NODE StringDescs = NULL;
PUSB_HUB_INFORMATION_EX HubInfoEx = NULL;
PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps = NULL;
PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 = NULL;
PUSB_HUB_CAPABILITIES_EX HubCapabilityEx = NULL;
PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties = NULL;
PUSB_CONTROLLER_INFO_0 ControllerInfo = NULL;
//
// All structures except DEVICE_INFO_NODE are free'd up here. DEVICE_INFO_NODE structures are free'd while
// destroying device info lists (ClearDeviceList())
//
switch (*(PUSBDEVICEINFOTYPE)info)
{
case HostControllerInfo:
//
// Remove this host controller from the list of enumerated
// host controllers.
//
RemoveEntryList(&((PUSBHOSTCONTROLLERINFO)info)->ListEntry);
DriverKey = ((PUSBHOSTCONTROLLERINFO)info)->DriverKey;
ControllerInfo = ((PUSBHOSTCONTROLLERINFO)info)->ControllerInfo;
UsbDeviceProperties = ((PUSBHOSTCONTROLLERINFO)info)->UsbDeviceProperties;
break;
case RootHubInfo:
HubInfo = ((PUSBROOTHUBINFO)info)->HubInfo;
HubInfoEx = ((PUSBROOTHUBINFO)info)->HubInfoEx;
HubName = ((PUSBROOTHUBINFO)info)->HubName;
PortConnectorProps = ((PUSBROOTHUBINFO)info)->PortConnectorProps;
UsbDeviceProperties = ((PUSBROOTHUBINFO)info)->UsbDeviceProperties;
HubCapabilityEx = ((PUSBROOTHUBINFO)info)->HubCapabilityEx;
break;
case ExternalHubInfo:
HubInfo = ((PUSBEXTERNALHUBINFO)info)->HubInfo;
HubInfoEx = ((PUSBEXTERNALHUBINFO)info)->HubInfoEx;
HubName = ((PUSBEXTERNALHUBINFO)info)->HubName;
ConnectionInfoEx = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfo;
PortConnectorProps = ((PUSBEXTERNALHUBINFO)info)->PortConnectorProps;
ConfigDesc = ((PUSBEXTERNALHUBINFO)info)->ConfigDesc;
BosDesc = ((PUSBEXTERNALHUBINFO)info)->BosDesc;
StringDescs = ((PUSBEXTERNALHUBINFO)info)->StringDescs;
ConnectionInfoV2 = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfoV2;
UsbDeviceProperties = ((PUSBEXTERNALHUBINFO)info)->UsbDeviceProperties;
HubCapabilityEx = ((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx;
break;
case DeviceInfo:
ConnectionInfoEx = ((PUSBDEVICEINFO)info)->ConnectionInfo;
PortConnectorProps = ((PUSBDEVICEINFO)info)->PortConnectorProps;
ConfigDesc = ((PUSBDEVICEINFO)info)->ConfigDesc;
BosDesc = ((PUSBDEVICEINFO)info)->BosDesc;
StringDescs = ((PUSBDEVICEINFO)info)->StringDescs;
ConnectionInfoV2 = ((PUSBDEVICEINFO)info)->ConnectionInfoV2;
UsbDeviceProperties = ((PUSBDEVICEINFO)info)->UsbDeviceProperties;
break;
}
if(UsbDeviceProperties)
{
FreeDeviceProperties(&UsbDeviceProperties);
}
if(ControllerInfo)
{
FREE(ControllerInfo);
}
if(HubCapabilityEx)
{
FREE(HubCapabilityEx);
}
if (DriverKey)
{
FREE(DriverKey);
}
if (HubInfo)
{
FREE(HubInfo);
}
if (HubName)
{
FREE(HubName);
}
if (ConfigDesc)
{
FREE(ConfigDesc);
}
if (BosDesc)
{
FREE(BosDesc);
}
if (StringDescs)
{
PSTRING_DESCRIPTOR_NODE Next;
do {
Next = StringDescs->Next;
FREE(StringDescs);
StringDescs = Next;
} while (StringDescs);
}
if (ConnectionInfoEx)
{
FREE(ConnectionInfoEx);
}
if (HubInfoEx)
{
FREE(HubInfoEx);
}
if (PortConnectorProps)
{
FREE(PortConnectorProps);
}
if (ConnectionInfoV2)
{
FREE(ConnectionInfoV2);
}
FREE(info);
}
}
//*****************************************************************************
//
// GetHostControllerPowerMap()
//
// HANDLE hHCDev
// - handle to USB Host Controller
//
// PUSBHOSTCONTROLLERINFO hcInfo
// - data structure to receive the Power Map Info
//
// return DWORD dwError
// - return ERROR_SUCCESS or last error
//
//*****************************************************************************
DWORD
GetHostControllerPowerMap(
HANDLE hHCDev,
PUSBHOSTCONTROLLERINFO hcInfo)
{
USBUSER_POWER_INFO_REQUEST UsbPowerInfoRequest;
PUSB_POWER_INFO pUPI = &UsbPowerInfoRequest.PowerInformation ;
DWORD dwError = 0;
DWORD dwBytes = 0;
BOOL bSuccess = FALSE;
int nIndex = 0;
int nPowerState = WdmUsbPowerSystemWorking;
for ( ; nPowerState <= WdmUsbPowerSystemShutdown; nIndex++, nPowerState++)
{
// zero initialize our request
memset(&UsbPowerInfoRequest, 0, sizeof(UsbPowerInfoRequest));
// set the header and request sizes
UsbPowerInfoRequest.Header.UsbUserRequest = USBUSER_GET_POWER_STATE_MAP;
UsbPowerInfoRequest.Header.RequestBufferLength = sizeof(UsbPowerInfoRequest);
UsbPowerInfoRequest.PowerInformation.SystemState = nPowerState;
//
// Now query USBHUB for the USB_POWER_INFO structure for this hub.
// For Selective Suspend support
//
bSuccess = DeviceIoControl(hHCDev,
IOCTL_USB_USER_REQUEST,
&UsbPowerInfoRequest,
sizeof(UsbPowerInfoRequest),
&UsbPowerInfoRequest,
sizeof(UsbPowerInfoRequest),
&dwBytes,
NULL);
if (!bSuccess)
{
dwError = GetLastError();
OOPS();
}
else
{
// copy the data into our USB Host Controller's info structure
memcpy( &(hcInfo->USBPowerInfo[nIndex]), pUPI, sizeof(USB_POWER_INFO));
}
}
return dwError;
}
void
EnumerateAllDevices()
{
EnumerateAllDevicesWithGuid(&gDeviceList,
(LPGUID)&GUID_DEVINTERFACE_USB_DEVICE);
EnumerateAllDevicesWithGuid(&gHubList,
(LPGUID)&GUID_DEVINTERFACE_USB_HUB);
}
//*****************************************************************************
//
// GetHostControllerInfo()
//
// HANDLE hHCDev
// - handle to USB Host Controller
//
// PUSBHOSTCONTROLLERINFO hcInfo
// - data structure to receive the Power Map Info
//
// return DWORD dwError
// - return ERROR_SUCCESS or last error
//
//*****************************************************************************
DWORD
GetHostControllerInfo(
HANDLE hHCDev,
PUSBHOSTCONTROLLERINFO hcInfo)
{
USBUSER_CONTROLLER_INFO_0 UsbControllerInfo;
DWORD dwError = 0;
DWORD dwBytes = 0;
BOOL bSuccess = FALSE;
memset(&UsbControllerInfo, 0, sizeof(UsbControllerInfo));
// set the header and request sizes
UsbControllerInfo.Header.UsbUserRequest = USBUSER_GET_CONTROLLER_INFO_0;
UsbControllerInfo.Header.RequestBufferLength = sizeof(UsbControllerInfo);
//
// Query for the USB_CONTROLLER_INFO_0 structure
//
bSuccess = DeviceIoControl(hHCDev,
IOCTL_USB_USER_REQUEST,
&UsbControllerInfo,
sizeof(UsbControllerInfo),
&UsbControllerInfo,
sizeof(UsbControllerInfo),
&dwBytes,
NULL);
if (!bSuccess)
{
dwError = GetLastError();
OOPS();
}
else
{
hcInfo->ControllerInfo = (PUSB_CONTROLLER_INFO_0) ALLOC(sizeof(USB_CONTROLLER_INFO_0));
if(NULL == hcInfo->ControllerInfo)
{
dwError = GetLastError();
OOPS();
}
else
{
// copy the data into our USB Host Controller's info structure
memcpy(hcInfo->ControllerInfo, &UsbControllerInfo.Info0, sizeof(USB_CONTROLLER_INFO_0));
}
}
return dwError;
}
_Success_(return == TRUE)
BOOL
GetDeviceProperty(
_In_ HDEVINFO DeviceInfoSet,
_In_ PSP_DEVINFO_DATA DeviceInfoData,
_In_ DWORD Property,
_Outptr_ LPTSTR *ppBuffer
)
{
BOOL bResult;
DWORD requiredLength = 0;
DWORD lastError;
if (ppBuffer == NULL)
{
return FALSE;
}
*ppBuffer = NULL;
bResult = SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet,
DeviceInfoData,
Property ,
NULL,
NULL,
0,
&requiredLength);
lastError = GetLastError();
if ((requiredLength == 0) || (bResult != FALSE && lastError != ERROR_INSUFFICIENT_BUFFER))
{
return FALSE;
}
requiredLength *= 8;
*ppBuffer = ALLOC(requiredLength);
if (*ppBuffer == NULL)
{
return FALSE;
}
bResult = SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet,
DeviceInfoData,
Property ,
NULL,
(PBYTE) *ppBuffer,
requiredLength,
&requiredLength);
if(bResult == FALSE)
{
FREE(*ppBuffer);
*ppBuffer = NULL;
return FALSE;
}
return TRUE;
}
void
EnumerateAllDevicesWithGuid(
PDEVICE_GUID_LIST DeviceList,
LPGUID Guid
)
{
if (DeviceList->DeviceInfo != INVALID_HANDLE_VALUE)
{
ClearDeviceList(DeviceList);
}
DeviceList->DeviceInfo = SetupDiGetClassDevs(Guid,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
if (DeviceList->DeviceInfo != INVALID_HANDLE_VALUE)
{
ULONG index;
DWORD error;
error = 0;
index = 0;
while (error != ERROR_NO_MORE_ITEMS)
{
BOOL success;
PDEVICE_INFO_NODE pNode;
pNode = ALLOC(sizeof(DEVICE_INFO_NODE));
if (pNode == NULL)
{
OOPS();
break;
}
pNode->DeviceInfo = DeviceList->DeviceInfo;
pNode->DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
pNode->DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
success = SetupDiEnumDeviceInfo(DeviceList->DeviceInfo,
index,
&pNode->DeviceInfoData);
index++;
if (success == FALSE)
{
error = GetLastError();
if (error != ERROR_NO_MORE_ITEMS)
{
OOPS();
}
FreeDeviceInfoNode(&pNode);
}
else
{
BOOL bResult;
ULONG requiredLength;
bResult = GetDeviceProperty(DeviceList->DeviceInfo,
&pNode->DeviceInfoData,
SPDRP_DEVICEDESC,
&pNode->DeviceDescName);
if (bResult == FALSE)
{
FreeDeviceInfoNode(&pNode);
OOPS();
break;
}
bResult = GetDeviceProperty(DeviceList->DeviceInfo,
&pNode->DeviceInfoData,
SPDRP_DRIVER,
&pNode->DeviceDriverName);
if (bResult == FALSE)
{
FreeDeviceInfoNode(&pNode);
OOPS();
break;
}
pNode->DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
success = SetupDiEnumDeviceInterfaces(DeviceList->DeviceInfo,
0,
Guid,
index-1,
&pNode->DeviceInterfaceData);
if (!success)
{
FreeDeviceInfoNode(&pNode);
OOPS();
break;
}
success = SetupDiGetDeviceInterfaceDetail(DeviceList->DeviceInfo,
&pNode->DeviceInterfaceData,
NULL,
0,
&requiredLength,
NULL);
error = GetLastError();
if (!success && error != ERROR_INSUFFICIENT_BUFFER)
{
FreeDeviceInfoNode(&pNode);
OOPS();
break;
}
pNode->DeviceDetailData = ALLOC(requiredLength);
if (pNode->DeviceDetailData == NULL)
{
FreeDeviceInfoNode(&pNode);
OOPS();
break;
}
pNode->DeviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
success = SetupDiGetDeviceInterfaceDetail(DeviceList->DeviceInfo,
&pNode->DeviceInterfaceData,
pNode->DeviceDetailData,
requiredLength,
&requiredLength,
NULL);
if (!success)
{
FreeDeviceInfoNode(&pNode);
OOPS();
break;
}
InsertTailList(&DeviceList->ListHead, &pNode->ListEntry);
}
}
}
}
DEVICE_POWER_STATE
AcquireDevicePowerState(
_Inout_ PDEVICE_INFO_NODE pNode
)
{
CM_POWER_DATA cmPowerData = {0};
BOOL bResult;
bResult = SetupDiGetDeviceRegistryProperty(pNode->DeviceInfo,
&pNode->DeviceInfoData,
SPDRP_DEVICE_POWER_DATA,
NULL,
(PBYTE)&cmPowerData,
sizeof(cmPowerData),
NULL);
pNode->LatestDevicePowerState = bResult ? cmPowerData.PD_MostRecentPowerState : PowerDeviceUnspecified;
return pNode->LatestDevicePowerState;
}
void
ClearDeviceList(
PDEVICE_GUID_LIST DeviceList
)
{
if (DeviceList->DeviceInfo != INVALID_HANDLE_VALUE)
{
SetupDiDestroyDeviceInfoList(DeviceList->DeviceInfo);
DeviceList->DeviceInfo = INVALID_HANDLE_VALUE;
}
while (!IsListEmpty(&DeviceList->ListHead))
{
PDEVICE_INFO_NODE pNode = NULL;
PLIST_ENTRY pEntry;
pEntry = RemoveHeadList(&DeviceList->ListHead);
pNode = CONTAINING_RECORD(pEntry,
DEVICE_INFO_NODE,
ListEntry);
FreeDeviceInfoNode(&pNode);
}
}
VOID
FreeDeviceInfoNode(
_In_ PDEVICE_INFO_NODE *ppNode
)
{
if (ppNode == NULL)
{
return;
}
if (*ppNode == NULL)
{
return;
}
if ((*ppNode)->DeviceDetailData != NULL)
{
FREE((*ppNode)->DeviceDetailData);
}
if ((*ppNode)->DeviceDescName != NULL)
{
FREE((*ppNode)->DeviceDescName);
}
if ((*ppNode)->DeviceDriverName != NULL)
{
FREE((*ppNode)->DeviceDriverName);
}
FREE(*ppNode);
*ppNode = NULL;
}
PDEVICE_INFO_NODE
FindMatchingDeviceNodeForDriverName(
_In_ PSTR DriverKeyName,
_In_ BOOLEAN IsHub
)
{
PDEVICE_INFO_NODE pNode = NULL;
PDEVICE_GUID_LIST pList = NULL;
PLIST_ENTRY pEntry = NULL;
pList = IsHub ? &gHubList : &gDeviceList;
pEntry = pList->ListHead.Flink;
while (pEntry && pEntry != &pList->ListHead)
{
pNode = CONTAINING_RECORD(pEntry,
DEVICE_INFO_NODE,
ListEntry);
if (_stricmp(DriverKeyName, pNode->DeviceDriverName) == 0)
{
return pNode;
}
pEntry = pEntry->Flink;
}
return NULL;
}
#define CUSTOM_USBVIEW
#ifdef CUSTOM_USBVIEW
PUSBDEVICEINFO
enumerate_hub_port(HANDLE hHubDevice, ULONG port_index)
{
ULONG index = port_index;
BOOL success = 0;
HRESULT hr = S_OK;
PCHAR driverKeyName = NULL;
PUSB_DEVICE_PNP_STRINGS DevProps = NULL;
DWORD dwSizeOfLeafName = 0;
CHAR leafName[512] = { 0 };
int icon = 0;
PUSBDEVICEINFO info = NULL;
PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfoEx = NULL;
PUSB_PORT_CONNECTOR_PROPERTIES pPortConnectorProps = NULL;
USB_PORT_CONNECTOR_PROPERTIES portConnectorProps = { 0 };
PUSB_DESCRIPTOR_REQUEST configDesc = NULL;
PUSB_DESCRIPTOR_REQUEST bosDesc = NULL;
PSTRING_DESCRIPTOR_NODE stringDescs = NULL;
PUSB_NODE_CONNECTION_INFORMATION_EX_V2 connectionInfoExV2 = NULL;
PDEVICE_INFO_NODE pNode = NULL;
// Loop over all ports of the hub.
//
// Port indices are 1 based, not 0 based.
//
//for (index = 1; index <= NumPorts; index++)
{
ULONG usb_pipes = 30;
ULONG nBytesEx = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) + (sizeof(USB_PIPE_INFO) * usb_pipes);
ULONG nBytes = 0;
//
// Allocate space to hold the connection info for this port.
// For now, allocate it big enough to hold info for 30 pipes.
//
// Endpoint numbers are 0-15. Endpoint number 0 is the standard
// control endpoint which is not explicitly listed in the Configuration
// Descriptor. There can be an IN endpoint and an OUT endpoint at
// endpoint numbers 1-15 so there can be a maximum of 30 endpoints
// per device configuration.
//
// Should probably size this dynamically at some point.
//
connectionInfoEx = (PUSB_NODE_CONNECTION_INFORMATION_EX)ALLOC(nBytesEx);
if (connectionInfoEx == NULL)
{
OOPS();
return NULL;
}
connectionInfoExV2 = (PUSB_NODE_CONNECTION_INFORMATION_EX_V2)ALLOC(sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2));
if (connectionInfoExV2 == NULL)
{
OOPS();
FREE(connectionInfoEx);
return NULL;
}
//
// Now query USBHUB for the structures
// for this port. This will tell us if a device is attached to this
// port, among other things.
// The fault tolerate code is executed first.
//
portConnectorProps.ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES,
&portConnectorProps,
sizeof(USB_PORT_CONNECTOR_PROPERTIES),
&portConnectorProps,
sizeof(USB_PORT_CONNECTOR_PROPERTIES),
&nBytes,
NULL);
if (success && nBytes == sizeof(USB_PORT_CONNECTOR_PROPERTIES))
{
pPortConnectorProps = (PUSB_PORT_CONNECTOR_PROPERTIES)ALLOC(portConnectorProps.ActualLength);
if (pPortConnectorProps != NULL)
{
pPortConnectorProps->ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES,
pPortConnectorProps,
portConnectorProps.ActualLength,
pPortConnectorProps,
portConnectorProps.ActualLength,
&nBytes,
NULL);
if (!success || nBytes < portConnectorProps.ActualLength)
{
FREE(pPortConnectorProps);
pPortConnectorProps = NULL;
}
}
}
connectionInfoExV2->ConnectionIndex = index;
connectionInfoExV2->Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2);
connectionInfoExV2->SupportedUsbProtocols.Usb300 = 1;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
connectionInfoExV2,
sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2),
connectionInfoExV2,
sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2),
&nBytes,
NULL);
if (!success || nBytes < sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2))
{
FREE(connectionInfoExV2);
connectionInfoExV2 = NULL;
}
connectionInfoEx->ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
connectionInfoEx,
nBytesEx,
connectionInfoEx,
nBytesEx,
&nBytesEx,
NULL);
if (success)
{
//
// Since the USB_NODE_CONNECTION_INFORMATION_EX is used to display
// the device speed, but the hub driver doesn't support indication
// of superspeed, we overwrite the value if the super speed
// data structures are available and indicate the device is operating
// at SuperSpeed.
//
if (connectionInfoEx->Speed == UsbHighSpeed
&& connectionInfoExV2 != NULL
&& (connectionInfoExV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher ||
connectionInfoExV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher))
{
connectionInfoEx->Speed = UsbSuperSpeed;
}
}
else
{
PUSB_NODE_CONNECTION_INFORMATION connectionInfo = NULL;
// Try using IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
// instead of IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX
//
nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) + sizeof(USB_PIPE_INFO) * usb_pipes;
connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)ALLOC(nBytes);
if (connectionInfo == NULL)
{
OOPS();
FREE(connectionInfoEx);
if (pPortConnectorProps != NULL)
{
FREE(pPortConnectorProps);
}
if (connectionInfoExV2 != NULL)
{
FREE(connectionInfoExV2);
}
return NULL;
}
connectionInfo->ConnectionIndex = index;
success = DeviceIoControl(hHubDevice,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
connectionInfo,
nBytes,
connectionInfo,
nBytes,
&nBytes,
NULL);
if (!success)
{
OOPS();
FREE(connectionInfo);
FREE(connectionInfoEx);
if (pPortConnectorProps != NULL)
{
FREE(pPortConnectorProps);
}
if (connectionInfoExV2 != NULL)
{
FREE(connectionInfoExV2);
}
return NULL;
}
// Copy IOCTL_USB_GET_NODE_CONNECTION_INFORMATION into
// IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX structure.
//
connectionInfoEx->ConnectionIndex = connectionInfo->ConnectionIndex;
connectionInfoEx->DeviceDescriptor = connectionInfo->DeviceDescriptor;
connectionInfoEx->CurrentConfigurationValue = connectionInfo->CurrentConfigurationValue;
connectionInfoEx->Speed = connectionInfo->LowSpeed ? UsbLowSpeed : UsbFullSpeed;
connectionInfoEx->DeviceIsHub = connectionInfo->DeviceIsHub;
connectionInfoEx->DeviceAddress = connectionInfo->DeviceAddress;
connectionInfoEx->NumberOfOpenPipes = connectionInfo->NumberOfOpenPipes;
connectionInfoEx->ConnectionStatus = connectionInfo->ConnectionStatus;
memcpy(&connectionInfoEx->PipeList[0], &connectionInfo->PipeList[0], sizeof(USB_PIPE_INFO) * usb_pipes);
FREE(connectionInfo);
}
// If there is a device connected, get the Device Description
//
if (connectionInfoEx->ConnectionStatus != NoDeviceConnected)
{
driverKeyName = GetDriverKeyName(hHubDevice, index);
if (driverKeyName)
{
size_t cbDriverName = 0;
hr = StringCbLength(driverKeyName, MAX_DRIVER_KEY_NAME, &cbDriverName);
if (SUCCEEDED(hr))
{
DevProps = DriverNameToDeviceProperties(driverKeyName, cbDriverName);
pNode = FindMatchingDeviceNodeForDriverName(driverKeyName, connectionInfoEx->DeviceIsHub);
}
FREE(driverKeyName);
}
}
// If there is a device connected to the port, try to retrieve the
// Configuration Descriptor from the device.
//
if (/*gDoConfigDesc &&*/
connectionInfoEx->ConnectionStatus == DeviceConnected)
{
configDesc = GetConfigDescriptor(hHubDevice,
index,
0);
}
else
{
configDesc = NULL;
}
if (configDesc != NULL &&
connectionInfoEx->DeviceDescriptor.bcdUSB > 0x0200)
{
bosDesc = GetBOSDescriptor(hHubDevice,
index);
}
else
{
bosDesc = NULL;
}
if (configDesc != NULL &&
AreThereStringDescriptors(&connectionInfoEx->DeviceDescriptor,
(PUSB_CONFIGURATION_DESCRIPTOR)(configDesc + 1)))
{
stringDescs = GetAllStringDescriptors(
hHubDevice,
index,
&connectionInfoEx->DeviceDescriptor,
(PUSB_CONFIGURATION_DESCRIPTOR)(configDesc + 1));
}
else
{
stringDescs = NULL;
}
// If the device connected to the port is an external hub, get the
// name of the external hub and recursively enumerate it.
//
if (connectionInfoEx->DeviceIsHub)
{
OOPS();
if (configDesc != NULL)
{
FREE(configDesc);
}
if (bosDesc != NULL)
{
FREE(bosDesc);
}
FREE(connectionInfoEx);
if (pPortConnectorProps != NULL)
{
FREE(pPortConnectorProps);
}
if (connectionInfoExV2 != NULL)
{
FREE(connectionInfoExV2);
}
return NULL;
}
else
{
// Allocate some space for a USBDEVICEINFO structure to hold the
// hub info, hub name, and connection info pointers. GPTR zero
// initializes the structure for us.
//
info = (PUSBDEVICEINFO)ALLOC(sizeof(USBDEVICEINFO));
if (info == NULL)
{
OOPS();
if (configDesc != NULL)
{
FREE(configDesc);
}
if (bosDesc != NULL)
{
FREE(bosDesc);
}
FREE(connectionInfoEx);
if (pPortConnectorProps != NULL)
{
FREE(pPortConnectorProps);
}
if (connectionInfoExV2 != NULL)
{
FREE(connectionInfoExV2);
}
return NULL;
}
info->DeviceInfoType = DeviceInfo;
info->ConnectionInfo = connectionInfoEx;
info->PortConnectorProps = pPortConnectorProps;
info->ConfigDesc = configDesc;
info->StringDescs = stringDescs;
info->BosDesc = bosDesc;
info->ConnectionInfoV2 = connectionInfoExV2;
info->UsbDeviceProperties = DevProps;
info->DeviceInfoNode = pNode;
StringCchPrintf(leafName, sizeof(leafName), "[Port%d] ", index);
// Add error description if ConnectionStatus is other than NoDeviceConnected / DeviceConnected
StringCchCat(leafName,
sizeof(leafName),
ConnectionStatuses[connectionInfoEx->ConnectionStatus]);
if (DevProps)
{
size_t cchDeviceDesc = 0;
hr = StringCbLength(DevProps->DeviceDesc, MAX_DEVICE_PROP, &cchDeviceDesc);
if (FAILED(hr))
{
OOPS();
}
dwSizeOfLeafName = sizeof(leafName);
StringCchCatN(leafName,
dwSizeOfLeafName - 1,
" : ",
sizeof(" : "));
StringCchCatN(leafName,
dwSizeOfLeafName - 1,
DevProps->DeviceDesc,
cchDeviceDesc);
}
if (connectionInfoEx->ConnectionStatus == NoDeviceConnected)
{
if (connectionInfoExV2 != NULL &&
connectionInfoExV2->SupportedUsbProtocols.Usb300 == 1)
{
icon = NoSsDeviceIcon;
}
else
{
icon = NoDeviceIcon;
}
}
else if (connectionInfoEx->CurrentConfigurationValue)
{
if (connectionInfoEx->Speed == UsbSuperSpeed)
{
icon = GoodSsDeviceIcon;
}
else
{
icon = GoodDeviceIcon;
}
}
else
{
icon = BadDeviceIcon;
}
}
} // for
return info;
}
PUSBDEVICEINFO get_usb_device_info(const char* device_name)
{
PUSBDEVICEINFO info = NULL;
HANDLE hub = NULL;
ULONG port = -1;
DWORD bytes = 0;
BOOL ret = FALSE;
HDEVINFO dev = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_USB_HUB, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (dev)
{
SetupDiDestroyDeviceInfoList(dev);
}
if (hub)
{
info = enumerate_hub_port(hub, port);
CloseHandle(hub);
}
return info;
}
void free_usb_device_info(PUSBDEVICEINFO pudi)
{
if (pudi)
{
if (pudi->ConnectionInfo)
FREE(pudi->ConnectionInfo);
if (pudi->PortConnectorProps)
FREE(pudi->PortConnectorProps);
if (pudi->ConfigDesc)
FREE(pudi->ConfigDesc);
if (pudi->StringDescs)
{
PSTRING_DESCRIPTOR_NODE next = pudi->StringDescs->Next;
FREE(pudi->StringDescs);
while (next)
{
pudi->StringDescs = next;
next = pudi->StringDescs->Next;
FREE(pudi->StringDescs);
}
}
if (pudi->BosDesc)
FREE(pudi->BosDesc);
if (pudi->ConnectionInfoV2)
FREE(pudi->ConnectionInfoV2);
if (pudi->UsbDeviceProperties)
FreeDeviceProperties(&pudi->UsbDeviceProperties);
//if (pudi->DeviceInfoNode)
// FREE(pudi->DeviceInfoNode);
FREE(pudi);
}
}
#endif