Get drive type with SetupDiGetDeviceRegistryProperty

前端 未结 3 899
广开言路
广开言路 2020-12-17 08:22

I would like to know whether i can get the drive information using the

SP_DEVICE_INTERFACE_DETAIL_DATA\'s DevicePath

my device path looks like below

3条回答
  •  -上瘾入骨i
    2020-12-17 09:02

    I've created a GetMountedVolumes method with optional mask to specify what type of volumes should be included in the search (readable, writeable, removeable, hotplugable, eraseable).

    I abstained from Setup API methods at all and only used null access volume handle for DeviceIoControl calls (no administrative privileges are required). I will share my code, may be this will help others to implement methods to determine drive (volume) type without using Setup API.

    enum VolumesFlags {
        VolumeReadable = 1,
        VolumeWriteable = 2,
        VolumeEraseable = 4,
        VolumeRemoveable = 8,
        VolumeHotplugable = 16,
        VolumeMounted = 128
    };
    
    bool GetMountedVolumes(std::vector &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;
    }
    

提交回复
热议问题