代码之家  ›  专栏  ›  技术社区  ›  Judge Maygarden

如何在Windows中以编程方式挂载驱动器?

  •  4
  • Judge Maygarden  · 技术社区  · 14 年前

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

    我可以遍历设备树,并使用 PnP Configuration Manager Device Installation \\.\PhysicalDrive1 ).

    DefineDosDevice 因为这项任务而无法取得进展 SetVolumeMountPoint 因为设备没有 Volume GUID 直到安装完毕。这是一个鸡和蛋的问题。

    2 回复  |  直到 14 年前
        1
  •  8
  •   Community CDub    8 年前

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

    FindFirstVolume 一组函数。可以去掉前导“\.\”和尾随“\”字符,然后将结果字符串传递给 QueryDosDevice . 这将提供设备名称。

    接下来,必须使用GUID\u deviceinterface\u VOLUME和 SetupDiGetClassDevs IOCTL_STORAGE_GET_DEVICE_NUMBER . 一旦这些匹配,您就可以从卷中获取设备名,并将其与其他设备名列表进行比较,以找到卷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;
                }
            }
        }
    }
    
        2
  •  0
  •   Community CDub    8 年前

    在我看来,你必须使用 IOCTL_MOUNTMGR_CREATE_POINT IOCTL_MOUNTMGR_XXX 是为内核模式驱动程序编写的,但不是必需的。可能是我的 old answer (使用哪种方法 IOCTL_MOUNTMGR_QUERY_POINTS another one 我可以帮你做这个。另请参见 http://msdn.microsoft.com/en-us/library/ff567603.aspx http://support.microsoft.com/kb/836662 .

    IOCTL\u MOUNTMGR\u创建\u点 SetVolumeMountPoint