4

我们制造和销售一种设备,我们的用户有时会希望通过多个 USB 集线器大量连接到他们的计算机。它是一种同时具有人机接口 (HID) 和大容量存储 (MSD) 接口的 USB 复合设备。Windows 会自动挂载每个设备的文件系统,直到“Z:”处的字母用完为止。

我可以使用PnP 配置管理器设备安装功能的组合遍历设备树并获取 HID 和 USBSTOR 接口的设备实例标识符。通过 USB 存储设备路径,我还可以获得磁盘号(即\\.\PhysicalDrive1)。

下一步是通过在与设备通信时循环输出驱动器号来根据需要安装这些磁盘,或者更好的是,将它们安装在 C: 驱动器上的临时目录中。我在尝试使用DefineDosDevice执行此任务时遇到困难,并且无法使用 SetVolumeMountPoint 取得进展,因为设备在安装之前没有卷 GUID 。这提出了一个先有鸡还是先有蛋的问题。

要是我们的客户使用unix就好了!!!

4

2 回答 2

8

Windows 不挂载磁盘;它安装卷。但是,USBSTOR 类设备的卷并未列为设备树中的子节点。因此,您必须枚举所有卷,并进行一系列字符串操作和比较,以将 STORAGE\VOLUME 节点与 USBSTOR 节点匹配。

所有卷 GUID 值都使用FindFirstVolume函数集进行枚举。可以去除前导“\.\”和尾随“\”字符,然后将生成的字符串传递给QueryDosDevice。这提供了一个设备名称。

接下来,必须使用带有SetupDiGetClassDevs和朋友的 GUID_DEVINTERFACE_VOLUME 枚举所有卷。使用IOCTL_STORAGE_GET_DEVICE_NUMBER将每个卷的设备类型和数量与您要查找的 USBSTOR 设备进行比较。一旦这些匹配,您可以从卷中获取设备名称并将其与其他设备名称列表进行比较以查找卷 GUID。

最后,卷 GUID 可以成功地与SetVolumeMountPoint一起使用。

感谢Gabe在对我的问题的评论中提供的非常有帮助的帮助。


代码片段

从设备路径获取设备类型和编号:

STORAGE_DEVICE_NUMBER sdn;
HANDLE handle = CreateFile(devInterfaceDetail->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL);
DWORD len = 0;
DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof (sdn), &len, NULL);

通过遍历所有卷接口并比较上述代码段中的磁盘号,找到相应 USBSTOR 实例的设备名称:

std::string deviceName;
HDEVINFO devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_DEVICE_INTERFACE_DATA devInterface = { 0 };
devInterface.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
for (int i = 0; SetupDiEnumDeviceInterfaces(devInfoSet, NULL, &GUID_DEVINTERFACE_VOLUME, i, &devInterface); ++i) {
    SP_DEVINFO_DATA devInfoData = { 0 };
    devInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
    DWORD len;
    SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterface, NULL, 0, &len, &devInfoData);
    std::vector<char> buf(len);
    SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetail = (SP_DEVICE_INTERFACE_DETAIL_DATA *) &buf[0];
    devInterfaceDetail->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
    if (SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterface, devInterfaceDetail, len, NULL, &devInfoData)) {
        if (DEVICE_NUMBER == this->getDeviceNumber(devInterfaceDetail->DevicePath)) {
            std::vector<BYTE> buf(MAX_PATH + 1);
            DWORD type, len;
            if (SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, &type, &buf[0], buf.size(), &len)) {
                deviceName.assign(buf.begin(), buf.begin() + len);
                break;
            }
        }
    }
}
于 2010-09-24T21:17:44.173 回答
0

在我看来,您必须使用IOCTL_MOUNTMGR_CREATE_POINT. 不幸的是,使用的大多数示例IOCTL_MOUNTMGR_XXX都是为内核模式驱动程序编写的,但这不是必需的。可能我的旧答案(使用IOCTL_MOUNTMGR_QUERY_POINTS)和另一个可以帮助你做到这一点。另请参阅http://msdn.microsoft.com/en-us/library/ff567603.aspxhttp://support.microsoft.com/kb/836662

可能在更好地理解IOCTL_MOUNTMGR_CREATE_POINT应该如何使用之后,您将能够解决有关SetVolumeMountPoint的问题。

于 2010-09-27T00:05:10.527 回答