/**
http://support.microsoft.com/kb/q165721/
*/
#include
#include
#include
#include
// Prototypes
BOOL EjectVolume(TCHAR cDriveLetter);
HANDLE OpenVolume(TCHAR cDriveLetter);
BOOL LockVolume(HANDLE hVolume);
BOOL DismountVolume(HANDLE hVolume);
BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent);
BOOL AutoEjectVolume(HANDLE hVolume);
BOOL CloseVolume(HANDLE hVolume);
BOOL EJECT = TRUE;
//default is to eject device;
but a command switch can tell program to close cdrom
LPTSTR szVolumeFormat = TEXT("\\\\.\\%c:");
LPTSTR szRootFormat = TEXT("%c:\\");
LPTSTR szErrorFormat = TEXT("Error %d: %s\n");
void ReportError(LPTSTR szMsg)
{
_tprintf(szErrorFormat, GetLastError(), szMsg);
}
HANDLE OpenVolume(TCHAR cDriveLetter)
{
HANDLE hVolume;
UINT uDriveType;
TCHAR szVolumeName[8];
TCHAR szRootName[5];
DWORD dwAccessFlags;
wsprintf(szRootName, szRootFormat, cDriveLetter);
uDriveType = GetDriveType(szRootName);
switch(uDriveType)
{
case DRIVE_REMOVABLE:
dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
break;
case DRIVE_CDROM:
dwAccessFlags = GENERIC_READ;
break;
default:
_tprintf(TEXT("Cannot eject. Drive type is incorrect.\n"));
return INVALID_HANDLE_VALUE;
}
wsprintf(szVolumeName, szVolumeFormat, cDriveLetter);
hVolume = CreateFile( szVolumeName,
dwAccessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if (hVolume == INVALID_HANDLE_VALUE)
ReportError(TEXT("CreateFile"));
return hVolume;
}
BOOL CloseVolume(HANDLE hVolume)
{
return CloseHandle(hVolume);
}
#define LOCK_TIMEOUT 10000 // 10 Seconds (1 s == 1000 ms)
#define LOCK_RETRIES 20
BOOL LockVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
DWORD dwSleepAmount;
int nTryCount;
dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;
// Do this in a loop until a timeout period has expired
for (nTryCount = 0;
nTryCount <
LOCK_RETRIES;
nTryCount++)
{
if (DeviceIoControl(hVolume,
FSCTL_LOCK_VOLUME,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL))
return TRUE;
Sleep(dwSleepAmount);
}
return FALSE;
}
BOOL DismountVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
return DeviceIoControl( hVolume,
FSCTL_DISMOUNT_VOLUME,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL);
}
BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
{
DWORD dwBytesReturned;
PREVENT_MEDIA_REMOVAL PMRBuffer;
PMRBuffer.PreventMediaRemoval = fPreventRemoval;
return DeviceIoControl( hVolume,
IOCTL_STORAGE_MEDIA_REMOVAL,
&PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
NULL, 0,
&dwBytesReturned,
NULL);
}
AutoEjectVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
if(EJECT)
return DeviceIoControl( hVolume,
// IOCTL_STORAGE_LOAD_MEDIA ,
IOCTL_STORAGE_EJECT_MEDIA ,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL);
return DeviceIoControl( hVolume,
IOCTL_STORAGE_LOAD_MEDIA ,
// IOCTL_STORAGE_EJECT_MEDIA ,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL);
}
BOOL EjectVolume(TCHAR cDriveLetter)
{
HANDLE hVolume;
BOOL fRemoveSafely = FALSE;
BOOL fAutoEject = FALSE;
// Open the volume.
hVolume = OpenVolume(cDriveLetter);
if (hVolume == INVALID_HANDLE_VALUE)
return FALSE;
// Lock and dismount the volume.
if (LockVolume(hVolume) && DismountVolume(hVolume))
{
fRemoveSafely = TRUE;
// Set prevent removal to false and eject the volume.
if (PreventRemovalOfVolume(hVolume, FALSE) &&
AutoEjectVolume(hVolume))
fAutoEject = TRUE;
}
// Close the volume so other processes can use the drive.
if (!CloseVolume(hVolume))
return FALSE;
if (fAutoEject)
if(EJECT)
printf("Media in Drive %c has been ejected safely.\n",
cDriveLetter);
else
{
if (fRemoveSafely)
{
if(EJECT)
printf("Media in Drive %c can be safely removed.\n",
cDriveLetter);
}
}
return TRUE;
}
void Usage()
{
printf("Usage: Eject [/C] \n");
printf("When /c is supplied, the program will close CD-ROM bay\n\n");
return ;
}
void main(int argc, char * argv[])
{
if (argc <
2)
{
Usage();
return ;
}
if(argc == 3)
{
if(strlen(argv[2])>
1 && argv[2][1] == 'c' || argv[2][1]== 'C')
{
EJECT = FALSE;
}
}
if (!EjectVolume(argv[1][0]))
{
printf("Failure ejecting drive %c.\n\n", argv[1][0]);
Usage();
}
return ;
}
No comments:
Post a Comment