今天做项目,要求代码能区分出U盘,移动硬盘,光驱等。
有时候我们在做设备监控的时候,要识别一些链接设备,在使用函数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 //The drive type cannot be determined. 未知
#define DRIVE_NO_ROOT_DIR 1 //The root path is invalid; for example, there is no volume is mounted at the path. 可移动磁盘
#define DRIVE_REMOVABLE 2 //The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader. U盘,软盘
#define DRIVE_FIXED 3//The drive has fixed media; for example, a hard drive or flash drive. 本地硬盘,移动硬盘
#define DRIVE_REMOTE 4 //The drive is a remote (network) drive.网络磁盘
#define DRIVE_CDROM 5 //The drive is a CD-ROM drive. CD-ROM
#define DRIVE_RAMDISK 6 //The drive is a RAM disk. RAM磁盘
//DeviceIoControl要查询的类型 typedef struct _STORAGE_PROPERTY_QUERY { // ID of the property being retrieved STORAGE_PROPERTY_ID PropertyId;//使用前要对此字段赋值 // Flags indicating the type of query being performed STORAGE_QUERY_TYPE QueryType; //使用前要对此字段赋值 // Space for additional parameters if necessary BYTE 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 details StorageDeviceWriteCacheProperty, 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 descriptor PropertyExistsQuery, // Used to test whether the descriptor is supported PropertyMaskQuery, // Used to retrieve a mask of writeable fields in the descriptor PropertyQueryMaxDefined // 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 strings DWORD Size; // The SCSI-2 device type BYTE DeviceType; // The SCSI-2 device type modifier (if any) - this may be zero BYTE 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 descriptor DWORD 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;
封装的函数代码如下:
#include "stdafx.h" #include <Windows.h> #include <Winioctl.h>
INT GetBusType(TCHAR driver) { bool bResult = true; INT BusType = BusTypeUnknown; HANDLE hDrv = INVALID_HANDLE_VALUE; STORAGE_DEVICE_DESCRIPTOR DevDesc; STORAGE_PROPERTY_QUERY ProQuery;
TCHAR tszSymbol[MAX_PATH] = {TEXT("\\\\?\\*:")}; ULONG ulBytesResults = 0; memset(&ProQuery, 0 ,sizeof(ProQuery)); memset(&DevDesc, 0, sizeof(DevDesc));
if ((driver >= TEXT('A') && driver <= TEXT('Z')) || (driver >= TEXT('a') && driver <= TEXT('z'))) {
} else { return false; }
tszSymbol[4] = driver;
hDrv = CreateFile(tszSymbol, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDrv == INVALID_HANDLE_VALUE) goto jump_ret;
ProQuery.QueryType = PropertyStandardQuery; ProQuery.PropertyId = StorageDeviceProperty; if (DeviceIoControl(hDrv,IOCTL_STORAGE_QUERY_PROPERTY, &ProQuery,sizeof(ProQuery), &DevDesc, sizeof (DevDesc), &ulBytesResults, NULL) == FALSE) goto jump_ret;
BusType = DevDesc.BusType;
jump_ret: if (hDrv != INVALID_HANDLE_VALUE) { CloseHandle(hDrv); hDrv = INVALID_HANDLE_VALUE; } return BusType; }
bool IsCDRom(TCHAR driver) //判断是否是光盘 { UINT DriverType = DRIVE_UNKNOWN; TCHAR tszDriver[4] = {TEXT("*:\\")};
tszDriver[0] = driver; DriverType = GetDriveType(tszDriver);
return DriverType == DRIVE_CDROM; }
bool IsRemovableDrive(TCHAR driver) //判断是可移动硬盘 true:移动硬盘,false:本地硬盘 { UINT DriverType = DRIVE_UNKNOWN; TCHAR tszDriver[4] = {TEXT("*:\\")};
tszDriver[0] = driver; DriverType = GetDriveType(tszDriver);
bool bRemovableDrive = false; if (DriverType == DRIVE_FIXED) { if (GetBusType(driver) == BusTypeUsb) bRemovableDrive = true; }
return bRemovableDrive; }
bool IsUDrive(TCHAR driver) //判断是否是U盘 { TCHAR tszDriver[4] = {TEXT("*:\\")}; UINT DriverType = DRIVE_UNKNOWN; tszDriver[0] = driver; DriverType = GetDriveType(tszDriver); return DriverType == DRIVE_REMOVABLE; }
int _tmain(int argc, _TCHAR* argv[]) {
bool bU = IsUDrive(L'H');
bool bRemovable = IsRemovableDrive(L'H');
bool bIsCD = IsCDRom(L'H');
getchar(); return 0; }