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:

code format="bb4w" IF FNeject("D:") THEN PRINT "Eject succeeded" ELSE PRINT "Eject failed" ENDIF code 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:

code format="bb4w" 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% code