igor.sol
igor.sol

Reputation: 647

Converting volume GUID path to device path

My task is to track adding and deleting disk drives from windows service. I use RegisterServiceCtrlHandlerEx and RegisterDeviceNotification to implement this. My service control handler routine succefully receives SERVICE_CONTROL_DEVICEEVENT control code and handles DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events for GUID_DEVINTERFACE_VOLUME clsss. By the way windows does not send DBT_DEVICEQUERYREMOVE, DBT_DEVICEQUERYREMOVEFAILED, DBT_DEVICEREMOVEPENDING events to my routine but now i want to solve another problem.

When i receive DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events and dbch_devicetype is DBT_DEVTYP_DEVICEINTERFACE i can read device name from dbcc_name field of DEV_BROADCAST_DEVICEINTERFACE structure. It looks like this: \?\STORAGE#RemovableMedia#7&331a4e33&0&RM#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}

I can convert this string to volume guid path using GetVolumeNameForVolumeMountPoint procedure only on DBT_DEVICEARRIVAL event. On DBT_DEVICEREMOVECOMPLETE event GetVolumeNameForVolumeMountPoint returns error 3 (The system cannot find the path specified).

On the other hand during service start i do scan for all volumes in the system with FindFirstVolume/FindNextVolume which returns to me list of volume GUID paths of all volumes.

So if volume exists when my service starts i can receive its volume GUID path. And if that volume will be removed while my service is running then i will receive device name (like \?\STORAGE#RemovableMedia#7&331a4e33&0&RM#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b} ) from DBT_DEVICEREMOVECOMPLETE event.

As i wrote above i can not use GetVolumeNameForVolumeMountPoint during DBT_DEVICEREMOVECOMPLETE event to get volume GUID path. So i would like to find a way to convert volume GUID path received from FindFirstVolume/FindNextVolume to device name. I need this to maintain my own list of present removable disk drives in the system.

Please give me some advice on this problem.

Upvotes: 2

Views: 3931

Answers (2)

igor.sol
igor.sol

Reputation: 647

So i found no way to retrieve device paths from volume GUID paths returned by FindFisrtVolume/FindNextVolume. Instead i will replace FindFisrtVolume/FindNextVolume with enumerating device interfaces using SetupApi.

Here is steps to do that:

  1. Call SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME,NULL,NULL,DIGCF_INTERFACEDEVICE|DIGCF_PRESENT) to retrieve device info set.
  2. Enum device interfaces with SetupDiEnumDeviceInterfaces(devinfoset,NULL,&GUID_DEVINTERFACE_VOLUME,idx,&devitf).
  3. For each device interface call SetupDiGetDeviceInterfaceDetail to retrieve device path.

Unfortunately device path retrieved in this way differs in case from device path which windows passes in DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events. So we need to normalize device paths when we compare them.

Upvotes: 1

Heinrich Ulbricht
Heinrich Ulbricht

Reputation: 10372

To enumerate devices for building your own device list you can use the SetupAPI:

By using the SetupAPI routines, you can enumerate all devices in the specified device interface class and retrieve the device path of the device.

You call SetupDiGetClassDevs first with an appropriate GUID for your device class, e.g. GUID_DEVINTERFACE_VOLUME, then call SetupDiEnumDeviceInfo repeatedly to iterate devices.

Example code showing how to do it:

  • Knowledge base article showing it all
  • Another description of the process can be found here, have a look for the section Use the following steps to create a file handle for the USB device.

The individual devices can be queried for properties (the path is among them) using SetupDiGetDeviceRegistryProperty.

Upvotes: 1

Related Questions