Как извлечь съемный USB-диск / том, похожий на функцию "Извлечь" в Windows Explorer?

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

До сих пор я пробовал две вещи:

  1. используя CM_Request_Device_Eject, я перечисляю съемные диски (используя API SetupDiXXX), нахожу тот, который мне интересен, прохожу иерархию диспетчера устройств (используя API CM_XXX) и, наконец, вызываю 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
    • и, наконец, выполнить функцию IOCTL_STORAGE_EJECT_MEDIA.

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

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

РЕДАКТИРОВАТЬ

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

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

3 ответа

Решение

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

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

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

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

Попробуйте следовать инструкции " Как подготовить USB-накопитель для безопасного удаления", в которой показано, как использовать функцию CM_Request_Device_Eject.

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

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

Другие вопросы по тегам