User Tools

Site Tools


ejecting_20a_20removable_20disk

This is an old revision of the document!


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.1522502358.txt.gz · Last modified: 2018/03/31 13:19 by 127.0.0.1