=====Ejecting a removable disk=====
//by Richard Russell, November 2007//\\ \\ The routine listed below will eject a disk (if any) in the specified drive; it requires **Windows NT4**, **Windows 2000**, **Windows XP** or **Windows Vista**. It should be called using code similar to the following:\\ \\
IF FNeject("D:") THEN
PRINT "Eject succeeded"
ELSE
PRINT "Eject failed"
ENDIF
The specified drive name must include the colon (**:**). Note that it is possible for the routine to return FALSE even though the disk was actually ejected. If the drive is currently in use by another application the routine will fail.\\ \\ Here is the code:\\ \\
DEF FNeject(drive$)
LOCAL hVolume%, ejectSucceeded%, result%
_LOCK_TIMEOUT = 10000 : REM 10 Seconds
_LOCK_RETRIES = 20
_GENERIC_READ = &80000000
_GENERIC_WRITE = &40000000
_OPEN_EXISTING = 3
_FILE_SHARE_READ = 1
_FILE_SHARE_WRITE = 2
_INVALID_HANDLE_VALUE = -1
_FSCTL_LOCK_VOLUME = &90018
_FSCTL_DISMOUNT_VOLUME = &90020
_IOCTL_STORAGE_MEDIA_REMOVAL = &2D4804
_IOCTL_STORAGE_EJECT_MEDIA = &2D4808
_IOCTL_STORAGE_LOAD_MEDIA = &2D480C
_DRIVE_REMOVABLE = 2
_DRIVE_CDROM = 5
REM Open the volume:
hVolume% = FNopenvolume(drive$)
IF hVolume% = _INVALID_HANDLE_VALUE THEN = FALSE
REM Lock and dismount the volume:
IF FNlockvolume(hVolume%) IF FNdismountvolume(hVolume%) THEN
REM Set prevent removal to false and eject the media:
IF FNpreventremovalofvolume(hVolume%, FALSE) IF FNejectmedia(hVolume%) THEN
ejectSucceeded% = TRUE
ENDIF
ENDIF
REM Close the volume so other processes can use the drive:
SYS "CloseHandle", hVolume% TO result%
IF result% = 0 ejectSucceeded% = FALSE
= ejectSucceeded%
DEF FNopenvolume(drive$)
LOCAL hVolume%, dwAccessFlags%, uDriveType%
SYS "GetDriveType", drive$+"\" TO uDriveType%
CASE uDriveType% OF
WHEN _DRIVE_REMOVABLE: dwAccessFlags% = _GENERIC_READ OR _GENERIC_WRITE
WHEN _DRIVE_CDROM: dwAccessFlags% = _GENERIC_READ
OTHERWISE: ERROR 100, "Cannot eject: drive is not removable"
ENDCASE
SYS "CreateFile", "\\.\"+drive$, dwAccessFlags%, \
\ _FILE_SHARE_READ OR _FILE_SHARE_WRITE, 0, _OPEN_EXISTING, 0 TO hVolume%
= hVolume%
DEF FNlockvolume(hVolume%)
LOCAL dwBytesReturned%, dwSleepAmount%, nTryCount%, result%
dwSleepAmount% = _LOCK_TIMEOUT / _LOCK_RETRIES
FOR nTryCount% = 1 TO _LOCK_RETRIES
SYS "DeviceIoControl", hVolume%, _FSCTL_LOCK_VOLUME, 0, 0, 0, 0, \
\ ^dwBytesReturned%, 0 TO result%
IF result% THEN = TRUE
SYS "Sleep", dwSleepAmount%
NEXT
= FALSE
DEF FNdismountvolume(hVolume%)
LOCAL dwBytesReturned%, result%
SYS "DeviceIoControl", hVolume%, _FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, \
\ ^dwBytesReturned%, 0 TO result%
= result%
DEF FNpreventremovalofvolume(hVolume%, fPreventRemoval%)
LOCAL dwBytesReturned%, result%
SYS "DeviceIoControl", hVolume%, _IOCTL_STORAGE_MEDIA_REMOVAL, \
\ ^fPreventRemoval%, 4, 0, 0, \
\ ^dwBytesReturned%, 0 TO result%
= result%
DEF FNejectmedia(hVolume%)
LOCAL dwBytesReturned%, result%
SYS "DeviceIoControl", hVolume%, _IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, \
\ ^dwBytesReturned%, 0 TO result%
= result%