Windows下USB磁盘开发系列三:枚举系统中U盘、并获取其设备信息
前面我们介绍了枚举系统中的U盘盘符(见《Windows下USB磁盘开发系列一:枚举系统中U盘的盘符》)、以及获取USB设备的信息(见《Windows下USB磁盘开发系列二:枚举系统中所有USB设备》)。有个时候我们不仅仅需要获取U盘盘符(路径),而且需要获取该U盘的硬件信息,比如厂商、friendly name、描述等等。那么我们可以通过前面两个方法,把U盘盘符和设备信息匹配起来吗?答案是肯定的,下面介绍具体的实现方法。
具体方法如下:
1,获取U盘盘符(路径);
2,对U盘路径调用CreateFile()获取U盘句柄;
3,对U盘句柄调用DeviceIoControl()获取其Device Number;
4,调用SetupDiGetClassDevs()/SetupDiEnumDeviceInfo()枚举系统中所有U盘设备;
5,调用SetupDiEnumDeviceInterfaces()/SetupDiGetDeviceInterfaceDetail()获取设备路径;
6,对U盘设备路径调用CreateFile()获取U盘设备句柄;
7,对U盘设备句柄调用DeviceIoControl()获取其Device Number;
8,判断3和7获得的Device Number,两者一致则表示该U盘盘符和设备为同一设备。
具体实现代码如下:
1,获取U盘设备列表
int get_usb_device_list(usb_device_info *usb_list, int list_size) { int usb_device_cnt = 0; char disk_path[5] = {0}; char device_path[10] = {0}; DWORD all_disk = GetLogicalDrives(); int i = 0; DWORD bytes_returned = 0; STORAGE_DEVICE_NUMBER device_num; while (all_disk && usb_device_cnt < list_size) { if ((all_disk & 0x1) == 1) { sprintf_s(disk_path, "%c:", 'A'+i); sprintf_s(device_path, "\\\\.\\%s", disk_path); if (GetDriveTypeA(disk_path) == DRIVE_REMOVABLE) { // get this usb device id HANDLE hDevice = CreateFileA(device_path, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &device_num, sizeof(device_num), &bytes_returned, (LPOVERLAPPED) NULL)) { usb_list[usb_device_cnt].volume = 'A' + i; usb_list[usb_device_cnt].device_num = device_num.DeviceNumber; usb_device_cnt++; } CloseHandle(hDevice); hDevice = 0; } } all_disk = all_disk >> 1; i++; } return usb_device_cnt; }
2,匹配U盘设备信息
int get_usb_device_friendname(usb_device_info *usb_list, int list_size) { int i = 0; int res = 0; HDEVINFO hDevInfo; SP_DEVINFO_DATA DeviceInfoData = {sizeof(DeviceInfoData)}; // get device class information handle hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK,0, 0, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); if (hDevInfo == INVALID_HANDLE_VALUE) { res = GetLastError(); return res; } // enumerute device information DWORD required_size = 0; for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); i++) { DWORD DataT; char friendly_name[2046] = {0}; DWORD buffersize = 2046; DWORD req_bufsize = 2046; // get device friendly name if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &DeviceInfoData, SPDRP_FRIENDLYNAME, &DataT, (LPBYTE)friendly_name, buffersize, &req_bufsize)) { continue; } if (strstr(friendly_name, "USB") == 0) { continue; } int index = 0; SP_DEVICE_INTERFACE_DATA did = {sizeof(did)}; PSP_DEVICE_INTERFACE_DETAIL_DATA pdd = NULL; while(1) { // get device interface data if (!SetupDiEnumDeviceInterfaces(hDevInfo, &DeviceInfoData, &GUID_DEVINTERFACE_DISK, index++, &did)) { res = GetLastError(); if( ERROR_NO_MORE_DEVICES == res || ERROR_NO_MORE_ITEMS == res) break; } // get device interface detail size if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &did, NULL, 0, &required_size, NULL)) { res = GetLastError(); if(ERROR_INSUFFICIENT_BUFFER == res) { pdd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, required_size); pdd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); } else break; } // get device interface detail if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &did, pdd, required_size, NULL, NULL)) { res = GetLastError(); LocalFree(pdd); pdd = NULL; break; } // get device number DWORD bytes_returned = 0; STORAGE_DEVICE_NUMBER device_num; HANDLE hDevice = CreateFile(pdd->DevicePath, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &device_num, sizeof(device_num), &bytes_returned, (LPOVERLAPPED) NULL)) { for (int usb_index = 0; usb_index < list_size; usb_index++) { if (device_num.DeviceNumber == usb_list[usb_index].device_num) { strcpy_s(usb_list[usb_index].friendname, friendly_name); break; } } } CloseHandle(hDevice); LocalFree(pdd); pdd = NULL; } } SetupDiDestroyDeviceInfoList(hDevInfo); return res; }
3,调用代码:
typedef struct usb_device_info_t { char volume; char friendname[256]; int device_num; }usb_device_info;
int _tmain(int argc, _TCHAR* argv[]) { bool bRes = false; usb_device_info usb_list[8]; memset(usb_list, 0, 8*sizeof(usb_device_info)); int usb_cnt = get_usb_device_list(usb_list, 8); printf("System has %d USB disk.\n", usb_cnt); if (usb_cnt > 0) { get_usb_device_friendname(usb_list, usb_cnt); { for (int i = 0; i < usb_cnt; i++) { printf("%c: %s\n", usb_list[i].volume, usb_list[i].friendname); } } } getchar(); return 1; }
4,运行结果如下: