Sign in to follow this  
Followers 0
arcker

AutoEjectIt v 1.0

16 posts in this topic

#1 ·  Posted (edited)

This script lets you to dismount an usb key of a CD-Rom safely

For example, it's useful if you don't want you users to use an usb key

i've just translated it from http://support.microsoft.com/kb/165721

Note that preventremoval doesn't work, so if you have opened files, they will be lost if you launch this script.

For now, it's impossible to "remount" an usb key that has been removed. You have to disconnect and reconnect it.

If you manage to remount the key without eject and reconnect physically your usb key, please let me now

; #FUNCTION# ====================================================================================================================
; Description ...: Eject an USB Key or a CD-ROM safely
; Parameters ....: $$cDriveLetter - Drive to eject (ex : E: )

; Return values .: Success      - True
;                  Failure      - False
; Author ........: Yoan Roblet (Arcker)
; Remarks .......:
; Requirements...: AutoIt3Lib
; Related .......: http://support.microsoft.com/kb/165721
; ===============================================================================================================================

#include <A3LWinApi.au3>
;Prototypes
;BOOL EjectVolume(TCHAR cDriveLetter);
;HANDLE OpenVolume(TCHAR cDriveLetter);
;BOOL LockVolume(HANDLE hVolume);
;BOOL DismountVolume(HANDLE hVolume);
;BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent);
;BOOL AutoEjectVolume(HANDLE hVolume);
;BOOL CloseVolume(HANDLE hVolume);

;StringFormat Output
$szVolumeFormat = "\\\\.\\%s"
$szRootFormat = "%s\\"
$szErrorFormat = "Error %d: %s\n"
;------------------------------------------
;Arbitrary variables
Global Const $INVALID_HANDLE_VALUE = 0
;------------------------------------------
;DeviceIoControl Contants
Global Const $FSCTL_LOCK_VOLUME = int(0x090018)
Global Const $FSCTL_DISMOUNT_VOLUME = int(0x00090020)
Global Const $IOCTL_STORAGE_EJECT_MEDIA  = int(0x002D4808)
Global Const $IOCTL_STORAGE_MEDIA_REMOVAL = int(0x002D4804)

;------------------------------------------
;Retry Constants
Global Const $LOCK_TIMEOUT = 10000       ; 10 Seconds
Global Const $LOCK_RETRIES = 20
$OpenVolume = InputBox("Ejecting...", "Enter the drive to eject", "G:")
ConsoleWrite("Trying to Eject the drive " & EjectVolume($OpenVolume) & @crlf)

Func ReportError($szMsg)
    ConsoleWrite(StringFormat($szErrorFormat, _API_GetLastErrorMessage (), $szMsg) & @CRLF)
    Exit
EndFunc   ;==>ReportError
Func OpenVolume($cDriveLetter)
    ;HANDLE hVolume
    ;UINT uDriveType
    ;TCHAR szVolumeName[8]
    ;TCHAR szRootName[5]
    ;DWORD dwAccessFlags
    $szRootName = StringFormat($szRootFormat, $cDriveLetter)
    $uDriveType = DriveGetType($szRootName);
    ConsoleWrite($szRootName & @tab & $uDriveType & @crlf)
    Switch $uDriveType
        Case "Removable"
            $dwAccessFlags = 6
        Case "CDROM"
            $dwAccessFlags = 2
        Case Else
            ConsoleWrite("Cannot eject.  Drive type is incorrect." & @CRLF)
            Return $INVALID_HANDLE_VALUE
    EndSwitch
    $szVolumeName = StringFormat($szVolumeFormat, $cDriveLetter)
    ;$szVolumeName = $szVolumeFormat & $cDriveLetter
    ConsoleWrite($szVolumeName & @crlf )
    $hVolume = _API_CreateFile ($szVolumeName, 2,$dwAccessFlags, 6)
    
    #cs
        hVolume = CreateFile(   szVolumeName,
        dwAccessFlags,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL );
    #ce
    If ($hVolume == $INVALID_HANDLE_VALUE) Then ReportError("CreateFile");
    Return $hVolume;
EndFunc   ;==>OpenVolume
Func CloseVolume($hVolume)
    Return _API_CloseHandle ($hVolume);
EndFunc   ;==>CloseVolume
Func LockVolume($hVolume)
    Local $dwBytesReturned
    Local $dwSleepAmount
    Local $nTryCount
    local $iRead
    $dwSleepAmount = $LOCK_TIMEOUT / $LOCK_RETRIES;
    ; Do this in a loop until a timeout period has expired
    For $nTryCount = 0 To $nTryCount < $LOCK_RETRIES
        If _Device_Control($hVolume, $FSCTL_LOCK_VOLUME, $iRead) Then
            Return True
        Else
            Sleep($dwSleepAmount);
        EndIf
    Next
    Return False;
EndFunc   ;==>LockVolume
Func DismountVolume($hVolume)
    ConsoleWrite("Dismount " & $hVolume & @crlf)
    Local $dwBytesReturned, $iRead
    local $aResult = _Device_Control($hVolume, $FSCTL_DISMOUNT_VOLUME, $iRead)
    msgbox(0,"",$aResult)
    Return $aResult
    ;Return $dwBytesReturned
EndFunc   ;==>DismountVolume
Func PreventRemovalOfVolume($hVolume, $fPreventRemoval)
    Local $dwBytesReturned
    Local $aResult
    Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
    
    $PMRBUFFER = DllStructCreate("bool PreventMediaRemoval")
    
    DllStructSetData($PMRBUFFER,"PreventMediaRemoval",$fPreventRemoval)
    
    $lpBytesReturned    = DllStructCreate("int Read")
    $pRead   = DllStructGetPtr($lpBytesReturned, "Read")
    $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hVolume,"uint",$IOCTL_STORAGE_MEDIA_REMOVAL,"ptr",DllStructGetPtr($PMRBUFFER),"uint",DllStructGetSize($PMRBUFFER), _ 
    "ptr",$lpOutBuffer,"uint",$nOutBufferSize,"ptr",$pRead,"ptr",$lpOverlapped)
    if $aResult = 0 then msgbox(0,"",_API_GetLastErrorMessage())
    Return $aResult <> 0
    
     ;& PMRBuffer, sizeof (PREVENT_MEDIA_REMOVAL),
    ;NULL, 0,
    ; & dwBytesReturned,
    ;NULL);
EndFunc   ;==>PreventRemovalOfVolume
Func AutoEjectVolume($hVolume)
    Local $aResult, $iRead;
    $aResult = _Device_Control($hVolume, $IOCTL_STORAGE_EJECT_MEDIA, $iRead)
    Return $aResult
EndFunc   ;==>AutoEjectVolume
Func EjectVolume($cDriveLetter)
    Local $hVolume;
    Local $fRemoveSafely = False;
    Local $fAutoEject = False;
    ; Open the volume.
    $hVolume = OpenVolume($cDriveLetter);
    If $hVolume == $INVALID_HANDLE_VALUE Then Return False
    ; Lock and dismount the volume.
    If LockVolume($hVolume) And DismountVolume($hVolume) Then
        $fRemoveSafely = True;
        ConsoleWrite("Volume Locked and Dismounted, trying to eject " & @crlf)
        ; Set prevent removal to false and eject the volume.
        If PreventRemovalOfVolume($hVolume, False) And AutoEjectVolume($hVolume) Then
            $fAutoEject = True;
        EndIf
    Else
        ConsoleWrite("Volume can't be locked or dismounted, please close possible opened files" & @crlf)
    EndIf
    
    ; Close the volume so other processes can use the drive.
    If CloseVolume($hVolume) = False Then
        Return False;
    EndIf
    
    If $fAutoEject Then
        ConsoleWrite(StringFormat("Media in Drive %s has been ejected safely.\n", $cDriveLetter))
    Else
        If $fRemoveSafely Then
            ConsoleWrite(StringFormat("Media in Drive %s can be safely removed.\n", $cDriveLetter))
        EndIf
    EndIf
    
    Return True;
EndFunc   ;==>EjectVolume
Func _Device_Control($hDevice, $dwIoControlCode, ByRef $iRead)
    Local $aResult
    Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
    $tRead   = DllStructCreate("int Data")
    
    $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hDevice,"uint",$dwIoControlCode,"ptr",$lpInBuffer,"uint",0, _ 
    "ptr",$lpOutBuffer,"uint",0,"ptr",DllStructGetPtr($tRead),"ptr",$lpOverlapped)
    
    $iRead   = DllStructGetData($tRead, "Data")
    
    ConsoleWrite("Device Control " & $iRead & @CRLF)
    Return $aResult<>0
EndFunc   ;==>_Device_Control
Edited by arcker

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites



Updated api include and _API_ funcs.

#include <WinApi.au3>
;Prototypes
;BOOL EjectVolume(TCHAR cDriveLetter);
;HANDLE OpenVolume(TCHAR cDriveLetter);
;BOOL LockVolume(HANDLE hVolume);
;BOOL DismountVolume(HANDLE hVolume);
;BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent);
;BOOL AutoEjectVolume(HANDLE hVolume);
;BOOL CloseVolume(HANDLE hVolume);

;StringFormat Output
$szVolumeFormat = "\\\\.\\%s"
$szRootFormat = "%s\\"
$szErrorFormat = "Error %d: %s\n"
;------------------------------------------
;Arbitrary variables
Global Const $INVALID_HANDLE_VALUE = 0
;------------------------------------------
;DeviceIoControl Contants
Global Const $FSCTL_LOCK_VOLUME = int(0x090018)
Global Const $FSCTL_DISMOUNT_VOLUME = int(0x00090020)
Global Const $IOCTL_STORAGE_EJECT_MEDIA  = int(0x002D4808)
Global Const $IOCTL_STORAGE_MEDIA_REMOVAL = int(0x002D4804)

;------------------------------------------
;Retry Constants
Global Const $LOCK_TIMEOUT = 10000       ; 10 Seconds
Global Const $LOCK_RETRIES = 20
$OpenVolume = InputBox("Ejecting...", "Enter the drive to eject", "G:")
ConsoleWrite("Trying to Eject the drive " & EjectVolume($OpenVolume) & @crlf)

Func ReportError($szMsg)
    ConsoleWrite(StringFormat($szErrorFormat, _WinAPI_GetLastErrorMessage (), $szMsg) & @CRLF)
    Exit
EndFunc   ;==>ReportError
Func OpenVolume($cDriveLetter)
    ;HANDLE hVolume
    ;UINT uDriveType
    ;TCHAR szVolumeName[8]
    ;TCHAR szRootName[5]
    ;DWORD dwAccessFlags
    $szRootName = StringFormat($szRootFormat, $cDriveLetter)
    $uDriveType = DriveGetType($szRootName);
    ConsoleWrite($szRootName & @tab & $uDriveType & @crlf)
    Switch $uDriveType
        Case "Removable"
            $dwAccessFlags = 6
        Case "CDROM"
            $dwAccessFlags = 2
        Case Else
            ConsoleWrite("Cannot eject.  Drive type is incorrect." & @CRLF)
            Return $INVALID_HANDLE_VALUE
    EndSwitch
    $szVolumeName = StringFormat($szVolumeFormat, $cDriveLetter)
    ;$szVolumeName = $szVolumeFormat & $cDriveLetter
    ConsoleWrite($szVolumeName & @crlf )
    $hVolume = _WinAPI_CreateFile ($szVolumeName, 2,$dwAccessFlags, 6)
    
    #cs
        hVolume = CreateFile(   szVolumeName,
        dwAccessFlags,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL );
    #ce
    If ($hVolume == $INVALID_HANDLE_VALUE) Then ReportError("CreateFile");
    Return $hVolume;
EndFunc   ;==>OpenVolume
Func CloseVolume($hVolume)
    Return _WinAPI_CloseHandle ($hVolume);
EndFunc   ;==>CloseVolume
Func LockVolume($hVolume)
    Local $dwBytesReturned
    Local $dwSleepAmount
    Local $nTryCount
    local $iRead
    $dwSleepAmount = $LOCK_TIMEOUT / $LOCK_RETRIES;
    ; Do this in a loop until a timeout period has expired
    For $nTryCount = 0 To $nTryCount < $LOCK_RETRIES
        If _Device_Control($hVolume, $FSCTL_LOCK_VOLUME, $iRead) Then
            Return True
        Else
            Sleep($dwSleepAmount);
        EndIf
    Next
    Return False;
EndFunc   ;==>LockVolume
Func DismountVolume($hVolume)
    ConsoleWrite("Dismount " & $hVolume & @crlf)
    Local $dwBytesReturned, $iRead
    local $aResult = _Device_Control($hVolume, $FSCTL_DISMOUNT_VOLUME, $iRead)
    msgbox(0,"",$aResult)
    Return $aResult
    ;Return $dwBytesReturned
EndFunc   ;==>DismountVolume
Func PreventRemovalOfVolume($hVolume, $fPreventRemoval)
    Local $dwBytesReturned
    Local $aResult
    Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
    
    $PMRBUFFER = DllStructCreate("bool PreventMediaRemoval")
    
    DllStructSetData($PMRBUFFER,"PreventMediaRemoval",$fPreventRemoval)
    
    $lpBytesReturned    = DllStructCreate("int Read")
    $pRead   = DllStructGetPtr($lpBytesReturned, "Read")
    $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hVolume,"uint",$IOCTL_STORAGE_MEDIA_REMOVAL,"ptr",DllStructGetPtr($PMRBUFFER),"uint",DllStructGetSize($PMRBUFFER), _ 
    "ptr",$lpOutBuffer,"uint",$nOutBufferSize,"ptr",$pRead,"ptr",$lpOverlapped)
    if $aResult = 0 then msgbox(0,"",_WinAPI_GetLastErrorMessage())
    Return $aResult <> 0
    
     ;& PMRBuffer, sizeof (PREVENT_MEDIA_REMOVAL),
    ;NULL, 0,
    ; & dwBytesReturned,
    ;NULL);
EndFunc   ;==>PreventRemovalOfVolume
Func AutoEjectVolume($hVolume)
    Local $aResult, $iRead;
    $aResult = _Device_Control($hVolume, $IOCTL_STORAGE_EJECT_MEDIA, $iRead)
    Return $aResult
EndFunc   ;==>AutoEjectVolume
Func EjectVolume($cDriveLetter)
    Local $hVolume;
    Local $fRemoveSafely = False;
    Local $fAutoEject = False;
    ; Open the volume.
    $hVolume = OpenVolume($cDriveLetter);
    If $hVolume == $INVALID_HANDLE_VALUE Then Return False
    ; Lock and dismount the volume.
    If LockVolume($hVolume) And DismountVolume($hVolume) Then
        $fRemoveSafely = True;
        ConsoleWrite("Volume Locked and Dismounted, trying to eject " & @crlf)
        ; Set prevent removal to false and eject the volume.
        If PreventRemovalOfVolume($hVolume, False) And AutoEjectVolume($hVolume) Then
            $fAutoEject = True;
        EndIf
    Else
        ConsoleWrite("Volume can't be locked or dismounted, please close possible opened files" & @crlf)
    EndIf
    
    ; Close the volume so other processes can use the drive.
    If CloseVolume($hVolume) = False Then
        Return False;
    EndIf
    
    If $fAutoEject Then
        ConsoleWrite(StringFormat("Media in Drive %s has been ejected safely.\n", $cDriveLetter))
    Else
        If $fRemoveSafely Then
            ConsoleWrite(StringFormat("Media in Drive %s can be safely removed.\n", $cDriveLetter))
        EndIf
    EndIf
    
    Return True;
EndFunc   ;==>EjectVolume
Func _Device_Control($hDevice, $dwIoControlCode, ByRef $iRead)
    Local $aResult
    Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
    $tRead   = DllStructCreate("int Data")
    
    $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hDevice,"uint",$dwIoControlCode,"ptr",$lpInBuffer,"uint",0, _ 
    "ptr",$lpOutBuffer,"uint",0,"ptr",DllStructGetPtr($tRead),"ptr",$lpOverlapped)
    
    $iRead   = DllStructGetData($tRead, "Data")
    
    ConsoleWrite("Device Control " & $iRead & @CRLF)
    Return $aResult<>0
EndFunc   ;==>_Device_Control

Share this post


Link to post
Share on other sites

My Drive has the Letter E, so when the InputBox prompts for the drive letter I enter "E:" (without quotes)

it Pops a MsgBox that says "True" and then I get the following error message

_WinAPI_CloseHandle: The handle is invalid

this is the output written to the console

>Running:(3.2.12.1):H:\Autoit\autoit3.exe "H:\Scripts\AuotEjectIt.au3"  
E:\ Removable
\\.\E:
Device Control 0
Dismount 0xFFFFFFFF
Device Control 0
Volume Locked and Dismounted, trying to eject 
Device Control 0
+>14:43:56 AutoIT3.exe ended.rc:0
>Exit code: 0   Time: 36.611

Am I missing something here?


[font="Century Gothic"]quisnam est quantum stultus , balatro vel balatro quisnam insistovolubilis in solum rideo risi risum----------------------------------------------------------------------------------------------------------------------------Portable Command Line Tool[/font]

Share this post


Link to post
Share on other sites

Am I missing something here?

Hmm not too sure. I notice in your console output your device (Dismount 0xFFFFFFFF). I think something is failing there. My output has never returned 0xFFFFFFFF.

Share this post


Link to post
Share on other sites

thank !!!!! :P

Share this post


Link to post
Share on other sites

after Eject/dismount how to replug/remount the usb?

Share this post


Link to post
Share on other sites

reconnect it. once unmounted windows doesn't recognise it once you unplugged, replugged it. This is the purpose => Security.


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

reconnect it. once unmounted windows doesn't recognise it once you unplugged, replugged it. This is the purpose => Security.

is it really impossible? or only autoit can not do it?

Edited by Cdma1X

Share this post


Link to post
Share on other sites

Works like a beaut

abosoloutly great!!!

works perfect for me no error's :P

cheers C.W


C.Wnew rules:1.dont use plz in a post or title use please instead2.always use help file as it is now muchly over rated3. dont think where not watching u4.please wait 24 hours after last post ot bump XD i use to make that mistake

Share this post


Link to post
Share on other sites

Cool ! Would be useful for me in future ;D

Share this post


Link to post
Share on other sites

Thanks...I'll try it after this. I've been using the example posted by arcker last year, and its working well.


AUTOIT[sup] I'm lovin' it![/sup]

Share this post


Link to post
Share on other sites

Hi there, sorry for the late response...

one small detail I had forgotten to mention.

I had initially tried the script here at work, NO ADMIN Rights :P

I tried the script again on my home pc and it worked

would be cool to get this to work without admin rights

eitherway... nice work

Cheers...


[font="Century Gothic"]quisnam est quantum stultus , balatro vel balatro quisnam insistovolubilis in solum rideo risi risum----------------------------------------------------------------------------------------------------------------------------Portable Command Line Tool[/font]

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

would be cool to get this to work without admin rights

This is not a limitation of the code, but how the Operating System works. It's outside the scripts control unfortunately. :P Edited by spudw2k

Share this post


Link to post
Share on other sites

Hi!

My external USB disk is:

$uDriveType = "Fixed"

If I add

Case "Fixed"
            $dwAccessFlags = 6

The script run OK.

@-salutations

Share this post


Link to post
Share on other sites

imnsho

CDTray("F:", "open")
Sleep(5000)
CDTray("F:", "closed")

Share this post


Link to post
Share on other sites

Works great, I wish there was a way to just put the text in automatically....

Updated api include and _API_ funcs.

#include <WinApi.au3>
;Prototypes
;BOOL EjectVolume(TCHAR cDriveLetter);
;HANDLE OpenVolume(TCHAR cDriveLetter);
;BOOL LockVolume(HANDLE hVolume);
;BOOL DismountVolume(HANDLE hVolume);
;BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent);
;BOOL AutoEjectVolume(HANDLE hVolume);
;BOOL CloseVolume(HANDLE hVolume);

;StringFormat Output
$szVolumeFormat = ".%s"
$szRootFormat = "%s"
$szErrorFormat = "Error %d: %sn"
;------------------------------------------
;Arbitrary variables
Global Const $INVALID_HANDLE_VALUE = 0
;------------------------------------------
;DeviceIoControl Contants
Global Const $FSCTL_LOCK_VOLUME = int(0x090018)
Global Const $FSCTL_DISMOUNT_VOLUME = int(0x00090020)
Global Const $IOCTL_STORAGE_EJECT_MEDIA  = int(0x002D4808)
Global Const $IOCTL_STORAGE_MEDIA_REMOVAL = int(0x002D4804)

;------------------------------------------
;Retry Constants
Global Const $LOCK_TIMEOUT = 10000     ; 10 Seconds
Global Const $LOCK_RETRIES = 20
$OpenVolume = InputBox("Ejecting...", "Enter the drive to eject", "G:")
ConsoleWrite("Trying to Eject the drive " & EjectVolume($OpenVolume) & @crlf)

Func ReportError($szMsg)
    ConsoleWrite(StringFormat($szErrorFormat, _WinAPI_GetLastErrorMessage (), $szMsg) & @CRLF)
    Exit
EndFunc   ;==>ReportError
Func OpenVolume($cDriveLetter)
    ;HANDLE hVolume
    ;UINT uDriveType
    ;TCHAR szVolumeName[8]
    ;TCHAR szRootName[5]
    ;DWORD dwAccessFlags
    $szRootName = StringFormat($szRootFormat, $cDriveLetter)
    $uDriveType = DriveGetType($szRootName);
    ConsoleWrite($szRootName & @tab & $uDriveType & @crlf)
    Switch $uDriveType
        Case "Removable"
            $dwAccessFlags = 6
        Case "CDROM"
            $dwAccessFlags = 2
        Case Else
            ConsoleWrite("Cannot eject.  Drive type is incorrect." & @CRLF)
            Return $INVALID_HANDLE_VALUE
    EndSwitch
    $szVolumeName = StringFormat($szVolumeFormat, $cDriveLetter)
    ;$szVolumeName = $szVolumeFormat & $cDriveLetter
    ConsoleWrite($szVolumeName & @crlf )
    $hVolume = _WinAPI_CreateFile ($szVolumeName, 2,$dwAccessFlags, 6)
    
    #cs
        hVolume = CreateFile(   szVolumeName,
        dwAccessFlags,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL );
    #ce
    If ($hVolume == $INVALID_HANDLE_VALUE) Then ReportError("CreateFile");
    Return $hVolume;
EndFunc   ;==>OpenVolume
Func CloseVolume($hVolume)
    Return _WinAPI_CloseHandle ($hVolume);
EndFunc   ;==>CloseVolume
Func LockVolume($hVolume)
    Local $dwBytesReturned
    Local $dwSleepAmount
    Local $nTryCount
    local $iRead
    $dwSleepAmount = $LOCK_TIMEOUT / $LOCK_RETRIES;
    ; Do this in a loop until a timeout period has expired
    For $nTryCount = 0 To $nTryCount < $LOCK_RETRIES
        If _Device_Control($hVolume, $FSCTL_LOCK_VOLUME, $iRead) Then
            Return True
        Else
            Sleep($dwSleepAmount);
        EndIf
    Next
    Return False;
EndFunc   ;==>LockVolume
Func DismountVolume($hVolume)
    ConsoleWrite("Dismount " & $hVolume & @crlf)
    Local $dwBytesReturned, $iRead
    local $aResult = _Device_Control($hVolume, $FSCTL_DISMOUNT_VOLUME, $iRead)
    msgbox(0,"",$aResult)
    Return $aResult
    ;Return $dwBytesReturned
EndFunc   ;==>DismountVolume
Func PreventRemovalOfVolume($hVolume, $fPreventRemoval)
    Local $dwBytesReturned
    Local $aResult
    Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
    
    $PMRBUFFER = DllStructCreate("bool PreventMediaRemoval")
    
    DllStructSetData($PMRBUFFER,"PreventMediaRemoval",$fPreventRemoval)
    
    $lpBytesReturned    = DllStructCreate("int Read")
    $pRead   = DllStructGetPtr($lpBytesReturned, "Read")
    $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hVolume,"uint",$IOCTL_STORAGE_MEDIA_REMOVAL,"ptr",DllStructGetPtr($PMRBUFFER),"uint",DllStructGetSize($PMRBUFFER), _
    "ptr",$lpOutBuffer,"uint",$nOutBufferSize,"ptr",$pRead,"ptr",$lpOverlapped)
    if $aResult = 0 then msgbox(0,"",_WinAPI_GetLastErrorMessage())
    Return $aResult <> 0
    
     ;& PMRBuffer, sizeof (PREVENT_MEDIA_REMOVAL),
    ;NULL, 0,
    ; & dwBytesReturned,
    ;NULL);
EndFunc   ;==>PreventRemovalOfVolume
Func AutoEjectVolume($hVolume)
    Local $aResult, $iRead;
    $aResult = _Device_Control($hVolume, $IOCTL_STORAGE_EJECT_MEDIA, $iRead)
    Return $aResult
EndFunc   ;==>AutoEjectVolume
Func EjectVolume($cDriveLetter)
    Local $hVolume;
    Local $fRemoveSafely = False;
    Local $fAutoEject = False;
    ; Open the volume.
    $hVolume = OpenVolume($cDriveLetter);
    If $hVolume == $INVALID_HANDLE_VALUE Then Return False
    ; Lock and dismount the volume.
    If LockVolume($hVolume) And DismountVolume($hVolume) Then
        $fRemoveSafely = True;
        ConsoleWrite("Volume Locked and Dismounted, trying to eject " & @crlf)
        ; Set prevent removal to false and eject the volume.
        If PreventRemovalOfVolume($hVolume, False) And AutoEjectVolume($hVolume) Then
            $fAutoEject = True;
        EndIf
    Else
        ConsoleWrite("Volume can't be locked or dismounted, please close possible opened files" & @crlf)
    EndIf
    
    ; Close the volume so other processes can use the drive.
    If CloseVolume($hVolume) = False Then
        Return False;
    EndIf
    
    If $fAutoEject Then
        ConsoleWrite(StringFormat("Media in Drive %s has been ejected safely.n", $cDriveLetter))
    Else
        If $fRemoveSafely Then
            ConsoleWrite(StringFormat("Media in Drive %s can be safely removed.n", $cDriveLetter))
        EndIf
    EndIf
    
    Return True;
EndFunc   ;==>EjectVolume
Func _Device_Control($hDevice, $dwIoControlCode, ByRef $iRead)
    Local $aResult
    Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
    $tRead   = DllStructCreate("int Data")
    
    $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hDevice,"uint",$dwIoControlCode,"ptr",$lpInBuffer,"uint",0, _
    "ptr",$lpOutBuffer,"uint",0,"ptr",DllStructGetPtr($tRead),"ptr",$lpOverlapped)
    
    $iRead   = DllStructGetData($tRead, "Data")
    
    ConsoleWrite("Device Control " & $iRead & @CRLF)
    Return $aResult<>0
EndFunc   ;==>_Device_Control

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0