将卷GUIDpath转换为设备path

我的任务是跟踪从Windows服务添加和删除磁盘驱动器。 我使用RegisterServiceCtrlHandlerEx和RegisterDeviceNotification来实现这一点。 我的服务控制处理程序例程成功接收SERVICE_CONTROL_DEVICEEVENT控制代码,并处理GUID_DEVINTERFACE_VOLUME clsss的DBT_DEVICEAREMIVAL和DBT_DEVICEREMOVECOMPLETE事件。 顺便说一句,Windows不会发送DBT_DEVICEQUERYREMOVE,DBT_DEVICEQUERYREMOVEFAILED,DBT_DEVICEREMOVEPENDING事件到我的例程,但现在我想解决另一个问题。

当我收到DBT_DEVICEARRIVAL和DBT_DEVICEREMOVECOMPLETE事件和dbch_devicetype是DBT_DEVTYP_DEVICEINTERFACE我可以从DEV_BROADCAST_DEVICEINTERFACE结构的dbcc_name字段读取设备名称。 它看起来像这样:\?\ STORAGE#RemovableMedia#7&331a4e33&0&RM#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}

我只能在DBT_DEVICEARRIVAL事件中使用GetVolumeNameForVolumeMountPoint过程将此string转换为卷GUIDpath。 在DBT_DEVICEREMOVECOMPLETE事件GetVolumeNameForVolumeMountPoint返回错误3(系统找不到指定的path)。

另一方面,在服务启动期间,我使用FindFirstVolume / FindNextVolume扫描系统中的所有卷,并返回给我所有卷的GUIDpath列表。

所以如果卷存在,当我的服务启动我可以收到其卷GUIDpath。 如果这个卷将被删除,而我的服务正在运行,那么我将从DBT_DEVICEREMOVECOMPLETE事件接收设备名称(如\?\ STORAGE#RemovableMedia#7&331a4e33&0&RM#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b})。

正如我上面写的,我不能使用GetVolumeNameForVolumeMountPoint在DBT_DEVICEREMOVECOMPLETE事件获取卷GUIDpath。 所以我想find一种方法来将从FindFirstVolume / FindNextVolume接收到的卷GUIDpath转换为设备名称。 我需要这个维护我自己的系统中的可移动磁盘驱动器列表。

请给我一些关于这个问题的build议。

要枚举用于构建自己的设备列表的设备,可以使用SetupAPI :

通过使用SetupAPI例程,可以枚举指定的设备接口类中的所有设备,并检索设备的设备路径。

首先调用SetupDiGetClassDevs,并为设备类使用适当的GUID,例如GUID_DEVINTERFACE_VOLUME ,然后重复调用SetupDiEnumDeviceInfo来迭代设备。

示例代码显示如何执行此操作:

  • 知识库文章显示这一切
  • 这个过程的另一个描述可以在这里找到,查看这个部分使用以下步骤为USB设备创建一个文件句柄。

可以使用SetupDiGetDeviceRegistryProperty查询各个设备的属性(路径在其中)。

所以我找不到从FindFisrtVolume / FindNextVolume返回的卷GUID路径检索设备路径。 相反,我将使用SetupApi枚举设备接口来替换FindFisrtVolume / FindNextVolume。

这是步骤:

  1. 调用SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME,NULL,NULL,DIGCF_INTERFACEDEVICE | DIGCF_PRESENT)来检索设备信息集。
  2. 枚举设备与SetupDiEnumDeviceInterfaces(devinfoset,NULL,&GUID_DEVINTERFACE_VOLUME,idx和&devitf)接口。
  3. 对于每个设备接口调用SetupDiGetDeviceInterfaceDetail来检索设备路径。

不幸的是,以这种方式检索到的设备路径与窗口在DBT_DEVICEARRIVAL和DBT_DEVICEREMOVECOMPLETE事件中传递的设备路径不同。 所以当我们比较它们时,我们需要规范设备路径。