说明:
有时候我们在做设备监控的时候,要识别一些链接设备,在使用函数GetDriveType的时候,U盘可以返回DRIVE_REMOVABLE,而本地硬盘硬盘和移动硬盘DRIVE_FIXED,因此还需要进一步来识别。识别方法为判断设备的总线类型即可:需要用到的数据类型以及函数有:
//将所有的卷存储在buffer中,格式为:C:/NULLD:/NULLE:/NULL
DWORD GetLogicalDriveStrings(
DWORD nBufferLength, // size of buffer
LPTSTR lpBuffer // drive strings buffer);
//判断设备类型:
UINT GetDriveType( LPCTSTR lpRootPathName // root directory);
返回值有:
#define DRIVE_UNKNOWN 0
#define DRIVE_NO_ROOT_DIR 1
#define DRIVE_REMOVABLE 2
#define DRIVE_FIXED 3
#define DRIVE_REMOTE 4
#define DRIVE_CDROM 5
#define DRIVE_RAMDISK 6//DeviceIoControl要查询的类型
typedef struct _STORAGE_PROPERTY_QUERY {// ID of the property being retrievedSTORAGE_PROPERTY_ID PropertyId;//使用前要对此字段赋值// Flags indicating the type of query being performedSTORAGE_QUERY_TYPE QueryType; //使用前要对此字段赋值// Space for additional parameters if necessaryBYTE AdditionalParameters[1];} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;// STORAGE_PROPERTY_ID枚举类型
typedef enum _STORAGE_PROPERTY_ID {StorageDeviceProperty = 0,StorageAdapterProperty,StorageDeviceIdProperty,StorageDeviceUniqueIdProperty, // See storduid.h for detailsStorageDeviceWriteCacheProperty,StorageMiniportProperty,StorageAccessAlignmentProperty,StorageDeviceSeekPenaltyProperty,StorageDeviceTrimProperty,StorageDeviceWriteAggregationProperty,StorageDeviceDeviceTelemetryProperty,StorageDeviceLBProvisioningProperty,StorageDevicePowerProperty,StorageDeviceCopyOffloadProperty,StorageDeviceResiliencyProperty,StorageDeviceMediumProductType,
} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;//STORAGE_QUERY_TYPE枚举
typedef enum _STORAGE_QUERY_TYPE {PropertyStandardQuery = 0, // Retrieves the descriptorPropertyExistsQuery, // Used to test whether the descriptor is supportedPropertyMaskQuery, // Used to retrieve a mask of writeable fields in the descriptorPropertyQueryMaxDefined // use to validate the value
} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;//我们的输出结构:typedef _Struct_size_bytes_(Size) struct _STORAGE_DEVICE_DESCRIPTOR {// Sizeof(STORAGE_DEVICE_DESCRIPTOR)DWORD Version;// Total size of the descriptor, including the space for additional data and id stringsDWORD Size;// The SCSI-2 device typeBYTE DeviceType;// The SCSI-2 device type modifier (if any) - this may be zeroBYTE DeviceTypeModifier; // Flag indicating whether the device's media (if any) is removable. This// field should be ignored for media-less devices BOOLEAN RemovableMedia; // Flag indicating whether the device can support mulitple outstanding// commands. The actual synchronization in this case is the responsibility of the port driver.BOOLEAN CommandQueueing; // Byte offset to the zero-terminated ascii string containing the device's// vendor id string. For devices with no such ID this will be zero DWORD VendorIdOffset; // Byte offset to the zero-terminated ascii string containing the device's// product id string. For devices with no such ID this will be zero DWORD ProductIdOffset; // Byte offset to the zero-terminated ascii string containing the device's// product revision string. For devices with no such string this will be zero DWORD ProductRevisionOffset; // Byte offset to the zero-terminated ascii string containing the device's// serial number. For devices with no serial number this will be zero DWORD SerialNumberOffset; // Contains the bus type (as defined above) of the device. It should be// used to interpret the raw device properties at the end of this structure// (if any) STORAGE_BUS_TYPE BusType; // The number of bytes of bus-specific data which have been appended to this descriptorDWORD RawPropertiesLength; // Place holder for the first byte of the bus specific property data BYTE RawDeviceProperties[1];
} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;//最后要根据BusType字段来判断 看一些这个类型:
typedef enum _STORAGE_BUS_TYPE {BusTypeUnknown = 0x00,BusTypeScsi,BusTypeAtapi,BusTypeAta,BusType1394,BusTypeSsa,BusTypeFibre,BusTypeUsb,//这个就是移动硬盘了BusTypeRAID,BusTypeiScsi,BusTypeSas,BusTypeSata,BusTypeSd,BusTypeMmc,BusTypeVirtual,BusTypeFileBackedVirtual,BusTypeSpaces,BusTypeNvme,BusTypeMax,BusTypeMaxReserved = 0x7F
} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;//下面附一段代码测试:int _tmain(int argc, _TCHAR* argv[])
{DWORD dwReturnLen = 0;PWCHAR pDrive = NULL;WCHAR wszDrive[MAX_PATH] = { 0 };dwReturnLen = GetLogicalDriveStringsW(MAX_PATH, wszDrive);//WCHAR wszName[MAX_PATH] = { 0 };HANDLE hDevice = NULL;if (dwReturnLen < MAX_PATH){pDrive = wszDrive;while (*pDrive){UINT uType = 0;uType = GetDriveTypeW(pDrive);if (uType == DRIVE_REMOVABLE){printf("%ws:U盘.\n", pDrive);}else if (uType == DRIVE_CDROM){printf("%ws:光驱.\n", pDrive);}else if (uType == DRIVE_FIXED){//进一步判断移动硬盘或者本地硬盘wstring wstrName(L"\\\\.\\");wstrName.append(pDrive, 2);/*经测试\\.\C:\这种格式打不开,*如换成\\.\C:就可以打开了*/hDevice = CreateFileW(wstrName.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,0, NULL);if (INVALID_HANDLE_VALUE == hDevice){printf("createFile error code:(0x%08x).\n", GetLastError());getchar();return 0;}//输入查询参数STORAGE_PROPERTY_QUERY PropertyQuery;//初始化PropertyQueryPropertyQuery.PropertyId = StorageDeviceProperty;PropertyQuery.QueryType = PropertyStandardQuery;BOOL bResult;DWORD dwBytesReturned = 0;//查询结果结构STORAGE_DEVICE_DESCRIPTOR deviceDescriptor = { 0 };deviceDescriptor.Size = sizeof(STORAGE_DEVICE_DESCRIPTOR);//STORAGE_BUS_TYPEbResult = DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, //系统内置控制码&PropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), &deviceDescriptor, deviceDescriptor.Size, &dwBytesReturned, NULL);if (bResult){//依据总线类型来判断//printf("device:%ws storage bus type:%d \n", pDrive, deviceDescriptor.BusType);if (BusTypeUsb == deviceDescriptor.BusType)printf("%ws:移动硬盘 \n", pDrive);else//这里还可以再进一步详细划分printf("%ws:本地硬盘 \n", pDrive);}CloseHandle(hDevice);hDevice = NULL;}else //if (uType == DRIVE_UNKNOWN){printf("%ws:未知.\n", pDrive);}pDrive += 4;}}getchar();return 0;
}
测试结果:

说明:这里的结果是我自己的电脑上插了两个U盘,分别是8G和16G的,还有一个移动硬盘,自带一个光驱,安装了一个虚拟光驱。可以都能正确的识别出来
参考链接:
http://blog.sina.com.cn/s/blog_56f9f160010009gp.html
http://blog.csdn.net/sloan6/article/details/7874554