To avoid having to include copyrighted code I decided to describe in detail the method Uwe Sieber has discovered to Eject a drive.
Because the method of doing something is not protected by copyright, anyone following these steps and coming to a working solution will have their own copyright on the code thus produced.
-----------------------------------------------------------------------------
This document describes the method Uwe Sieber uses to perform a device eject
See also:
How to prepare an USB drive for save removal
By Uwe Sieber.
http://www.codeproject.com/useritems/RemoveDriveByLetter.asp
Note that in order to be able to implement this, you will need experience
in writing code that uses setupapi.h to perform device enumeration.
Device Trees for USB Flash Drives
The following device trees are representative of how USB Flash Drives are
normally setup in the system.
USB Mass Storage Device +- DaneElec zMate USB to CF USB Device +- Generic volume - (F:) USB Mass Storage Device +- OTi Flash Disk USB Device +- Generic volume - (U:)
The 'USB Device' entries can be enumerated with setupapi.h using
guid GUID_DEVINTERFACE_DISK.
Goal
Create a function that ejects a drive based on a drivenumber.
Here a drive number in the range 0..25 represents drive letter 'A'..'Z'.
Below are the steps you will need to perform to make the eject happen:
Getting the disk number for a give drive number
Some background information. The disk number is the physical disk number
of the device. This disk number uniquely identifies it.
1. Map the drive number to a volume name "\\.\?:" by replacing ? with
A+drivenumber to get the real drive letter again.
2. Use CreateFile to open the volume name, request minimal privileges,
attribute reading only.
3. Use DeviceIoControl with IOCTL_STORAGE_GET_DEVICE_NUMBER to retrieve
the STORAGE_DEVICE_NUMBER structure which contains a DeviceNumber member.
Hold on to this number, we will refer to it in the rest of the text
as TargetDeviceNumber.
Finding a device instance for a disk number
Purpose of this step is enumerating device interfaces until you hit upon
the one that has a DeviceNumber that matches TargetDeviceNumber. What Uwe
Sieber has discovered is that the device path that can be accessed when
enumerating GUID_DEVINTERFACE_DISK interfaces can be used to retrieve
the disk number.
4. Use setupapi.h to enumerate all present GUID_DEVINTERFACE_DISK interfaces.
4a. Hold on to the SP_DEVINFO_DATA, we will refer to it as CurrentDeviceInfo.
4b. Dig into every entry to get at the SP_DEVICE_INTERFACE_DETAIL_DATA.
4c. Use CreateFile to open DevicePath field of interface detail data, request
minimal privileges, attribute reading only.
4d. Use DeviceIoControl with IOCTL_STORAGE_GET_DEVICE_NUMBER to retrieve a
STORAGE_DEVICE_NUMBER structure which contains DeviceNumber member.
4e. If the DeviceNumber matches take the TargetDeviceNumber then take the
DevInst member of CurrentDeviceInfo. Hold on to it, we will refer to
it as TargetDevInst.
Performing the Eject
Now the device instance has been found we switch over to using cfgmgr32.h.
5. Find the parent of TargetDevInst using CM_Get_Parent
6. Retrieve the status of the parent using CM_Get_DevNode_Status
7. Compare the status with DN_REMOVABLE (bitmask compare) and hold on to
that result, we will refer to it as DeviceRemovable.
8. Use CM_Request_Device_EjectW when DeviceRemovable is true, otherwise
use CM_Query_And_Remove_SubTreeW. Provide a veto name to prevent popup
of message boxes. Also provide parameter veto type initialized with
the value PNP_VetoTypeUnknown.
9. If the return values is CR_SUCCESS the eject may have been successfull.
You will need to check the veto type. If it is PNP_VetoTypeUnknown
then the eject succeeded. The veto name will give insight in the reason
for the failure when veto type has a value other than PNP_VetoTypeUnknown.
You may try to perform this eject a couple of times, seems that Uwe has
found it doesn't always work on the first try.
What is not protected by copyright ?
Ideas, methods, or systems are not subject to copyright protection.
Copyright protection, therefore, is not available for ideas or procedures
for doing, making, or building things; scientific or technical methods or
discoveries; business operations or procedures; mathematical principles;
formulas, algorithms; or any other concept, process, or method of operation.
Section 102 of the copyright law, title 17, United States Code, clearly
expresses this principle: In no case does copyright protection for an
original work of authorship extend to any idea, procedure, process, system,
method of operation, concept, principle, or discovery, regardless of the
form in which it is described, explained, illustrated, or embodied in
such work.