作者微信:15013593099 欢迎交流
ADBAPIHANDLE __cdecl AdbEnumInterfaces(GUID class_id,
bool exclude_not_present,bool exclude_removed,
bool active_only)
bool AdbInterfaceEnumObject::InitializeEnum(GUID class_id,
bool exclude_not_present,
bool exclude_removed,
bool active_only)
bool EnumerateDeviceInterfaces(GUID class_id,
ULONG flags,
bool exclude_removed,
bool active_only,
AdbEnumInterfaceArray* interfaces) {
// Open a handle to the plug and play dev node.
// SetupDiGetClassDevs() returns a device information set that
// contains info on all installed devices of a specified class.
HDEVINFO hardware_dev_info =
SetupDiGetClassDevs(&class_id, NULL, NULL, flags);
bool ret = false;
if (INVALID_HANDLE_VALUE != hardware_dev_info) {
// Do the enum
ret = EnumerateDeviceInterfaces(hardware_dev_info,
class_id,
exclude_removed,
active_only,
interfaces);
// Preserve last error accross hardware_dev_info destruction
ULONG error_to_report = ret ? NO_ERROR : GetLastError();
SetupDiDestroyDeviceInfoList(hardware_dev_info);
if (NO_ERROR != error_to_report)
SetLastError(error_to_report);
}
return ret;
}
bool EnumerateDeviceInterfaces(GUID class_id,
ULONG flags,
bool exclude_removed,
bool active_only,
AdbEnumInterfaceArray* interfaces)
HDEVINFO hardware_dev_info =
SetupDiGetClassDevs(&class_id, NULL, NULL, flags);
bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,
GUID class_id,
bool exclude_removed,
bool active_only,
AdbEnumInterfaceArray* interfaces)
bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,
GUID class_id,
bool exclude_removed,
bool active_only,
AdbEnumInterfaceArray* interfaces) {
AdbEnumInterfaceArray tmp;
bool ret = false;
OutputDebugStringA("EnumerateDeviceInterfaces");
// Enumerate interfaces on this device
for (ULONG index = 0; ; index++) {
SP_DEVICE_INTERFACE_DATA interface_data;
interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
// SetupDiEnumDeviceInterfaces() returns information about device
// interfaces exposed by one or more devices defined by our interface
// class. Each call returns information about one interface. The routine
// can be called repeatedly to get information about several interfaces
// exposed by one or more devices.
if (SetupDiEnumDeviceInterfaces(hardware_dev_info,
0,
&class_id,
index,
&interface_data)) {
// Satisfy "exclude removed" and "active only" filters.
if ((!exclude_removed || (0 == (interface_data.Flags & SPINT_REMOVED))) &&
(!active_only || (interface_data.Flags & SPINT_ACTIVE))) {
std::wstring dev_name;
if (GetUsbDeviceName(hardware_dev_info, &interface_data, &dev_name)) {
char locinfo[200]={"helloerror"};
char locinfow[200];
SP_DEVINFO_DATA spDevInfoData = {0};
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo(hardware_dev_info,
index,
&spDevInfoData))
{
GetOtherDeviceRegistryProperty( hardware_dev_info, &spDevInfoData ,locinfow);
char* ptrmalloc= unicode_ascii((LPCWSTR)locinfow);
strcpy(locinfo,ptrmalloc);
free(ptrmalloc);
OutputDebugStringA("GetOtherDeviceRegistryProperty");
OutputDebugStringA(locinfo);
}else{
//OutputDebugStringA("GetOtherDeviceRegistryProperty ERROR");
}
try {
// Add new entry to the array
tmp.push_back(AdbInstanceEnumEntry(dev_name.c_str(),
interface_data.InterfaceClassGuid,
interface_data.Flags,
locinfo));
} catch (... ) {
SetLastError(ERROR_OUTOFMEMORY);
break;
}
} else {
// Something went wrong in getting device name
break;
}
}
} else {
if (ERROR_NO_MORE_ITEMS == GetLastError()) {
// There are no more items in the list. Enum is completed.
ret = true;
break;
} else {
// Something went wrong in SDK enum
break;
}
}
}
// On success, swap temp array with the returning one
if (ret)
interfaces->swap(tmp);
return ret;
}
bool GetUsbDeviceDetails(
HDEVINFO hardware_dev_info,
PSP_DEVICE_INTERFACE_DATA dev_info_data,
PSP_DEVICE_INTERFACE_DETAIL_DATA* dev_info_detail_data) {
ULONG required_len = 0;
// First query for the structure size. At this point we expect this call
// to fail with ERROR_INSUFFICIENT_BUFFER error code.
if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
dev_info_data,
NULL,
0,
&required_len,
NULL)) {
return false;
}
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
return false;
// Allocate buffer for the structure
PSP_DEVICE_INTERFACE_DETAIL_DATA buffer =
reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(required_len));
if (NULL == buffer) {
SetLastError(ERROR_OUTOFMEMORY);
return false;
}
buffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// Retrieve the information from Plug and Play.
if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
dev_info_data,
buffer,
required_len,
&required_len,
NULL)) {
*dev_info_detail_data = buffer;
return true;
} else {
// Free the buffer if this call failed
free(buffer);
return false;
}
}
SetupDiEnumDeviceInterfaces(hardware_dev_info,
0,
&class_id,
index,
&interface_data)
BOOL WINAPI SetupDiEnumDeviceInterfaces(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
CONST GUID * InterfaceClassGuid,
DWORD MemberIndex,
PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
{
struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
struct DeviceInfoSet /* HDEVINFO */
{
DWORD magic; /* SETUP_DEVICE_INFO_SET_MAGIC */
/* If != GUID_NULL, only devices of this class can be in the device info set */
GUID ClassGuid;
/* Local or distant HKEY_LOCAL_MACHINE registry key */
HKEY HKLM;
/* Used when dealing with CM_* functions */
HMACHINE hMachine;
/* Reserved Field points to a struct DriverInfoElement */
SP_DEVINSTALL_PARAMS_W InstallParams;
/* List of struct DriverInfoElement (if no driver has been
* searched/detected, this list is empty) */
LIST_ENTRY DriverListHead;
/* List of struct DeviceInfo */
LIST_ENTRY ListHead;
struct DeviceInfo *SelectedDevice;
/* Used by SetupDiGetClassInstallParamsW/SetupDiSetClassInstallParamsW */
struct ClassInstallParams ClassInstallParams;
/* Contains the name of the remote computer ('\\COMPUTERNAME' for example),
* or NULL if related to local machine. Points into szData field at the
* end of the structure */
PCWSTR MachineName;
/* Variable size array (contains data for MachineName) */
WCHAR szData[ANYSIZE_ARRAY];
};
typedef struct _SP_DEVICE_INTERFACE_DATA { DWORDcbSize; GUID InterfaceClassGuid; DWORD Flags; ULONG_PTR Reserved; } SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA;
typedef struct _SP_DEVINFO_DATA { DWORD cbSize; GUID ClassGuid; DWORD DevInst; ULONG_PTR Reserved; } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;
typedef struct _USB_DEVICE_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; USHORT bcdUSB; UCHAR bDeviceClass; UCHAR bDeviceSubClass; UCHAR bDeviceProtocol; UCHAR bMaxPacketSize0; USHORT idVendor; USHORT idProduct; USHORT bcdDevice; UCHAR iManufacturer; UCHAR iProduct; UCHAR iSerialNumber; UCHAR bNumConfigurations; } USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
typedef struct _USB_INTERFACE_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; UCHAR bInterfaceNumber; UCHAR bAlternateSetting; UCHAR bNumEndpoints; UCHAR bInterfaceClass; UCHAR bInterfaceSubClass; UCHAR bInterfaceProtocol; UCHAR iInterface; } USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;success = DeviceIoControl(hHubDevice,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
stringDescReq,nBytes,
stringDescReq,nBytes,
&nBytesReturned,NULL);
USB设备唯一标识可以使用PID,VID,与序列号相组合来达到唯一标识的目的。[喝小酒的网摘]http://blog.const.net.cn/a/15690.htm
要得到pid,vid,则直接从USB_DEVICE_DESCRIPTOR结构中取出idVendor,idProduct这两项的值就行了。如果要得到序列号,则不是取出 iSerialNumber就可以的。这里的 iSerialNumber仅仅是一个索引值。如果想得到序列号,就需要定义一个结构,然后给设备发送个请求。
代码参照GetStringDescriptor函数。可以根据iSerialNumber偏移,取出其对应的字符串,存放在上图USB_STRING_DESCRIPTOR结构中。