Как извлечь съемный USB-диск / том, похожий на функцию «Извлечь» в проводнике Windows? - PullRequest
13 голосов
/ 12 октября 2010

Знаете ли вы, что такое API или последовательность вызовов API, которые использует Windows для выполнения функции «Извлечь», которая доступна в контекстном меню оболочки для съемных томов?

Пока я пробовалдве вещи:

  1. с использованием CM_Request_Device_Eject , я перечисляю съемные диски (с помощью SetupDiXXX APIs ), нахожу тот, который мне интересен, пройдитесь по иерархии диспетчера устройств (используя CM_XXX APIs ) и, наконец, вызовите CM_Request_Device_Eject на devInst устройства, в котором я заинтересован. Это работает в том смысле, чтоон удаляет тома из «Моего компьютера» и делает устройство «безопасным для удаления» (готовым к удалению), но это не то же самое, что функция «Извлечь» из контекстного меню оболочки.Насколько я знаю, это потому, что устройство, которое я пытаюсь извлечь, должно что-то делать, когда оно выбрасывается, и что что-то не происходит, когда я выполняю извлечение с использованием CM_Request_Device_Eject.

  2. с использованием DeviceIoControl с IOCTL_STORAGE_EJECT_MEDIA контрольным кодом.Последовательность событий:

    • получить дескриптор тома, который меня интересует, используя CreateFile , как предлагается в документации
    • попытаться заблокировать томс помощью FSCTL_LOCK_VOLUME
    • попробуйте отключить его с помощью FSCTL_DISMOUNT_VOLUME
    • отключить предотвращение удаления носителя с помощью IOCTL_STORAGE_MEDIA_REMOVAL 1044 *1044*1046 * и, наконец, выполните функцию IOCTL_STORAGE_EJECT_MEDIA .

    Это не работает вообще.Каждый из вызовов DeviceIoControl завершается с ошибкой ERROR_IVALID_FUNCTION (0x00000001).Я не знаю, почему звонки терпят неудачу.Я проверил, что другие вызовы DeviceIoControl работают нормально для того же дескриптора файла (например, IOCTL_STORAGE_GET_DEVICE_NUMBER )

Наконец, мой компьютер под управлением Windows 7 x64,и чтобы заставить работать второй метод, я попытался запустить свое приложение с правами администратора, и это ничего не изменило.

EDIT

В конце концов я нашелгде я делал ошибку с подходом № 2.Оказывается, по какой-то причине я неправильно установил желаемый доступ при открытии ручки для громкости с помощью CreateFile.Правильный режим доступа - GENERIC_READ | GENERIC_WRITE, и я проходил 0. После исправления ошибки я смог успешно извлечь устройство, используя DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA, а также метод # 1, используя CM_Request_Device_Eject.

И оказывается, что метод № 2 действительно является методом, используемым функцией «Извлечь» из контекстного меню оболочки.Используя этот метод, устройство реагирует правильно.

Ответы [ 2 ]

2 голосов
/ 20 марта 2015

В конце концов, я узнал, где я ошибался с подходом № 2.

Оказывается, по какой-то причине я неправильно установил желаемый доступ при открытии дескриптора тома с помощью CreateFile.

Правильный режим доступа - GENERIC_READ | GENERIC_WRITE, и я проезжал 0.После исправления ошибки я смог успешно извлечь устройство, используя DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA, а также метод # 1, используя CM_Request_Device_Eject.

Наконец, оказывается, что метод № 2 действительно является методом, используемымФункция «Извлечь» из контекстного меню оболочки.Используя этот метод, устройство реагирует правильно.

0 голосов
/ 19 марта 2015

Я пришел сюда случайно, выполняя поиск по «CM_Request_Device_Eject», и увидел, что это было похоже на решение, которое я недавно сделал, собрав воедино похожие части решения. Простите за поздний ответ.

Я суммировал шаги, которые я сделал для этого в моем проекте в этом SO-ответе .

...