Windows がリムーバブル ボリュームのシェル コンテキスト メニューで使用できる「取り出し」機能を実行するために使用する API、または一連の API 呼び出しを知っていますか?
これまでのところ、次の 2 つのことを試しました。
CM_Request_Device_Ejectを使用して、( SetupDiXXX APIを使用して) リムーバブル ディスクを列挙し、関心のあるディスクを見つけ、( CM_XXX APIを使用して) デバイス マネージャー階層をたどり、最後に、関心のあるデバイスの を呼び出し
CM_Request_Device_Eject
ますdevInst
。これは、マイ コンピュータからボリュームを削除し、デバイスを「安全に削除できる」(削除できる状態にする) という意味で機能しますが、シェル コンテキスト メニューの「取り出し」機能とは異なります。これを知る方法は、イジェクトしようとしているデバイスが、イジェクト時に何かを実行するはずであり、 を使用してイジェクトを実行しても何も起こらないためCM_Request_Device_Eject
です。IOCTL_STORAGE_EJECT_MEDIA制御コードでDeviceIoControlを使用します。イベントのシーケンスは次のとおりです。
- ドキュメントで提案されているように、CreateFileを使用して関心のあるボリュームへのハンドルを取得する
- FSCTL_LOCK_VOLUMEでボリュームをロックしてみてください
- FSCTL_DISMOUNT_VOLUMEを使用してマウント解除してみてください
- IOCTL_STORAGE_MEDIA_REMOVALを使用してストレージ メディアの取り外しを防止する機能を無効にします。
- 最後にIOCTL_STORAGE_EJECT_MEDIA関数を実行します。
これはまったく機能しません。各呼び出しは(0x00000001)
DeviceIoControl
で失敗します。ERROR_IVALID_FUNCTION
通話が失敗する理由がわかりません。DeviceIoControl への他の呼び出しが同じファイル ハンドル ( IOCTL_STORAGE_GET_DEVICE_NUMBERなど)に対して正常に機能することを確認しました。
最後に、私の開発マシンは Windows 7 x64 を実行しており、2 番目の方法を機能させるために、管理者権限でアプリケーションを実行しようとしましたが、何も変わりませんでした。
編集
最終的に、アプローチ 2 のどこで間違いを犯していたのかがわかりました。を使用してボリュームへのハンドルを開くときに、何らかの理由で目的のアクセスを正しく設定していなかったことが判明しましたCreateFile
。正しいアクセス モードはGENERIC_READ | GENERIC_WRITE
で、0 を渡していました。エラーを修正した後、 を使用してデバイスを正常に取り出すことができました。DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA
また、方法 #1 を使用してCM_Request_Device_Eject
.
そして、メソッド #2 は、実際にシェル コンテキスト メニューの "Eject" 機能で使用されるメソッドであることがわかります。この方法を使用すると、デバイスは正しく反応します。