16

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.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151
  • Your approach #2 should work. On http://stackoverflow.com/questions/58670/windows-cdrom-eject, the answer from Andreas Magnusson worked for me, ejecting a USB stick. The only change was to correct his spelling of `DeviceIoControl`. – Nate Oct 12 '10 at 22:45
  • Also, `DeviceIoControl` returns `1` on success. When you report getting `ERROR_INVALID_FUNCTION`, is that the return value of `DeviceIoControl`, or is it returning `0` and you are calling `GetLastError`? – Nate Oct 12 '10 at 22:57
  • @Nate: DeviceIoControl does return 0 when I call it with either of the control codes that I mentioned. Then when I call GetLastError() it returns 1 which is ERROR_INVALID_FUNCTION. – Mike Dinescu Oct 12 '10 at 23:14
  • Try to follow [How to Prepare a USB Drive for Safe Removal](http://www.codeproject.com/kb/system/RemoveDriveByLetter.aspx) which shows how to use [CM_Request_Device_Eject](http://msdn.microsoft.com/en-us/library/ff539806(VS.85).aspx) function. – Oleg Oct 12 '10 at 23:04
  • Thanks @Oleg, but that approach is exactly what I described as solution #1 which works in that it ejects the USB but it doesn't do whatever else windows does when you click "Eject" in the Shell Context Menu. That's what I need.. – Mike Dinescu Oct 12 '10 at 23:12
  • @Miky Dinescu: why you need to know exactly what do windows in the Shell Context Menu? I supposed that you need to have a way which work and need no Administrator privileges. The article from the codeproject is old enough, you can download full code example which works. Why do you need to know what shell context menu do? – Oleg Oct 12 '10 at 23:28
  • Because ejecting the device from the windows shell triggers an action on this device - for brevity let's just say an LED turns on. When I eject the device from my application using the CM_Request_Device_Eject method, the device is ejected, but the LED does not turn on. And yes, I've checked, it's the same as the code project implementation. And I'm pretty familiar with what's already available on the forums out there - including CodeProject - as I've been searching the internet for two days trying to figure this one out. Do you have any other suggestions? – Mike Dinescu Oct 12 '10 at 23:46
  • @Miky Dinescu: OK, the information about LED seems interesting for me. Is the way 2 (the way described in the http://support.microsoft.com/kb/165721) turn the LED on? By the way the turning on of the LED can be a disadvantage (a bug or an additional verification). It can be just because windows ask some information about the disk before it ejecting. So the LED goes for a short time on. Nevertheless in my knowledge the way 2 is an old way before introducing of Plug&Play API from the Cfgmgr32.dll and the best way for ejecting is `CM_Request_Device_Eject` and I would you recommend the way 1. – Oleg Oct 13 '10 at 00:03

2 Answers2

2

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.

Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151
0

I came here accidentally while doing a search on "CM_Request_Device_Eject", and saw that it was similar to a solution I'd recently done by pulling together similar pieces of a solution. Forgive the late answer.

I've summarized the steps I've done for this on my project in this SO answer.

Community
  • 1
  • 1
John Castleman
  • 1,552
  • 11
  • 12
  • I've actually answered my own question a few years ago (see the edit in the question). Thanks for chiming in though. – Mike Dinescu Mar 20 '15 at 02:54