Ring 3下的方法:
童鞋们应该已经发现了,GetDriveType函数只能识别出U盘,无法识别移动硬盘。移动硬盘和本地硬盘将返回相同的类型DRIVE_FIXED。MSDN上的建议是用一个蛋疼无比的函数SetupDiGetDeviceRegistryProperty来识别USB设备。
其实有个更方便的方法,可以通过DeviceIoControl函数查询总线类型来识别USB设备。贴代码:
BOOL IsUsbDriver(TCHAR tchDrvName) /*++ Routine Description: 判断某分区是否是USB设备。 Arguments: tchDrvName - 输入参数,驱动器号。 Return Value: 是USB设备则返回TRUE,否则返回FALSE, 查询失败也返回FALSE。 Author: Fypher http://hi.baidu.com/nmn714 2011/5/1 --*/ { TCHAR tcsDrvName[8] = TEXT("////.//X:"); tcsDrvName[4] = tchDrvName; HANDLE hDevice = CreateFile( tcsDrvName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hDevice == INVALID_HANDLE_VALUE ) { return FALSE; } STORAGE_PROPERTY_QUERY StoragePropertyQuery; StoragePropertyQuery.PropertyId = StorageDeviceProperty; StoragePropertyQuery.QueryType = PropertyStandardQuery; BYTE buff[1024] = {0}; PSTORAGE_DEVICE_DESCRIPTOR pDevDesc = (PSTORAGE_DEVICE_DESCRIPTOR)buff; pDevDesc->Size = sizeof(buff); DWORD dwOutLen; BOOL res = DeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &StoragePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), pDevDesc, pDevDesc->Size, &dwOutLen, NULL ); CloseHandle(hDevice); if (res) { // 返回结果 return pDevDesc->BusType == BusTypeUsb; } else { // 查询失败 return FALSE; } }
Ring 0下的方法:
在Ring 0下,通过DiskDeviceObject的名字在一定概率上能判断该DiskDeviceObject对应的卷设备是否是USB设备。即名称为HardDiskVolumeXXX的DiskDeviceObject通常是本地硬盘。不过这个方法其实也很不靠谱,尤其是Win7下,插个U盘都是HardDiskVolumeXXX。
其实最好的方法同样是查询总线类型。贴代码:
BOOLEAN IsUsbDriver(IN PDEVICE_OBJECT pDeviceObject) /*++ Routine Description: 判断某磁盘设备是否是USB设备。 Arguments: pDeviceObject - 输入参数,卷设备对应的 DiskDeviceObject。 卷设备与 DiskDeviceObject 之间的关系可以参考: http://hi.baidu.com/nmn714/blog/item/3d2ccccad529e994c8176842.html Return Value: 是USB设备则返回TRUE,否则返回FALSE, 查询失败也返回FALSE。 --*/ { PIRP pNewIrp; PSTORAGE_DEVICE_DESCRIPTOR pStorageDeviceDescriptor; STORAGE_PROPERTY_QUERY StoragePropertyQuery; CHAR buff[128]; KEVENT WaitEvent; NTSTATUS Status; IO_STATUS_BLOCK IoStatus; StoragePropertyQuery.PropertyId = StorageDeviceProperty; StoragePropertyQuery.QueryType = PropertyStandardQuery; KeInitializeEvent(&WaitEvent, NotificationEvent, FALSE); pNewIrp = IoBuildDeviceIoControlRequest( IOCTL_STORAGE_QUERY_PROPERTY,pDeviceObject, (PVOID)&StoragePropertyQuery, sizeof(StoragePropertyQuery), (PVOID)buff, sizeof(buff), FALSE, &WaitEvent, &IoStatus ); if (!pNewIrp) { // 创建 IRP 失败 return FALSE; } Status = IoCallDriver(pDeviceObject, pNewIrp); if (Status == STATUS_PENDING) { Status = KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL); Status = IoStatus.Status; } if (!NT_SUCCESS(Status)) { // 查询失败 return FALSE; } pStorageDeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)buff; // 返回结果 return pStorageDeviceDescriptor->BusType == BusTypeUsb; }