Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Trying to eject disks

llynisa
Beginner
2,317 Views
I have tried to write a routine to eject floppies, Zip disks and CD-ROMs from drives, but it does not work. Can anybody please point me to an example of how to do it, or tell me where I am going wrong in the code below.

Alan

function EjectDisk(DriveLetter)
! Obtains authority and ejects disks from removable drives.  Initial version is
! for single drive.  Does not work - fails with System Error  5 Access is Denied.
use dfwinty,  only : DRIVE_CDROM, DRIVE_REMOVABLE, FILE_ATTRIBUTE_NORMAL,      &
                     INVALID_HANDLE_VALUE, IOCTL_STORAGE_EJECT_MEDIA,          &
                     IOCTL_STORAGE_MEDIA_REMOVAL, NULL, OPEN_EXISTING,  &
                     T_PREVENT_MEDIA_REMOVAL
use kernel32, only : CloseHandle, CreateFile, DeviceIoControl, GetDriveType,   &
                     GetLastError
implicit none
character*1, intent(in) :: DriveLetter
logical*4               :: EjectDisk
integer*4               :: hDrive, i4, DriveType, j4, sizePMR
type (T_PREVENT_MEDIA_REMOVAL) pmr
!
! Get Drive Type
DriveType = GetDriveType(DriveLetter//':')
if (DriveType == DRIVE_REMOVABLE .OR. DriveType == DRIVE_CDROM) then
  ! If removable, get drive handle
  hDrive = CreateFile(DriveLetter, 0, 0, NULL, OPEN_EXISTING,                  &
                      FILE_ATTRIBUTE_NORMAL, NULL)
  if (hDrive /= INVALID_HANDLE_VALUE) then
    ! Allow media removal
    pmr.PreventMediaRemoval = "F"
    sizePMR = sizeof(pmr)
    ! Allow ejection - not that it works.
    if (.NOT. DeviceIoControl(hDrive, IOCTL_STORAGE_MEDIA_REMOVAL, loc(pmr),   &
                      sizePMR, NULL, 0, loc(j4), NULL)) then
      ! Display error Message: System Error 5  Access is denied.
      i4 = DisplayErrorMessage('StorageMediaRemoval'C)
      EjectDisk = .FALSE.
    end if
    ! Eject - not that it works.
    if (.NOT. DeviceIoControl(hDrive, IOCTL_STORAGE_EJECT_MEDIA, NULL,         &
                      0, NULL, 0, loc(j4), NULL)) then
      ! Display error Message: System Error 5  Access is denied.
      i4 = DisplayErrorMessage('StorageEjectMedia'C)
      EjectDisk = .FALSE.
    else
      EjectDisk = .TRUE.
    end if
  end if
  call CloseHandle(hDrive)
else
  EjectDisk = .FALSE.
end if
end function EjectDisk
0 Kudos
5 Replies
Jugoslav_Dujic
Valued Contributor II
2,317 Views
I can spot two errors in the code. In line 1, string is not null-terminated; it should be:

DriveType = GetDriveType(DriveLetter//':'//CHAR(0))

or

DriveType = GetDriveType(DriveLetter//':'C)

Second, where did you find that "F" means .FALSE. in this context? Lemme see... BOOLEAN is a typedef for unsigned char in C; that's supposed to be a LOGICAL(1) in Fortran, however, I see it is translated as CHARACTER(UCHAR) in DFWINTY.f90 instead... it is not quite an appropriate translation. In any case, that means that CHAR(0) corresponds to FALSE and CHAR(255) (or anything else) to TRUE.

Jugoslav
0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,317 Views
Btw, did you read Q165721? It discusses some important caveats.

Jugoslav
0 Kudos
llynisa
Beginner
2,317 Views
Jugoslav,

Thanks for your help.
GetDriveType worked OK without the missing CHAR(0), but I have now put it in. Changing pmr.PreventMediaRemoval = ?F? to CHAR(0), CHAR(1) ?T?, ?F? or any other character(s) made no difference at all to the end result. I had hoped that the ghastly transformation of CHARACTER(UCHAR) to BOOLEAN involved it being intelligent enough to take ?F? as .FALSE. Silly me! But it does not seem to have any effect on calling DeviceIOControl. I must be misinterpreting the requirements for the arguments.

Thanks for the tip on Q165721 ? I will take some time to digest it and will see if it gives me the tools to hack it.


Alan
0 Kudos
james1
Beginner
2,317 Views
Aside from the general considerations in that article, your immediate problem is due to your CreateFile call, you need at least GENERIC_READ access (second parameter) when opening the drive.

James
0 Kudos
llynisa
Beginner
2,317 Views
James, Jugoslav,

Many thanks for your help - the article with its advice and sample C++ code did the trick, and the routine now ejects both Zip disks & CD-ROMs, and with floppies correctly tells me that it is an incorrect function. I now need to polish it up with appropriate messages & logic for when there is no disk to eject, etc and that will be another routine safely in the bank.

Alan
0 Kudos
Reply