Знаете ли вы, что такое API, или последовательность вызовов API, которые использует Windows для выполнения функции "Извлечь" , которая доступна в контекстном меню оболочки для съемных томов?
До сих пор я пробовал две вещи:
-
используя CM_Request_Device_Eject, я перечисляю съемные диски (используя API SetupDiXXX), найдите тот, который мне интересен, идите по иерархии диспетчера устройств (используя API CM_XXX) и, наконец, вызовите
CM_Request_Device_Eject
наdevInst
устройства, в которое я вовлечен. Это работает в том смысле, что он удаляет тома с "Мой компьютер" и делает устройство "безопасным для удаления" (готово к удалению), но оно не то же самое, что и контекстное меню оболочки "Извлечь" . То, как я это знаю, связано с тем, что устройство, которое я пытаюсь извлечь, должно делать что-то, когда оно выбрасывается, и что что-то не происходит, когда я делаю извлечения с помощьюCM_Request_Device_Eject
. -
используя 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 действительно является методом, используемым в контекстном меню оболочки "Извлечь" . Используя этот метод, устройство реагирует правильно.