Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
626 views
in Technique[技术] by (71.8m points)

winapi - How to eject a USB removable disk/volume, similar to the "Eject" function in Windows Explorer?

Do you know what is the API, or sequence of API calls that windows uses to accomplish the "Eject" function which is available on the shell context menu for removable volumes?

So far I've tried two things:

  1. using CM_Request_Device_Eject, I enumerate the removable disks (using the SetupDiXXX APIs), find the one that I'm interested in, walk the device manager hierarchy (using CM_XXX APIs) and finally call CM_Request_Device_Eject on the devInst of the device I'm interesed in. This works in the sense that it does remove the volumes from My Computer and makes the device "safe to remove" (ready to be removed) but it is not the same as the shell context menu "Eject" function. The way I know this is because the device that I'm trying to eject is supposed to do something when it is ejected and that something is not happening when I do the eject using CM_Request_Device_Eject.

  2. using DeviceIoControl with the IOCTL_STORAGE_EJECT_MEDIA control code. The sequence of events is:

    This doesn't work at all. Each one of the DeviceIoControl calls fails with ERROR_IVALID_FUNCTION (0x00000001). I don't know why the calls fail. I've verified that other calls to DeviceIoControl work fine for the same file handle (such as IOCTL_STORAGE_GET_DEVICE_NUMBER)

Finally, my development machine is running Windows 7 x64, and in order to get the second method to work I've tried running my application with Administrator privileges and that did not change anything.

EDIT

Eventually, I found out where I was making a mistake with approach #2. It turns out that for some reason I was not setting the desired access correctly when opening the handle to the volume using CreateFile. The correct access mode is GENERIC_READ | GENERIC_WRITE and I was passing 0. After correcting my error I was able to successfully eject the device using DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA, as well as with method #1, using CM_Request_Device_Eject.

And it turns out that method #2 is indeed the method used by the shell context menu's "Eject" function. Using this method the device reacts correctly.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Eventually, I found out where I was making a mistake with approach #2.

It turns out that for some reason I was not setting the desired access correctly when opening the handle to the volume using CreateFile.

The correct access mode is GENERIC_READ | GENERIC_WRITE and I was passing 0. After correcting my error I was able to successfully eject the device using DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA, as well as with method #1, using CM_Request_Device_Eject.

Finally, it turns out that method #2 is indeed the method used by the shell context menu's "Eject" function. Using this method the device reacts correctly.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...