Sign in to follow this  
Followers 0
crash748

[Resolved] Lock the CD-ROM tray

14 posts in this topic

#1 ·  Posted (edited)

I'm searching the way to lock and unlock the cd-rom tray to protect it again my kids.

Anybody have an idea?

Edited by crash748

Share this post


Link to post
Share on other sites



Bump!

Share this post


Link to post
Share on other sites

Thanks Legacy99, toddlerkeys will do what i want but, did it was possible to do it with autoit?

My goal is more like making a cd which when insert autorun the lock of the current CD drive and make a tray icon to unlock and eject the CD...

The only thing I need to make it possible is a way to lock and unlock the cd drive tray with AutoIt!

Share this post


Link to post
Share on other sites

I don't think this is possible at all.

Share this post


Link to post
Share on other sites

By searching on the net i have found this code did it was possible to do the dll call thru autoit?

#DefineFunction LockMedia(DriveLetterAndColon, LockSetting) 
    IntControl(73, 1, 0, 0, 0)
    INVALID_HANDLE_VALUE = -1
    OPEN_EXISTING = 3
    FILE_ATTRIBUTE_NORMAL = 128
    FILE_SHARE_WRITE = 2
    GENERIC_READ = 2147483648
    IOCTL_STORAGE_MEDIA_REMOVAL = 2967556
    

;Fuction for (un)locking Media inside a removable storage drive
;DriveLetterAndColon should be two characters WITHOUT a trailing 
;backslash, ex: "D:"
;LockSetting specifies if we want to lock the media in the drive (True) 
;or unlock it (False)
;Returns True if it succeeds and False if it fails
;CreateFile will probably fail on Win9x systems so this function is only 
;intended for use on NT 4 and greater
    drivepath = StrCat("\\.\", DriveLetterAndColon)
    DaDll=strcat(DirWindows(1),"kernel32.dll")
    hDrive=DllCall(DaDll,long:"CreateFileA",lpstr:drivepath,long:GENERIC_READ,long:FILE_SHARE_WRITE,lpnull, long:OPEN_EXISTING, long:FILE_ATTRIBUTE_NORMAL, lpnull)
    If hDrive <> INVALID_HANDLE_VALUE 
        lpLock = BinaryAlloc(4)
        BinaryPoke(lpLock,0,locksetting)
        LockSz = BinaryEodGet(lpLock)
            lpReturnedBytes = BinaryAlloc(4)
        LockMediaRslt = DllCall(DaDll,long:"DeviceIoControl",long:hDrive, long:IOCTL_STORAGE_MEDIA_REMOVAL, lpbinary:lpLock, long:LockSz, long:0, long:0, lpbinary:lpReturnedBytes, lpnull)
        LastErr = DllLastError()
        BinaryFree(lpLock)
        BinaryFree(lpReturnedBytes)
        DllCall(DaDll,long:"CloseHandle",long:hDrive) ;Clean up after outselves
        if LockMediaRslt == 0
           Message("DeviceIoControl Failed with Error",LastErr)
            Return 0
        Endif 
        Return 1
    Endif
    Return 0

    :WBERRORHANDLER
    if hDrive !=0 then DllCall(DaDll,long:"CloseHandle",long:hDrive)  
    if IsDefined(lpLock) then BinaryFree(lpLock)
    if IsDefined(lpReturnedBytes) then BinaryFree(lpReturnedBytes)
    Message("Error Occured on line",wberrorhandlerline)
    Return 0

#EndFunction

;Grab CDROM Drive letter
CDROMLIST = DiskScan (8)
CDROM = ItemExtract(1,CDROMLIST,@TAB)


;Lock CDROM Drive
ret = LockMedia(CDROM, @True)

Pause("Check CDROM Drive","The CDROM drive %CDROM% should now be locked")

;UnLock CDROM Drive 
ret = LockMedia(CDROM, @False) 

Pause("Check CDROM Drive","The CDROM drive %CDROM% should now be unlocked")
exit

If it was possible, how i can do it? How it work?

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I will try a convert to AutoIt but I'm noob with the dllcall so if anybody can help me i will apreciate!

;Grab CDROM Drive letter
$CDROM = "D:"

;Lock CDROM Drive
LockMedia($CDROM, "@True")

MsgBox(0, "Check CDROM Drive", "The CDROM drive " & $CDROM & " should now be locked")

;UnLock CDROM Drive
LockMedia($CDROM, "@False")

MsgBox(0, "Check CDROM Drive", "The CDROM drive " & $CDROM & " should now be unlocked")

Exit

Func LockMedia($DriveLetterAndColon, $LockSetting)
    $INVALID_HANDLE_VALUE = -1
    $OPEN_EXISTING = 3
    $FILE_ATTRIBUTE_NORMAL = 128
    $FILE_SHARE_WRITE = 2
    $GENERIC_READ = 2147483648
    $IOCTL_STORAGE_MEDIA_REMOVAL = 2967556
        
;Fuction for (un)locking Media inside a removable storage drive
;DriveLetterAndColon should be two characters WITHOUT a trailing
;backslash, ex: "D:"
;LockSetting specifies if we want to lock the media in the drive (True)
;or unlock it (False)
;Returns True if it succeeds and False if it fails
;CreateFile will probably fail on Win9x systems so this function is only
;intended for use on NT 4 and greater
    $drivepath = ("\\.\" & $DriveLetterAndColon)
    $DaDll = "kernel32.dll"
...
...
...

Here my first problem, with what I replace lpnull?

$hDrive = DllCall($DaDll, "int", "CreateFileA", "str", $drivepath, "str", $GENERIC_READ, "str", $FILE_SHARE_WRITE, lpnull, "str", $OPEN_EXISTING, "str", $FILE_ATTRIBUTE_NORMAL, lpnull)

I think i have found, i replace lpnull with "ptr" !

Ok so it's enough for tonight i go sleep!

Edited by crash748

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

I don't want reinvent the wheel, I fount a example script from bhoar at http://www.autoitscript.com/forum/index.ph...mp;#entry201790

I have modifies the script cdtray_routines.au3 to use it like an include which offer these functions:

CDLockTray("DriveLetter:")

CDUnLockTray("DriveLetter:")

CDLoadDisc("DriveLetter:")

CDUnLoadDisc("DriveLetter:")

CDIsTrayOpen("DriveLetter:") ;> Return True or False but seem to don't work! or just work on Vista!?!

Big Thank to bhoar!

Now i will be able to continue my project!

cdtray_routines.au3 Include

;The Function list for the include .au3
;~ CDLockTray("D:")
;~ CDUnLockTray("D:")
;~ CDLoadDisc("D:")
;~ CDUnLoadDisc("D:")
;~ CDIsTrayOpen("D:")
;~   Example: If CDIsTrayOpen("D:") then msgbox(0,"DriveInfo","CD Tray is Open")
;-----------------------------------------------------

;Purpose - Query optical drive(s) directly via SCSI or SCSI-emulation (ATAPI,USB,Firewire) to find out if their tray/door is open or closed instead of the standard methods which really query whether or not media is loaded (all of the microsoft API calls do)
;TODO - parse returned sense info from 0xBD before assuming data is OK
;TODO - support for non-drive-letter optical drives
;TODO - support for changers (both one LUN and multi-lun ones)
;TODO - add support for reading the tray lock status

;-----------------------------------------------------
; Setup Globals Environment
;-----------------------------------------------------


Global Const $INVALID_HANDLE_VALUE = 0xFFFFFFFF
Global Const $GENERIC_READ = 0x80000000
Global Const $GENERIC_WRITE = 0x40000000
Global Const $FILE_SHARE_READ = 0x00000001
Global Const $FILE_SHARE_WRITE = 0x00000002
Global Const $OPEN_EXISTING = 3

Global Const $IOCTL_SCSI_PASS_THROUGH = 0x0004D004 ; (0x00000004 << 16) | ((0x0001 | 0x0002) << 14) | (0x0401 << 2) | 0 [from CTL_CODE macro]
Global Const $SCSI_IOCTL_DATA_IN = 0x01
Global Const $SCSI_IOCTL_DATA_OUT = 0x00
Global Const $SCSI_IOCTL_DATA_UNSPECIFIED = 0x02
Global Const $SPTCDBSIZE = 0x10 ; always sixteen, IOCTL_SCSI_PASS_THROUGH requires this - windows checks to make sure the size of $spt = 44.
Global Const $REALCDBSIZE = 0x0c ; twelve - more compatible than sixteen for ATAPI drives
Global Const $SENSEBUFFERSIZE = 0xF0 ;240 is max (was 32, then 255, which was stupid for byte alignment reasons)
Global Const $DATABUFFERSIZE = 0x0400 ;1024 should handle most calls, except IO, firmware and large changers.  Increase? (was 512)

;Global Const $FSCTL_LOCK_VOLUME = 0x00090018
;Global Const $FSCTL_UNLOCK_VOLUME = 0x00090022
;Global Const $IOCTL_STORAGE_EJECT_MEDIA = 0x002D0808

Global $cdb
Global $spt
Global $sptwb


;-----------------------------------------------------
; Main Routine
;-----------------------------------------------------


;Call routine to create structures to use with DLLs
CreateDLLStructures()
;Call routine to iterate through all of the Optical drives in the system allowing lock/unlock, mount/dismount and a report on the tray status.


;-----------------------------------------------------
; Top-level Function Definitions
;-----------------------------------------------------


Func CreateDLLStructures()
    $CDB_STRUCT = ("ubyte[" & String($SPTCDBSIZE) & "]")
    $SCSI_PASS_THROUGH = "ushort;ubyte;ubyte;ubyte;ubyte;ubyte;ubyte;ubyte;ubyte[3];uint;uint;uint;uint;ubyte[" & String($SPTCDBSIZE) & "]"
    $SCSI_PASS_THROUGH_WITH_BUFFERS = $SCSI_PASS_THROUGH & ";ubyte[" & String($SENSEBUFFERSIZE) & "];ubyte[" & String($DATABUFFERSIZE) & "]"
    
    $cdb = DllStructCreate($CDB_STRUCT)
    $spt = DllStructCreate($SCSI_PASS_THROUGH);used only for length calculations
    $sptwb = DllStructCreate($SCSI_PASS_THROUGH_WITH_BUFFERS)
EndFunc   ;==>CreateDLLStructures

Func PopulateCDB_TrayStatus()
    $CDBCOMMAND = 0xBD ;Mechanism Status in hex
    
    DllStructSetData($cdb, 1, $CDBCOMMAND, 1)
    DllStructSetData($cdb, 1, 0x00, 2)
    DllStructSetData($cdb, 1, 0x00, 3)
    DllStructSetData($cdb, 1, 0x00, 4)
    DllStructSetData($cdb, 1, 0x00, 5)
    DllStructSetData($cdb, 1, 0x00, 6)
    DllStructSetData($cdb, 1, 0x00, 7)
    DllStructSetData($cdb, 1, 0x00, 8)
    DllStructSetData($cdb, 1, 0x00, 9)
    DllStructSetData($cdb, 1, 0x08, 10) ;Request that the device returns only 08 bytes into our databuffer, which is the defined size of the header  We could do more if we had a changer, which would want to give more info, but by setting 8 here, we tell the device not to send more than the header anyway.
    DllStructSetData($cdb, 1, 0x00, 11)
    DllStructSetData($cdb, 1, 0x00, 12)
    ;The next four are not used for ATAPI compatibility, but should be set to zero anyway.
    DllStructSetData($cdb, 1, 0x00, 13)
    DllStructSetData($cdb, 1, 0x00, 14)
    DllStructSetData($cdb, 1, 0x00, 15)
    DllStructSetData($cdb, 1, 0x00, 16)
EndFunc   ;==>PopulateCDB_TrayStatus


Func PopulateCDB_LockTray()
    $CDBCOMMAND = 0x1E ;Prevent/Allow Medium Removal
    
    DllStructSetData($cdb, 1, $CDBCOMMAND, 1)
    DllStructSetData($cdb, 1, 0x00, 2)
    DllStructSetData($cdb, 1, 0x00, 3)
    DllStructSetData($cdb, 1, 0x00, 4)
    DllStructSetData($cdb, 1, 0x01, 5); Set bit 0 to 1
    DllStructSetData($cdb, 1, 0x00, 6)
    DllStructSetData($cdb, 1, 0x00, 7)
    DllStructSetData($cdb, 1, 0x00, 8)
    DllStructSetData($cdb, 1, 0x00, 9)
    DllStructSetData($cdb, 1, 0x00, 10)
    DllStructSetData($cdb, 1, 0x00, 11)
    DllStructSetData($cdb, 1, 0x00, 12)
    ;The next four are not used for ATAPI compatibility, but should be set to zero anyway.
    DllStructSetData($cdb, 1, 0x00, 13)
    DllStructSetData($cdb, 1, 0x00, 14)
    DllStructSetData($cdb, 1, 0x00, 15)
    DllStructSetData($cdb, 1, 0x00, 16)
EndFunc   ;==>PopulateCDB_LockTray

Func PopulateCDB_UnLockTray()
    $CDBCOMMAND = 0x1E ;Prevent/Allow Medium Removal
    
    DllStructSetData($cdb, 1, $CDBCOMMAND, 1)
    DllStructSetData($cdb, 1, 0x00, 2)
    DllStructSetData($cdb, 1, 0x00, 3)
    DllStructSetData($cdb, 1, 0x00, 4)
    DllStructSetData($cdb, 1, 0x00, 5); Set bit 0 to 0
    DllStructSetData($cdb, 1, 0x00, 6)
    DllStructSetData($cdb, 1, 0x00, 7)
    DllStructSetData($cdb, 1, 0x00, 8)
    DllStructSetData($cdb, 1, 0x00, 9)
    DllStructSetData($cdb, 1, 0x00, 10)
    DllStructSetData($cdb, 1, 0x00, 11)
    DllStructSetData($cdb, 1, 0x00, 12)
    ;The next four are not used for ATAPI compatibility, but should be set to zero anyway.
    DllStructSetData($cdb, 1, 0x00, 13)
    DllStructSetData($cdb, 1, 0x00, 14)
    DllStructSetData($cdb, 1, 0x00, 15)
    DllStructSetData($cdb, 1, 0x00, 16)
EndFunc   ;==>PopulateCDB_UnLockTray

Func PopulateCDB_LoadDisc()
    $CDBCOMMAND = 0x1B ;Start/Stop Unit
    
    DllStructSetData($cdb, 1, $CDBCOMMAND, 1)
    DllStructSetData($cdb, 1, 0x00, 2)
    DllStructSetData($cdb, 1, 0x00, 3)
    DllStructSetData($cdb, 1, 0x00, 4)
    DllStructSetData($cdb, 1, 0x03, 5) ;00000011 = Load Disc and Spin Up
    DllStructSetData($cdb, 1, 0x00, 6)
    DllStructSetData($cdb, 1, 0x00, 7)
    DllStructSetData($cdb, 1, 0x00, 8)
    DllStructSetData($cdb, 1, 0x00, 9)
    DllStructSetData($cdb, 1, 0x00, 10)
    DllStructSetData($cdb, 1, 0x00, 11)
    DllStructSetData($cdb, 1, 0x00, 12)
    ;The next four are not used for ATAPI compatibility, but should be set to zero anyway.
    DllStructSetData($cdb, 1, 0x00, 13)
    DllStructSetData($cdb, 1, 0x00, 14)
    DllStructSetData($cdb, 1, 0x00, 15)
    DllStructSetData($cdb, 1, 0x00, 16)
EndFunc   ;==>PopulateCDB_LoadDisc

Func PopulateCDB_UnLoadDisc()
    $CDBCOMMAND = 0x1B ;Start/Stop Unit
    
    DllStructSetData($cdb, 1, $CDBCOMMAND, 1)
    DllStructSetData($cdb, 1, 0x00, 2)
    DllStructSetData($cdb, 1, 0x00, 3)
    DllStructSetData($cdb, 1, 0x00, 4)
    DllStructSetData($cdb, 1, 0x02, 5) ;00000010 = Spin Down and UnLoad Disc
    DllStructSetData($cdb, 1, 0x00, 6)
    DllStructSetData($cdb, 1, 0x00, 7)
    DllStructSetData($cdb, 1, 0x00, 8)
    DllStructSetData($cdb, 1, 0x00, 9)
    DllStructSetData($cdb, 1, 0x00, 10)
    DllStructSetData($cdb, 1, 0x00, 11)
    DllStructSetData($cdb, 1, 0x00, 12)
    ;The next four are not used for ATAPI compatibility, but should be set to zero anyway.
    DllStructSetData($cdb, 1, 0x00, 13)
    DllStructSetData($cdb, 1, 0x00, 14)
    DllStructSetData($cdb, 1, 0x00, 15)
    DllStructSetData($cdb, 1, 0x00, 16)
EndFunc   ;==>PopulateCDB_UnLoadDisc

Func PopulateSPTWB()
    $Len_spt = DllStructGetSize($spt)
    ;Are these necessary if the optical drive is at a drive letter and we pass the handle, right?
    ;docs seem to suggest that the port driver fills these in if we are using an enumerated device
    $Bus = 0x00
    $ID = 0x00
    $Lun = 0x00
    
    DllStructSetData($sptwb, 1, $Len_spt);Length of pre-filler to be set before making call
    DllStructSetData($sptwb, 2, 0x00);Checked on return from call
    DllStructSetData($sptwb, 3, $Bus);SCSI bus # - I believe the port driver fills this in
    DllStructSetData($sptwb, 4, $ID);SCSI ID # - I believe the port driver fills this in
    DllStructSetData($sptwb, 5, $Lun);SCSI Lun # -I believe the port driver fills this in
    DllStructSetData($sptwb, 6, $REALCDBSIZE);Length of CDB to be set before making call (12 for ATAPI compatibility)?
    DllStructSetData($sptwb, 7, $SENSEBUFFERSIZE);Length of Sense buffer to be set before making call - or always 32?
    DllStructSetData($sptwb, 8, $SCSI_IOCTL_DATA_IN);Flag for Data Transfer direction to be set before making call
    ;item #9 is simple a placehold for byte alignment, so ignore it
    DllStructSetData($sptwb, 10, $DATABUFFERSIZE);Length of Data buffer to be set before making call - or always 512
    DllStructSetData($sptwb, 11, 0x05);Timeout for call - to be set before making call
    DllStructSetData($sptwb, 12, $Len_spt + $SENSEBUFFERSIZE);Offset from first byte to beginning of data buffer
    DllStructSetData($sptwb, 13, $Len_spt);Offset from first byte to beginning of sense buffer
    For $i = 1 To $SPTCDBSIZE
        DllStructSetData($sptwb, 14, DllStructGetData($cdb, 1, $i), $i);12 bytes of data representing the CDB
    Next
    DllStructSetData($sptwb, 15, 0x00, 1);Sense Buffer - leave alone before call
    DllStructSetData($sptwb, 16, 0x00, 1);Data Buffer - leave alone before call
    
EndFunc   ;==>PopulateSPTWB

;>The main Function of the include .au3

Func CDIsTrayOpen($CDROM_LETTER)
    $hVolume = OpenVolume($CDROM_LETTER)
    If $hVolume = $INVALID_HANDLE_VALUE Then
        MsgBox(4096, $CDROM_LETTER & " is not a valid Optical drive", "There was no optical drive at that drive letter, or you do not have high enough access to talk to it directly.", 5)
    EndIf
    If IsTrayOpen($hVolume) Then
        Return (True)
    Else
        Return (False)
    EndIf
EndFunc   ;==>CDIsTrayOpen

Func CDLockTray($CDROM_LETTER)
    $hVolume = OpenVolume($CDROM_LETTER)
    If $hVolume = $INVALID_HANDLE_VALUE Then
        MsgBox(4096, $CDROM_LETTER & " is not a valid Optical drive", "There was no optical drive at that drive letter, or you do not have high enough access to talk to it directly.", 5)
    EndIf
    LockTray($hVolume)
EndFunc   ;==>CDLockTray

Func CDUnLockTray($CDROM_LETTER)
    $hVolume = OpenVolume($CDROM_LETTER)
    If $hVolume = $INVALID_HANDLE_VALUE Then
        MsgBox(4096, $CDROM_LETTER & " is not a valid Optical drive", "There was no optical drive at that drive letter, or you do not have high enough access to talk to it directly.", 5)
    EndIf
    UnLockTray($hVolume)
EndFunc   ;==>CDUnLockTray

Func CDLoadDisc($CDROM_LETTER)
    $hVolume = OpenVolume($CDROM_LETTER)
    If $hVolume = $INVALID_HANDLE_VALUE Then
        MsgBox(4096, $CDROM_LETTER & " is not a valid Optical drive", "There was no optical drive at that drive letter, or you do not have high enough access to talk to it directly.", 5)
    EndIf
    LoadDisc($hVolume)
EndFunc   ;==>CDLoadDisc

Func CDUnLoadDisc($CDROM_LETTER)
    $hVolume = OpenVolume($CDROM_LETTER)
    If $hVolume = $INVALID_HANDLE_VALUE Then
        MsgBox(4096, $CDROM_LETTER & " is not a valid Optical drive", "There was no optical drive at that drive letter, or you do not have high enough access to talk to it directly.", 5)
    EndIf
    UnLoadDisc($hVolume)
EndFunc   ;==>CDUnLoadDisc

;-----------------------------------------------------
; Lower-level Function Definitions
;-----------------------------------------------------

Func DoSCSICall(ByRef $hVolume)
    $returnvalue = DllStructCreate("ptr")
    
    ;!!! DeviceIOControl expects ptr;long;ptr;long;ptr;long;ptr;ptr !!!
    $ret = DllCall( _
            "kernel32.dll", _
            "int", "DeviceIoControl", _
            "hwnd", $hVolume, _
            "int", $IOCTL_SCSI_PASS_THROUGH, _
            "ptr", DllStructGetPtr($sptwb), _
            "int", DllStructGetSize($spt), _
            "ptr", DllStructGetPtr($sptwb), _
            "int", DllStructGetSize($sptwb), _
            "int*", $returnvalue, _
            "ptr", 0 _
            )
    
    If @error Then
        MsgBox(1, "EXITING...", "DeviceIoControl DLLCall failed with error level: " & String(@error) & "!")
        Exit (1)
    EndIf
    
    If $ret[0] = 0 Then
        _GetLastErrorMessage("Error in DeviceIoControl call to IOCTL_SCSI_PASS_THROUGH:")
        Exit (1)
    EndIf
    
    ;check the sense buffer first, otherwise the data buffer is undefined?
    ;guess I should learn how to do that.
    
    ;For $i = 1 To $SENSEBUFFERSIZE
    ;   $temp = DllStructGetData($sptwb, 15, $i)
    ;   If $temp = 0x00 Then
    ;   Else
    ;      MsgBox(1, "Sense Buffer Data Found", "Non zero value found at sense buffer byte [" & $i & "]:  [" & $temp & "]")
    ;   EndIf
    ;Next
    
    ;For $i = 1 To $DATABUFFERSIZE
    ;   $temp = DllStructGetData($sptwb, 16, $i)
    ;   If $temp = 0x00 Then
    ;   Else
    ;      MsgBox(1, "Data Buffer Data Found", "Non zero value found at data buffer byte [" & $i & "]:  [" & $temp & "]")
    ;   EndIf
    ;Next
EndFunc   ;==>DoSCSICall

Func IsTrayOpen(ByRef $hVolume)
    ;Call routine to set up the CDB of this SCSI transaction's SRB, in this case 0xBD
    PopulateCDB_TrayStatus()
    ;Call routine to set up the SCSI_PASS_THROUGH_WITH_BUFFERS stucture - this is general purpose, though the sizes of globals might need to be adjusted for certain SRBs
    PopulateSPTWB(); to ensure a fresh SRB each time
    ;Perform the SCSI transaction
    DoSCSICall($hVolume)
    
    $second_byte = DllStructGetData($sptwb, 16, 2) ;should be the second byte
    ;now we need the bit here 00010000
    
    $traystatus = BitAND($second_byte, 0x10)
    If $traystatus = 0x10 Then
        Return (True)
    Else
        Return (False)
    EndIf
    
EndFunc   ;==>IsTrayOpen


Func LockTray(ByRef $hVolume)
    ;Call routine to set up the CDB of this SCSI transaction's SRB
    PopulateCDB_LockTray()
    ;Call routine to set up the SCSI_PASS_THROUGH_WITH_BUFFERS stucture - this is general purpose, though the sizes of globals might need to be adjusted for certain SRBs
    PopulateSPTWB(); to ensure a fresh SRB each time
    ;Perform the SCSI transaction
    DoSCSICall($hVolume)
    
    ;TODO: Analyze sense data to verify this worked.
    
EndFunc   ;==>LockTray

Func UnLockTray(ByRef $hVolume)
    ;Call routine to set up the CDB of this SCSI transaction's SRB
    PopulateCDB_UnLockTray()
    ;Call routine to set up the SCSI_PASS_THROUGH_WITH_BUFFERS stucture - this is general purpose, though the sizes of globals might need to be adjusted for certain SRBs
    PopulateSPTWB(); to ensure a fresh SRB each time
    ;Perform the SCSI transaction
    DoSCSICall($hVolume)
    
    ;TODO: Analyze sense data to verify this worked.
    
EndFunc   ;==>UnLockTray

Func LoadDisc(ByRef $hVolume)
    ;Call routine to set up the CDB of this SCSI transaction's SRB
    PopulateCDB_LoadDisc()
    ;Call routine to set up the SCSI_PASS_THROUGH_WITH_BUFFERS stucture - this is general purpose, though the sizes of globals might need to be adjusted for certain SRBs
    PopulateSPTWB(); to ensure a fresh SRB each time
    ;Perform the SCSI transaction
    DoSCSICall($hVolume)
    
    ;TODO: Analyze sense data to verify this worked.
    
EndFunc   ;==>LoadDisc

Func UnLoadDisc(ByRef $hVolume)
    ;Call routine to set up the CDB of this SCSI transaction's SRB
    PopulateCDB_UnLoadDisc()
    ;Call routine to set up the SCSI_PASS_THROUGH_WITH_BUFFERS stucture - this is general purpose, though the sizes of globals might need to be adjusted for certain SRBs
    PopulateSPTWB(); to ensure a fresh SRB each time
    ;Perform the SCSI transaction
    DoSCSICall($hVolume)
    
    ;TODO: Analyze sense data to verify this worked.
    
EndFunc   ;==>UnLoadDisc

Func OpenVolume($cDriveLetter)
    ;   From AUTOIT forums
    Local $hVolume, $uDriveType, $szVolumeName, $dwAccessFlags
    If StringLen($cDriveLetter) = 1 Then
        $cDriveLetter = $cDriveLetter & ":"
    ElseIf StringLen($cDriveLetter) = 2 Then
        ;do nothing
    ElseIf StringLen($cDriveLetter) = 3 Then
        $cDriveLetter = StringLeft($cDriveLetter, 2)
    Else
        Return $INVALID_HANDLE_VALUE
    EndIf
    
    Local $szRootName = $cDriveLetter & "\"
    
    $uDriveType = DriveGetType($szRootName)
    Select
        Case $uDriveType == "Removable"
            $dwAccessFlags = BitOR($GENERIC_READ, $GENERIC_WRITE)
        Case $uDriveType == "CDROM"
            ;We need write access in order to send scsi commands.
            $dwAccessFlags = BitOR($GENERIC_READ, $GENERIC_WRITE)
            ;$dwAccessFlags = $GENERIC_READ
        Case Else
            Return $INVALID_HANDLE_VALUE
    EndSelect
    
    $szVolumeName = "\\.\" & $cDriveLetter & ""
    ;$szVolumeName = "\\.\CdRom0"
    
    ;in addition to getting the handle, the following also verifies write access, which is required to use the scsi pass through
    $hVolume = DllCall( _
            "kernel32.dll", "hwnd", _
            "CreateFile", _
            "str", $szVolumeName, _
            "long", $dwAccessFlags, _
            "long", BitOR($FILE_SHARE_READ, $FILE_SHARE_WRITE), _
            "ptr", 0, _
            "long", $OPEN_EXISTING, _
            "long", 0, _
            "long", 0 _
            )
    
    If @error Then
        MsgBox(1, "EXITING...", "CreateFile DLLCall failed!")
        Exit (1)
    EndIf
    
    Return $hVolume[0]
EndFunc   ;==>OpenVolume

;===============================================
;    _GetLastErrorMessage($DisplayMsgBox="")
;    Format the last windows error as a string and return it
;    if $DisplayMsgBox <> "" Then it will display a message box w/ the error
;    Return        Window's error as a string
;===============================================
Func _GetLastErrorMessage($DisplayMsgBox = "")
    Local $ret, $s
    Local $p = DllStructCreate("char[4096]")
    Local Const $FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
    
    If @error Then Return ""
    
    $ret = DllCall("Kernel32.dll", "int", "GetLastError")
    $LastError = $ret[0]
    $ret = DllCall("kernel32.dll", "int", "FormatMessage", _
            "int", $FORMAT_MESSAGE_FROM_SYSTEM, _
            "ptr", 0, _
            "int", $LastError, _
            "int", 0, _
            "ptr", DllStructGetPtr($p), _
            "int", 4096, _
            "ptr", 0)
    $s = DllStructGetData($p, 1)
    If $DisplayMsgBox <> "" Then MsgBox(0, "_GetLastErrorMessage", $DisplayMsgBox & @CRLF & String($LastError) & "-" & $s)
    Return $s
EndFunc   ;==>_GetLastErrorMessage
Edited by crash748

Share this post


Link to post
Share on other sites

Big Thank to bhoar!

Now i will be able to continue my project!

You're welcome! ;)

-brendan

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

How can we know the current state of the CDRom drive Lock/Unlock?

Because when computer go to sleep the lock is automatically remove and making it lock again when the computer resume fail some time!

Edited by crash748

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

How can we know the current state of the CDRom drive Lock/Unlock?

Because when computer go to sleep the lock is automatically remove and making it lock again when the computer resume fail some time!

Sleep or hibernate?

If sleep, then it is probably windows unlocking the tray during resume. If hibernate, the power to the drive is cut, so the drive wakes up unlocked.

If it doesn't work when it resumes at all, the handle might be stale. In some situations, I've found it's safer to get rid of the handle (via the appropriate windows function) when you're not using it and just grab it when you need it.

-brendan

Edited by bhoar

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