I am working on code to programmatically eject a USB device on user request using the Win32 API (which I don't normally work with). From searching the web up and down, the code below is what I have come up with.
As you can see, my call to CreateFile() used to pass GENERIC_READ|GENERIC_WRITE for the dwIoControlCode parameter, but when I debugged, I got a handle with value INVALID_HANDLE_VALUE. In my call to FormatMessage(), the GetLastError() call returned a code that translated to "Access is denied". Looking around, I saw someone who said pass 0 instead of GENERIC_READ|GENERIC_WRITE. I tried that and I got a handle, no longer a bad handle value. With the non-bad handle value, I continued working with the subsequent code.
The next call was to DeviceIoControl() (GetHandleInformation() and DeviceIoControl came in later for debugging purposes), passing the supposedly non-bad handle along with FSCTL_LOCK_VOLUME for the dwIoControlCode parameter, and the call returned false, with GetLastError() returning a code translating to "Incorrect function". I inserted the calls to GetHandleInformation() and DeviceIoControl(..., IOCTL_STORAGE_CHECK_VERIFY, ...) just before this in order to check my handle. GetHandleInformation() returned true, so that sounded good. However, DeviceIoControl(..., IOCTL_STORAGE_CHECK_VERIFY, ...) returned false, with GetLastError() returning a code translating to "Access is denied". I haven't yet been able to get passed this point.
This code, or variations on it, is suggested by many on the internet, but it's not working for me. I'm hoping someone can point out where I'm going wrong here. I'm compiling on Win7 64-bit using the MSVC2010 compiler.
Thanks for any help.
#include <windows.h>
void ejectDrive(char driveletter)
{
DWORD dwRet = 0;
DWORD retSize;
LPTSTR pTemp=NULL;
bool ok = false;
char devicepath[7];
char format[] = "\\\\.\\?:";
wchar_t wtext[7];
strcpy_s(devicepath, format);
devicepath[4] = driveletter;
mbstowcs(wtext, devicepath,strlen(devicepath)+1);
HANDLE hVol = CreateFile(wtext, 0 /*GENERIC_READ | GENERIC_WRITE*/,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if (hVol == INVALID_HANDLE_VALUE)
{
retSize=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(LPTSTR)&pTemp,
0,
NULL );
return;
}
LPDWORD lpdwFlags;
ok = GetHandleInformation(hVol, lpdwFlags);
retSize=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(LPTSTR)&pTemp,
0,
NULL );
ok = DeviceIoControl(hVol, IOCTL_STORAGE_CHECK_VERIFY, NULL,0,NULL, 0, lpdwFlags, 0);
if(!ok)
{
retSize=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(LPTSTR)&pTemp,
0,
NULL );
return;
}
ok = DeviceIoControl(hVol, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &dwRet, 0);
if(!ok)
{
retSize=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(LPTSTR)&pTemp,
0,
NULL );
return;
}
if(!DeviceIoControl(hVol, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &dwRet, 0))
{
return;
}
DeviceIoControl(hVol, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, &dwRet, 0);
CloseHandle(hVol);
}