title: How to eject a USB removable disk/volume, similar to the "Eject" function in Windows Explorer?
body: <p>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?</p>
  
  <p>So far I've tried two things: </p>
  
  <ol>
  <li><p>using <a href="http://msdn.microsoft.com/en-us/library/ff539806(v=VS.85).aspx" rel="noreferrer">CM_Request_Device_Eject</a>, I enumerate the removable disks (using the <a href="http://msdn.microsoft.com/en-us/library/ff549791%28v=VS.85%29.aspx" rel="noreferrer">SetupDiXXX APIs</a>), find the one that I'm interested in, walk the device manager hierarchy (using <a href="http://msdn.microsoft.com/en-us/library/ff549794%28v=VS.85%29.aspx" rel="noreferrer">CM_XXX APIs</a>) and finally call <code>CM_Request_Device_Eject</code> on the <code>devInst</code> of the device I'm interesed in. This <em>works</em> 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 <em>something</em> is not happening when I do the eject using <code>CM_Request_Device_Eject</code>.</p></li>
  <li><p>using <a href="http://msdn.microsoft.com/en-us/library/aa363216(VS.85).aspx" rel="noreferrer">DeviceIoControl</a> with the <a href="http://msdn.microsoft.com/en-us/library/aa363406(VS.85).aspx" rel="noreferrer">IOCTL_STORAGE_EJECT_MEDIA</a> control code. The sequence of events is:</p>
  
  <ul>
  <li>obtain a handle to the volume I'm interested in using <a href="http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx" rel="noreferrer">CreateFile</a> as suggested in the documentation</li>
  <li>try to lock the volume with <a href="http://msdn.microsoft.com/en-us/library/aa364575(v=VS.85).aspx" rel="noreferrer">FSCTL_LOCK_VOLUME</a></li>
  <li>try to dismount it using <a href="http://msdn.microsoft.com/en-us/library/aa364562(v=VS.85).aspx" rel="noreferrer">FSCTL_DISMOUNT_VOLUME</a></li>
  <li>disable the prevent storage media removal using <a href="http://msdn.microsoft.com/en-us/library/aa363416(VS.85).aspx" rel="noreferrer">IOCTL_STORAGE_MEDIA_REMOVAL</a> </li>
  <li>and finally execute the <a href="http://msdn.microsoft.com/en-us/library/aa363406(VS.85).aspx" rel="noreferrer">IOCTL_STORAGE_EJECT_MEDIA</a> function.</li>
  </ul>
  
  <p>This doesn't work at all. Each one of the <code>DeviceIoControl</code> calls fails with <code>ERROR_IVALID_FUNCTION</code> (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 <a href="http://msdn.microsoft.com/en-us/library/bb968800%28VS.85%29.aspx" rel="noreferrer">IOCTL_STORAGE_GET_DEVICE_NUMBER</a>)</p></li>
  </ol>
  
  <p>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.</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>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 <code>CreateFile</code>. The correct access mode is <code>GENERIC_READ | GENERIC_WRITE</code> and I was passing 0. After correcting my error I was able to successfully eject the device using <code>DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA</code>, as well as with method #1, using <code>CM_Request_Device_Eject</code>.</p>
  
  <p>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.</p>