1

I am attempting to write C++/Win32 code that can determine if a given file path refers to a fixed disk. (I absolutely may not use WMI for this task.)

My best bet - at least from this thread -- appear to be the SetupDiXXXX functions. So that's what I'm trying.

I'm already successfully enumerating disks devices using SetupDiGetClassDevs and verifying that they are fixed.

// Get all devices classes of type "DISKDRIVE"

const auto hDevInfo = SetupDiGetClassDevs(
    &GUID_DEVCLASS_DISKDRIVE, 
    nullptr, 
    nullptr, 
    DIGCF_PRESENT);

But to link a device back to a given disk path, I would appear (from that thread I mentioned) that I also need to enumerate device interfaces. According to the documentation, That means I must supply the DIGCF_DEVICEINTERFACE flag to SetupDiGetClassDevs. That means I must also supply an "enumerator" argument to the same function. And this leads me to my question.

Where is the list of valid enumerators I may use for SetupDiGetClassDevs and GUID_DEVCLASS_DISKDRIVE? Is there a list?

I already know of one: "SCSI". But this code needs to work on anybody's machine. So what others should I check? Is there a header file somewhere that lists them all? Is there a function I can call to enumerate them?

(I would do this using DeviceIoControl if I could but it does not appear, from what I have read, that it will give me truly reliable information on whether or not a drive is fixed)

Joe
  • 5,394
  • 3
  • 23
  • 54
  • Your first paragraph suggests this might be an XY problem. `GetDriveType()` can tell you if a file path is on a fixed disk. Use `GetFinalPathNameByHandle()` to take symbolic links etc into account. – Jonathan Potter Jan 08 '19 at 19:45
  • Thanks for replying. Unfortunately GetDriveType will report detachable USB disks as fixed. I need something more reliable. WMI was reliable but it was Godawful slow so I am tasked with finding another way – Joe Jan 08 '19 at 19:58
  • 1
    you can say get [`STORAGE_DEVICE_DESCRIPTOR`](https://learn.microsoft.com/en-us/windows/desktop/api/winioctl/ns-winioctl-_storage_device_descriptor) for device via `IOCTL_STORAGE_QUERY_PROPERTY` but even for some usb flash you can got `RemovableMedia == false`. what is you have as input and what you exactly try got ? – RbMm Jan 08 '19 at 20:51
  • I have not even bothered with with using Ioctl with this because I encountered a number of threads in which people found USB devices reporting themselves as non removable. That makes sense. I don't want to ask the device if it is removable. I want to ask Windows. – Joe Jan 08 '19 at 21:01
  • 1
    I have managed to be able to get around the need for knowing what enumerators are available by instead keeping my call as it was then enumerating the devices (SetupDiEnumDeviceInfo), retrieving the DeviceInstanceID (CM_Get_Device_IDA), and then using that open up the class devices (SetupDiGetClassDevs). From there, I called SetupDiEnumDeviceInfo and then that gave me what I needed to call SetupDiEnumDeviceInterfaces. What a nightmare this API is – Joe Jan 08 '19 at 22:00
  • *To determine whether a drive is a USB-type drive, call SetupDiGetDeviceRegistryProperty and specify the SPDRP_REMOVAL_POLICY property* – Jonathan Potter Jan 08 '19 at 22:26
  • 1
    Thanks, I am already doing that, although I'm using SetupDiGetDeviceProperty, not SetupDiGetDeviceRegisteryProperty as you described. However I also needed to be able to enumerate the interfaces in SetupDiXXX functions so that I could get its device path from SetupDiGetDeviceInterfaceDetail. That led me to this question – Joe Jan 08 '19 at 23:15
  • 1
    `GetDriveType()` -> if `DRIVE_FIXED`, check `SPDRP_REMOVAL_POLICY` to exclude USB. – Jonathan Potter Jan 09 '19 at 00:44
  • Not sure how that would help me. I think SPDRP_REMOVAL_POLICY should by itself be enough for me to know if a drive is a fixed drive. Even if not it still doesn't solve my problem of matching a device volume (e.g. "c:") to the... device for which I'm determining SPDRP_REMOVAL_POLICY. How to know they're the same? What do I compare? I am callingl SetupDiGetDeviceInterfaceDetail get the device path, (from SP_DEVICE_INTERFACE_DETAIL_DATA), open up that device as I did "C:", and then using DeviceIoControl to compare STORAGE_DEVICE_NUMBERs – Joe Jan 09 '19 at 04:43
  • 1
    yes, you can detect that 2 paths belong to the same physical drive, bu compare `STORAGE_DEVICE_NUMBER.DeviceNumber`. also instead use Setup api more easy and efficient use CM_ api. however what exactly you have as input and what you need get. – RbMm Jan 09 '19 at 10:10
  • 1
    Yes I *am* comparing STORAGE_DEVICE_NUMBERS. But again, the only way that I could see to get that from SetupDiXXXX functions was to enumerate the device *interfaces*. Hence this thread. – Joe Jan 09 '19 at 10:44

0 Answers0