/*
* Eject CDs
*/
# Include <windows. h>
# Include <winioctl. h>
# Include <stdio. h>
# Include <stdlib. h>
/* Options */
Static int unmount_only;
Static int eject_all;
/* Wrapper for GetDriveTypeW */
Static DWORD get_drive_type (WCHAR drive)
{
Static const WCHAR rootW [] = {'A', ':', '\', 0 };
WCHAR path [16];
Memcpy (path, rootW, sizeof (rootW ));
Path [0] = drive;
Return GetDriveTypeW (path );
}
Static BOOL eject_cd (WCHAR drive)
{
Static const WCHAR deviceW [] = {'\', '\', '.', '\', 'A', ':', 0 };
PREVENT_MEDIA_REMOVAL removal;
WCHAR buffer [16];
HANDLE handle;
DWORD result;
If (get_drive_type (drive )! = DRIVE_CDROM)
{
Printf ("Drive % c: is not a CD or is not mounted \ n", (char) drive );
Return FALSE;
}
Memcpy (buffer, deviceW, sizeof (deviceW ));
Buffer [4] = drive;
Handle = CreateFileW (buffer,
GENERIC_WRITE | GENERIC_READ,
File_pai_read | file_pai_write,
NULL, OPEN_EXISTING, 0, 0 );
If (handle = INVALID_HANDLE_VALUE)
{
Printf ("Cannot open device for drive % c: \ n", (char) drive );
Return FALSE;
}
Printf ("ejecting % c: \ n", (char) drive );
If (! DeviceIoControl (handle, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, & result, NULL ))
Printf ("FSCTL_LOCK_VOLUME failed with err % d \ n", GetLastError ());
If (! DeviceIoControl (handle, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, & result, NULL ))
Printf ("FSCTL_DISMOUNT_VOLUME failed with err % d \ n", GetLastError ());
Removal. PreventMediaRemoval = FALSE;
If (! DeviceIoControl (handle, IOCTL_STORAGE_MEDIA_REMOVAL, & removal, sizeof (removal), NULL, 0, & result, NULL ))
Printf ("IOCTL_STORAGE_MEDIA_REMOVAL failed with err % d \ n", GetLastError ());
If (! Unmount_only)
{
If (! DeviceIoControl (handle, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, & result, NULL ))
Printf ("IOCTL_STORAGE_EJECT_MEDIA failed with err % d \ n", GetLastError ());
}
If (! DeviceIoControl (handle, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, & result, NULL ))
Printf ("FSCTL_UNLOCK_VOLUME failed with err % d \ n", GetLastError ());
CloseHandle (handle );
Return TRUE;
}
/* Find the CD drive, and die if we find more than one */
Static WCHAR find_cd_drive (void)
{
WCHAR ret = 0, drive;
For (drive = 'C'; drive <= 'Z'; drive ++)
{
If (get_drive_type (drive )! = DRIVE_CDROM) continue;
If (ret)
{
Printf ("Multiple CD drives found (% c: and % c :), you need to specify the one you want. \ n ",
(Char) ret, (char) drive );
Exit (1 );
}
Ret = drive;
}
Return ret;
}
Static void usage (void)
{
Printf ("Usage: eject [-u] [-a] [-h] [x:]... \ n ");
Printf ("-a Eject all the CD drives we find \ n ");
Printf ("-h Display this help message \ n ");
Printf ("-u Unmount only, don't eject the CD \ n ");
Printf ("x: Eject drive x: \ n ");
Exit (1 );
}
Static void parse_options (int * argc, char * argv [])
{
Int I;
Char * opt;
For (I = 1; I <* argc; I ++)
{
If (argv [I] [0]! = '-')
{
/* Check for valid drive argument */
If (strlen (argv [I])! = 2 | argv [I] [1]! = ':') Usage ();
Continue;
}
For (opt = argv [I] + 1; * opt; opt ++) switch (* opt)
{
Case 'A': eject_all = 1; break;
Case 'U': unmount_only = 1; break;
Case 'H': usage (); break;
Default:
Printf ("Unknown option-% c \ n", * opt );
Usage ();
}
Memmove (argv + I, argv + I + 1, (* argc-I) * sizeof (* argv ));
(* Argc )--;
I --;
}
}
Int main (int argc, char * argv [])
{
Parse_options (& argc, argv );
If (eject_all)
{
WCHAR drive;
For (drive = 'C'; drive <= 'Z'; drive ++)
{
If (get_drive_type (drive )! = DRIVE_CDROM) continue;
If (! Eject_cd (drive) exit (1 );
}
}
Else if (argc> 1)
{
Int I;
For (I = 1; I <argc; I ++)
If (! Eject_cd (argv [I] [0]) exit (1 );
}
Else
{
WCHAR drive = find_cd_drive ();
If (! Drive)
{
Printf ("No CD drive found \ n ");
Exit (1 );
}
If (! Eject_cd (drive) exit (1 );
}
Exit (0 );
}
From tody_guo's column