1. 程式人生 > >Windows下USB磁碟開發系列三:列舉系統中U盤、並獲取其裝置資訊

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,執行結果如下: