Как программно смонтировать диск в Windows? - PullRequest
4 голосов
/ 24 сентября 2010

Мы производим и продаем устройства, которые наши пользователи иногда захотят подключить к своему компьютеру в больших количествах с несколькими USB-концентраторами. Это композитное устройство USB, которое имеет интерфейсы как человеческого интерфейса (HID), так и интерфейсов массовой памяти (MSD). Windows автоматически монтирует файловую систему каждого устройства, пока в ней не заканчиваются буквы на «Z:».

Я могу пройтись по дереву устройства и получить идентификаторы экземпляра устройства для интерфейсов HID и USBSTOR, используя комбинацию функций PnP Configuration Manager и Установка устройства . С помощью пути к запоминающему USB-устройству я также могу получить номер диска (т.е. \\.\PhysicalDrive1).

Следующим шагом будет монтирование этих дисков по мере необходимости, отключая буквы дисков, когда мы общаемся с устройствами, или, что еще лучше, монтируем их во временные каталоги на диске C :. У меня возникают трудности при попытке использовать DefineDosDevice для этой задачи, и я не могу добиться успеха с помощью SetVolumeMountPoint , поскольку устройство не имеет GUID тома , пока оно не смонтировано. Это представляет проблему курицы и яйца.

Если бы только наши клиенты использовали unix !!!

Ответы [ 2 ]

8 голосов
/ 25 сентября 2010

Windows не монтирует диски; это монтирует объемы. Однако том для устройства класса USBSTOR не указан как дочерний узел в дереве устройств. Следовательно, вам нужно перечислить все тома и выполнить несколько манипуляций и сравнений строк, чтобы сопоставить узлы STORAGE \ VOLUME с узлами USBSTOR.

Все значения GUID тома перечислены с набором функций FindFirstVolume . Начальные символы "\. \" И завершающие "\" могут быть удалены, а полученная строка затем передана в QueryDosDevice . Это обеспечивает имя устройства.

Далее необходимо перечислить все тома, используя GUID_DEVINTERFACE_VOLUME с SetupDiGetClassDevs и друзьями. Сравните тип устройства и номер каждого тома с устройством USBSTOR, которое вы ищете, используя IOCTL_STORAGE_GET_DEVICE_NUMBER . Как только они будут сопоставлены, вы можете получить имя устройства из тома и сравнить его с другим списком имен устройств, чтобы найти GUID тома.

Наконец, GUID тома может быть успешно использован с SetVolumeMountPoint .

Спасибо Гейбу за его очень полезную помощь в комментариях к моему вопросу.


Фрагменты кода

Получить тип и номер устройства из пути к устройству:

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;
            }
        }
    }
}
0 голосов
/ 27 сентября 2010

Мне кажется, что вы должны использовать IOCTL_MOUNTMGR_CREATE_POINT.К сожалению, большинство используемых примеров IOCTL_MOUNTMGR_XXX написаны для драйверов режима ядра, но это не обязательно.Возможно, мой старый ответ (который использует IOCTL_MOUNTMGR_QUERY_POINTS) и еще один может помочь вам сделать это.См. Также http://msdn.microsoft.com/en-us/library/ff567603.aspx и http://support.microsoft.com/kb/836662.

Возможно, что после лучшего понимания того, как следует использовать IOCTL_MOUNTMGR_CREATE_POINT, вы сможете решить эту проблему в отношении SetVolumeMountPoint .

...