使用SetupDiGetDeviceRegistryProperty获取驱动器类型

时间:2010-06-07 13:05:57

标签: c++ winapi usb

我想知道我是否可以使用

获取驱动器信息

SP_DEVICE_INTERFACE_DETAIL_DATA的DevicePath

我的设备路径如下所示

“\ \ USB#vid_04f2&安培; pid_0111#5和; 39fe81e&安培; 0和2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}”

请在winapi中告诉我他们说“要确定驱动器是否是USB型驱动器,请调用SetupDiGetDeviceRegistryProperty并指定SPDRP_REMOVAL_POLICY属性。”

我也使用下面的SetupDiGetDeviceRegistryProperty

while ( !SetupDiGetDeviceRegistryProperty( hDevInfo,&DeviceInfoData,
    SPDRP_REMOVAL_POLICY,&DataT,( PBYTE )buffer,buffersize,&buffersize ))

但我不知道如何使用上面的驱动器类型..

请帮帮我

3 个答案:

答案 0 :(得分:4)

我创建了一个带有可选掩码的GetMountedVolumes方法,以指定搜索中应包含哪些类型的卷(可读,可写,可移除,可热插拔,可擦除)。

我完全弃用了Setup API方法,只使用了DeviceIoControl调用的空访问卷句柄(不需要管理权限)。我将分享我的代码,这可能会帮助其他人实现确定驱动器(卷)类型的方法,而无需使用安装程序API。

enum VolumesFlags {
    VolumeReadable = 1,
    VolumeWriteable = 2,
    VolumeEraseable = 4,
    VolumeRemoveable = 8,
    VolumeHotplugable = 16,
    VolumeMounted = 128
};

bool GetMountedVolumes(std::vector<std::wstring> &Volumes,
    unsigned int Flags = VolumeReadable | VolumeWriteable,
    unsigned int Mask = VolumeReadable | VolumeWriteable) {

    wchar_t Volume[MAX_PATH] = {0};
    wchar_t* VolumeEndPtr = Volume;

    Flags |= VolumeMounted;
    Mask |= VolumeMounted;
    Flags &= Mask;

    HANDLE hFind = FindFirstVolume(Volume, sizeof(Volume) / sizeof(wchar_t));
    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            bool IsMatching = false;
            VolumeEndPtr = &Volume[wcslen(Volume) - 1];
            *VolumeEndPtr = L'\0';

            HANDLE hDevice = CreateFile(Volume, 0, 0, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
            if (hDevice != INVALID_HANDLE_VALUE) {

                unsigned int CurrentFlags = 0;

                DWORD ReturnedSize;
                STORAGE_HOTPLUG_INFO Info = {0};

                if (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_HOTPLUG_INFO, 0, 0, &Info, sizeof(Info), &ReturnedSize, NULL)) {
                    if (Info.MediaRemovable) {
                        CurrentFlags |= VolumeRemoveable;
                    }
                    if (Info.DeviceHotplug) {
                        CurrentFlags |= VolumeHotplugable;
                    }
                }

                DWORD MediaTypeSize = sizeof(GET_MEDIA_TYPES);
                GET_MEDIA_TYPES* MediaType = (GET_MEDIA_TYPES*) new char[MediaTypeSize];

                while (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_MEDIA_TYPES_EX, 0, 0, MediaType, MediaTypeSize, &ReturnedSize, NULL) == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                    delete [] (char*) MediaType;
                    MediaTypeSize *= 2;
                    MediaType = (GET_MEDIA_TYPES*) new char[MediaTypeSize];
                }

                if (MediaType->MediaInfoCount > 0) {
                    DWORD Characteristics = 0;
                    // Supports: Disk, CD, DVD
                    if (MediaType->DeviceType == FILE_DEVICE_DISK || MediaType->DeviceType == FILE_DEVICE_CD_ROM || MediaType->DeviceType == FILE_DEVICE_DVD) {
                        if (Info.MediaRemovable) {
                            Characteristics = MediaType->MediaInfo[0].DeviceSpecific.RemovableDiskInfo.MediaCharacteristics;
                        } else {
                            Characteristics = MediaType->MediaInfo[0].DeviceSpecific.DiskInfo.MediaCharacteristics;
                        }

                        if (Characteristics & MEDIA_CURRENTLY_MOUNTED) {
                            CurrentFlags |= VolumeMounted;
                        }
                        if (Characteristics & (MEDIA_READ_ONLY | MEDIA_READ_WRITE)) {
                            CurrentFlags |= VolumeReadable;
                        }
                        if (((Characteristics & MEDIA_READ_WRITE) != 0 || (Characteristics & MEDIA_WRITE_ONCE) != 0) && (Characteristics & MEDIA_WRITE_PROTECTED) == 0 && (Characteristics & MEDIA_READ_ONLY) == 0) {
                            CurrentFlags |= VolumeWriteable;
                        }
                        if (Characteristics & MEDIA_ERASEABLE) {
                            CurrentFlags |= VolumeEraseable;
                        }
                    }
                }

                delete [] (char*) MediaType;

                CloseHandle(hDevice);

                CurrentFlags &= Mask;

                if (CurrentFlags == Flags) {
                    *VolumeEndPtr = L'\\';                  
                    wchar_t VolumePaths[MAX_PATH] = {0};
                    if (GetVolumePathNamesForVolumeName(Volume, VolumePaths, MAX_PATH, &ReturnedSize)) {
                        if (*VolumePaths) {
                            Volumes.push_back(VolumePaths);
                        }
                    }
                }

            }
        } while (FindNextVolume(hFind, Volume, sizeof(Volume) / sizeof(wchar_t)));
        FindVolumeClose(hFind);
    }

    return Volumes.size() > 0;
}

答案 1 :(得分:2)

您可能会在http://support.microsoft.com/kb/264203/en找到您所寻找的内容。另一个链接http://support.microsoft.com/kb/305184/en对你来说也很有趣。

更新:来自http://support.microsoft.com/kb/264203/en的示例向您展示了如何使用来确定USB驱动器是否可移动。您还可以在设备实例上使用SetupDiGetDeviceRegistryProperty SPDRP_REMOVAL_POLICY(使用SetupDiEnumDeviceInfoSetupDiGetDeviceInstanceId,然后SetupDiGetDeviceRegistryProperty)。如果返回DWORD的值为CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVALCM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL,则驱动器可以移除。

此外,代码示例显示了如何打开设备句柄,您可以使用DeviceIoControl函数来检索您可能需要的许多有用信息。 IOCTL_STORAGE_QUERY_PROPERTY {(http://msdn.microsoft.com/en-us/library/ff566997%28v=VS.85%29.aspxQueryTypePropertyId只有一个例子。例如,您可以使用IOCTL_STORAGE_GET_DEVICE_NUMBER来接收存储卷及其磁盘编号。

如果您有关于USB设备的完整STORAGE_DEVICE_NUMBER信息,我们将能够以不同的方式查找有关它的所有其他信息。最简单的方法之一是:只使用QueryDosDevice枚举所有驱动器号并为每个驱动器查询STORAGE_DEVICE_NUMBER。如果您在STORAGE_DEVICE_NUMBER找到完整匹配,您将找到驱动器号。

答案 2 :(得分:0)

鉴于您的+=

不同的存储总线类型是

  • BusTypeScsi :SCSI
  • BusTypeAtapi :ATAPI
  • BusTypeAta :ATA
  • BusType1394 :IEEE-1394
  • BusTypeSsa :SSA
  • BusTypeFibre :光纤通道
  • BusTypeUsb :USB
  • BusTypeRAID :RAID
  • BusTypeiSCSI :iSCSI
  • BusTypeSas :串行连接SCSI(SAS)
  • BusTypeSata :SATA

示例psueudo-code

STORAGE_DEVICE_DESCRIPTOR {
  DWORD            Version;
  DWORD            Size;
  BYTE             DeviceType;
  BYTE             DeviceTypeModifier;
  BOOLEAN          RemovableMedia;
  BOOLEAN          CommandQueueing;
  DWORD            VendorIdOffset;
  DWORD            ProductIdOffset;
  DWORD            ProductRevisionOffset;
  DWORD            SerialNumberOffset;
  STORAGE_BUS_TYPE BusType;         //<---------------
  DWORD            RawPropertiesLength;
  BYTE             RawDeviceProperties[1];