Reputation: 6638
I was wondering if it is possible to get the USB device descriptor with the SetupAPI functions (like SetupDiGetDeviceRegistryProperty
)?
Thank you!
EDIT
So far I am only able to receive the windows friendly name:
SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC,
&dwPropertyRegDataType, (BYTE*)szDesc, sizeof(szDesc), &dwSize)
Upvotes: 1
Views: 4195
Reputation: 33706
we need have/got string representing Device Instance ID of a device. with this we first obtains a device instance handle to the device node via CM_Locate_DevNode
and then call CM_Get_DevNode_Property
with DEVPKEY_NAME
:
The retrieved property value is the same as the value of the DEVPKEY_Device_FriendlyName device property, if DEVPKEY_Device_FriendlyName is set. Otherwise, the value of DEVPKEY_NAME is same as the value of the DEVPKEY_Device_DeviceDesc device property.
static volatile UCHAR guz;
CONFIGRET PrintFriendlyNameByDeviceID(PWSTR DeviceID)
{
DEVINST dnDevInst;
CONFIGRET status = CM_Locate_DevNodeW(&dnDevInst, DeviceID, CM_LOCATE_DEVNODE_NORMAL);
if (status == CR_SUCCESS)
{
ULONG cb = 0, rcb = 16;
PVOID stack = alloca(guz);
DEVPROPTYPE PropertyType;
union {
PVOID pv;
PWSTR sz;
PBYTE pb;
};
do
{
if (cb < rcb)
{
rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
}
status = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_NAME, &PropertyType, pb, &rcb, 0);
if (status == CR_SUCCESS)
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("NAME = %S\n", sz);
}
else
{
status = CR_WRONG_TYPE;
}
}
} while (status == CR_BUFFER_SMALL);
}
return status;
}
if we have the string that identifies the device interface instance - we can obtaining the device instance identifier from it via call CM_Get_Device_Interface_Property
with DEVPKEY_Device_InstanceId
key and then call PrintFriendlyNameByDeviceID
CONFIGRET PrintFriendlyNameByInterface(PCWSTR pszDeviceInterface)
{
ULONG cb = 0, rcb = 64;
PVOID stack = alloca(guz);
DEVPROPTYPE PropertyType;
CONFIGRET status;
union {
PVOID pv;
PWSTR DeviceID;
PBYTE pb;
};
do
{
if (cb < rcb)
{
rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
}
status = CM_Get_Device_Interface_PropertyW(pszDeviceInterface, &DEVPKEY_Device_InstanceId, &PropertyType, pb, &rcb, 0);
if (status == CR_SUCCESS)
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("DeviceID = %S\n", DeviceID);
status = PrintFriendlyNameByDeviceID(DeviceID);
}
else
{
status = CR_WRONG_TYPE;
}
break;
}
} while (status == CR_BUFFER_SMALL);
return status;
}
and at begin we have 2 choice: of just retrieves a list of device instance IDs via call CM_Get_Device_ID_List
with CM_GETIDLIST_FILTER_CLASS|CM_GETIDLIST_FILTER_PRESENT
and use "{36fc9e60-c465-11cf-8056-444553540000}"
as filter - this is string representation of well known GUID_DEVCLASS_USB
defined in devguid.h
:
void PrintFriendlyNames(PCWSTR pszFilter)
{
CONFIGRET status;
ULONG len = 0, cb = 0, rcb;
PVOID stack = alloca(guz);
PWSTR buf = 0;
do
{
if (status = CM_Get_Device_ID_List_SizeW(&len, pszFilter, CM_GETIDLIST_FILTER_CLASS|CM_GETIDLIST_FILTER_PRESENT))
{
break;
}
if (cb < (rcb = len * sizeof(WCHAR)))
{
len = (cb = RtlPointerToOffset(buf = (PWSTR)alloca(rcb - cb), stack)) / sizeof(WCHAR);
}
status = CM_Get_Device_ID_ListW(pszFilter, buf, len, CM_GETIDLIST_FILTER_CLASS|CM_GETIDLIST_FILTER_PRESENT);
if (status == CR_SUCCESS)
{
while (*buf)
{
DbgPrint("DeviceID = %S\n", buf);
PrintFriendlyNameByDeviceID(buf);
buf += 1 + wcslen(buf);
}
}
} while (status == CR_BUFFER_SMALL);
}
PrintFriendlyNames(L"{36fc9e60-c465-11cf-8056-444553540000}");
or enumerate device interfaces via CM_Get_Device_Interface_List and call PrintFriendlyNameByInterface
for every device interface.
void PrintFriendlyNames(PGUID InterfaceClassGuid)
{
CONFIGRET status;
ULONG len = 0, cb = 0, rcb;
PVOID stack = alloca(guz);
PWSTR buf = 0;
do
{
if (status = CM_Get_Device_Interface_List_SizeW(&len, InterfaceClassGuid, 0, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
{
break;
}
if (cb < (rcb = len * sizeof(WCHAR)))
{
len = (cb = RtlPointerToOffset(buf = (PWSTR)alloca(rcb - cb), stack)) / sizeof(WCHAR);
}
status = CM_Get_Device_Interface_ListW(InterfaceClassGuid, 0, buf, len, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (status == CR_SUCCESS)
{
while (*buf)
{
DbgPrint("Interface = %S\n", buf);
PrintFriendlyNameByInterface(buf);
buf += 1 + wcslen(buf);
}
}
} while (status == CR_BUFFER_SMALL);
}
you can use say GUID_DEVINTERFACE_USB_DEVICE
PrintFriendlyNames(const_cast<PGUID>(&GUID_DEVINTERFACE_USB_DEVICE));
the result of methods (which devices /interfaces) will be listed can be different. say om my comp when enum by GUID_DEVINTERFACE_USB_DEVICE
:
Interface = \\?\USB#VID_046D&PID_C52E#5&18d671f8&0&4#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
DeviceID = USB\VID_046D&PID_C52E\5&18d671f8&0&4
NAME = USB Composite Device
Interface = \\?\USB#VID_051D&PID_0002#5B1120T12418__#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
DeviceID = USB\VID_051D&PID_0002\5B1120T12418__
NAME = American Power Conversion USB UPS
Interface = \\?\USB#VID_045E&PID_077B#5&18d671f8&0&3#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
DeviceID = USB\VID_045E&PID_077B\5&18d671f8&0&3
NAME = USB Input Device
and when enum by GUID_DEVCLASS_USB
string filter:
DeviceID = USB\VID_1F75&PID_0916\120709860570000024
NAME = USB Mass Storage Device
DeviceID = USB\ROOT_HUB30\4&33ed72c&0&0
NAME = USB Root Hub (xHCI)
DeviceID = USB\VID_0951&PID_168F\001A92053B6A0CA101340008
NAME = USB Mass Storage Device
DeviceID = PCI\VEN_8086&DEV_A2AF&SUBSYS_7A741462&REV_00\3&11583659&0&A0
NAME = Intel(R) USB 3.0 eXtensible Host Controller - 1.0 (Microsoft)
DeviceID = USB\VID_046D&PID_C52E\5&18d671f8&0&4
NAME = USB Composite Device
Upvotes: 6