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

    xiaoxiao2022-06-27  179

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


    最新回复(0)