Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
279 views
in Technique[技术] by (71.8m points)

c++ - Get drive type with SetupDiGetDeviceRegistryProperty

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

"?usb#vid_04f2&pid_0111#5&39fe81e&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"

also please tell me in the winapi they say "To determine whether a drive is a USB-type drive, call SetupDiGetDeviceRegistryProperty and specify the SPDRP_REMOVAL_POLICY property."

i too use SetupDiGetDeviceRegistryProperty like below

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

but i dont know how can i get the drive type using the above..

Please help me up

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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<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'';

            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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...