User Tools

Site Tools


ejecting_20a_20removable_20disk

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%
This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
ejecting_20a_20removable_20disk.txt · Last modified: 2018/04/17 16:00 by tbest3112