C++ 实现判断插入USB的设备是U盘,移动硬盘,光驱

今天做项目,要求代码能区分出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;
}

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值