CD-LW locked

  • hi,

    da ich nen lappi habe, wo auf der einen seite der lüfter ist, und auf der anderen seite das cd-lw, habe ich ein prob, wenn ich den in meinen rucksack stecken will, und er noch an ist.

    da ich ihn nicht auf den lüfter legen kann, kommt das cd-lw nach unten. dann kann es aber passieren, dass es sich öffnet, was ebenfalls scheiße ist.

    nur wollte ich ein kleines script schreiben, dass das öffnen verhindert. doch wie fange ich das öffnen des cd-lws ab ?

  • Meinst Du das Signal, welches gesendet wird, wenn man auf die "Laufwerk öffnen"-taste am Laufwerk drückt?
    Ich denke, dass das Signal direkt im Laufwerk verarbeitet wird. Das heißt, Du müsstest auf die Software auf den Laufwerksplatinen zugreifen, was wohl schwierig bis unmöglich werden dürfte.

  • Also als Lsg. gibt es dann nur noch einmal.
    Ein Laptop, zumindest meines von Siemens, hat vier dünne und zwei breite Seiten. Dann leg es doch einfach auf die langen Seiten.

    Alternativ gibt es die Möglichkeit einen Rucksack zu kaufen, wo du das Laptop reinstellen kannst.

    NUN ABER mal im ernst. Glaube nicht, das Du eine Möglichkeit hast das zu steuern. Ober CD-LW nach unten und rechts und links was unter legen.

    LG Lina

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl

    • Offizieller Beitrag

    Also so sieht das ganze mit VB aus. Hier der Code aus "CDRom-Lock.frm" des gleichnamigen Tools.
    Den kpl. Sourcecode kannst du hier laden:
    SourceForge.net

    Spoiler anzeigen
  • thx, ich dachte erst, das script wäre mit 10 zeilen fertig ... danach merkte ich zwar, dass das nix wird, aber whooooooooooot ist das oO

    ich glaub ich greif dann doch auf ein bestehendes tool zurück =)

    PS: mein engl ist sehr besch... bescheiden, aber könnte das mir helfen?
    http://www.autoitscript.com/forum/index.php?showtopic=38921

    • Offizieller Beitrag

    So, ich hab schon mal 'nen Anfang gemacht.
    Im MS-Support habe ich ein Beispiel gefunden. Natürlich unter Verwendung von Routinen, die in AutoIt nicht verfügbar sind.
    Notwendig sind:
    - CreateFile (habe ich schon nachgebaut und scheint zu funktionieren)
    - PREVENT_MEDIA_REMOVAL (da fehlt mir noch jeder Ansatz, bzw. ich weiß nicht, wie ich das in AutoIt umsetzen soll: )

    Spoiler anzeigen

    - DeviceIoControl (Dazu habe ich das Folgende, komme aber auch nicht weiter: )

    Spoiler anzeigen


    Und hier gefundener Mustercode und meine Anfänge der Umsetzung in AutoIt:

    Spoiler anzeigen
    [autoit]

    ; Lock / UnLock CD-ROM Drive Link: http://support.microsoft.com/kb/138434/de
    #cs
    #include <windows.h>
    #include <winioctl.h> // From the Win32 SDK \Mstools\Include
    #include "ntddcdrm.h" // From the Windows NT DDK \Ddk\Src\Storage\Inc

    [/autoit] [autoit][/autoit] [autoit]

    /*
    This code reads sectors 16 and 17 from a compact disc and writes
    the contents to a disk file named Sector.dat
    */

    [/autoit] [autoit][/autoit] [autoit]

    {
    HANDLE hCD, hFile;
    DWORD dwNotUsed;

    [/autoit] [autoit][/autoit] [autoit]

    // Disk file that will hold the CD-ROM sector data.
    hFile = CreateFile ("sector.dat",
    GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL, NULL);

    [/autoit] [autoit][/autoit] [autoit]

    // For the purposes of this sample, drive F: is the CD-ROM
    // drive.
    hCD = CreateFile ("\\\\.\\F:", GENERIC_READ,
    FILE_SHARE_READ|FILE_SHARE_WRITE,
    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
    NULL);

    [/autoit] [autoit][/autoit] [autoit]

    // If the CD-ROM drive was successfully opened, read sectors 16
    // and 17 from it and write their contents out to a disk file.
    if (hCD != INVALID_HANDLE_VALUE)
    {
    DISK_GEOMETRY dgCDROM;
    PREVENT_MEDIA_REMOVAL pmrLockCDROM;

    [/autoit] [autoit][/autoit] [autoit]

    // Lock the compact disc in the CD-ROM drive to prevent accidental
    // removal while reading from it.
    pmrLockCDROM.PreventMediaRemoval = TRUE;
    DeviceIoControl (hCD, IOCTL_CDROM_MEDIA_REMOVAL,
    &pmrLockCDROM, sizeof(pmrLockCDROM), NULL,
    0, &dwNotUsed, NULL);

    [/autoit] [autoit][/autoit] [autoit]

    // Get sector size of compact disc
    if (DeviceIoControl (hCD, IOCTL_CDROM_GET_DRIVE_GEOMETRY,
    NULL, 0, &dgCDROM, sizeof(dgCDROM),
    &dwNotUsed, NULL))
    {
    LPBYTE lpSector;
    DWORD dwSize = 2 * dgCDROM.BytesPerSector; // 2 sectors

    [/autoit] [autoit][/autoit] [autoit]

    // Allocate buffer to hold sectors from compact disc. Note that
    // the buffer will be allocated on a sector boundary because the
    // allocation granularity is larger than the size of a sector on a
    // compact disk.
    lpSector = VirtualAlloc (NULL, dwSize,
    MEM_COMMIT|MEM_RESERVE,
    PAGE_READWRITE);

    [/autoit] [autoit][/autoit] [autoit]

    // Move to 16th sector for something interesting to read.
    SetFilePointer (hCD, dgCDROM.BytesPerSector * 16,
    NULL, FILE_BEGIN);

    [/autoit] [autoit][/autoit] [autoit]

    // Read sectors from the compact disc and write them to a file.
    if (ReadFile (hCD, lpSector, dwSize, &dwNotUsed, NULL))
    WriteFile (hFile, lpSector, dwSize, &dwNotUsed, NULL);

    [/autoit] [autoit][/autoit] [autoit]

    VirtualFree (lpSector, 0, MEM_RELEASE);
    }

    [/autoit] [autoit][/autoit] [autoit]

    // Unlock the disc in the CD-ROM drive.
    pmrLockCDROM.PreventMediaRemoval = FALSE;
    DeviceIoControl (hCD, IOCTL_CDROM_MEDIA_REMOVAL,
    &pmrLockCDROM, sizeof(pmrLockCDROM), NULL,
    0, &dwNotUsed, NULL);

    [/autoit] [autoit][/autoit] [autoit]

    CloseHandle (hCD);
    CloseHandle (hFile);
    }
    }
    #ce

    [/autoit] [autoit][/autoit] [autoit]

    #cs Link: http://www.vbarchiv.net/vbapi/CreateFile.php
    Private Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" _
    (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, _
    ByVal dwShareMode As Long, lpSecurityAttributes As Any, _
    ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, _
    ByVal hTemplateFile As Long) As Long
    #ce

    [/autoit] [autoit][/autoit] [autoit]

    Const $GENERIC_READ = 0x80000000 ; Nur Lesen
    Const $GENERIC_WRITE = 0x40000000 ; Nur Schreiben
    Const $FILE_SHARE_READ = 0x1
    Const $FILE_SHARE_WRITE = 0x2
    Const $OPEN_EXISTING = 3
    Const $FILE_ATTRIBUTE_NORMAL = 0x80
    Dim $Lw = 'F:' ; CD-Laufwerksbuchstabe

    [/autoit] [autoit][/autoit] [autoit]

    Dim $hCD = CreateFile("\\\\.\\" & $Lw, $GENERIC_READ, BitOR($FILE_SHARE_READ, $FILE_SHARE_WRITE), _
    'NULL', $OPEN_EXISTING, $FILE_ATTRIBUTE_NORMAL, 'NULL')

    [/autoit] [autoit][/autoit] [autoit]

    If $hCD = -1 Then
    MsgBox(0, 'Fehler', 'CD-Laufwerk nicht gefunden')
    Exit
    Else
    MsgBox(0, '', "funzt")
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    #cs
    PREVENT_MEDIA_REMOVAL pmrLockCDROM;

    [/autoit] [autoit][/autoit] [autoit]

    // Lock the compact disc in the CD-ROM drive to prevent accidental
    // removal while reading from it.
    pmrLockCDROM.PreventMediaRemoval = TRUE;
    DeviceIoControl (hCD, IOCTL_CDROM_MEDIA_REMOVAL,
    &pmrLockCDROM, sizeof(pmrLockCDROM), NULL,
    0, &dwNotUsed, NULL);
    #ce

    [/autoit] [autoit][/autoit] [autoit]

    #cs
    // Unlock the disc in the CD-ROM drive.
    pmrLockCDROM.PreventMediaRemoval = FALSE;
    DeviceIoControl (hCD, IOCTL_CDROM_MEDIA_REMOVAL,
    &pmrLockCDROM, sizeof(pmrLockCDROM), NULL,
    0, &dwNotUsed, NULL);
    #ce

    [/autoit] [autoit][/autoit] [autoit]

    Func CreateFile($lpFileName,$dwDesiredAccess,$dwShareMode,$lpSecurityAttributes, _
    $dwCreationDisposition,$dwFlagsAndAttributes,$hTemplateFile)
    Return DllCall("kernel32.dll", "long", "CreateFileA", "str", $lpFileName, "long", $dwDesiredAccess, _
    "long", $dwShareMode, "str", $lpSecurityAttributes, "long", $dwCreationDisposition, _
    "long", $dwFlagsAndAttributes, "long", $hTemplateFile)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func DeviceIoControl($hDevice,$dwIoControlCode,$lpInBuffer,$nInBufferSize, _
    $lpOutBuffer,$nOutBufferSize,$lpBytesReturned,$lpOverlapped)
    Return DllCall("kernel32.dll", "long", "DeviceIoControl", "long", $hDevice, "long", $dwIoControlCode, _
    "str", $lpInBuffer, "long", $nInBufferSize, "str", $lpOutBuffer, "long", $nOutBufferSize, _
    "long", $lpBytesReturned, "str", $lpOverlapped)
    EndFunc

    [/autoit]

    Edit: Die Funktion DeviceIoControl habe ich jetzt auch nachgebaut. (s. Code)
    Nun muß also noch 'ne Lösung für PREVENT_MEDIA_REMOVAL her...

    Die unteren beiden auskommentierten Blöcke müssen noch erledigt werden.
    Vielleicht hat ja jemand 'ne Eingebung :D .

    • Offizieller Beitrag

    HI,

    Spoiler anzeigen
    [autoit]

    ;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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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)

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    Global $cdb
    Global $spt
    Global $sptwb

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;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.
    TrayStuffForAllOpticals()

    [/autoit] [autoit][/autoit] [autoit]

    Exit (0)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    Func TrayStuffForAllOpticals()
    $var = DriveGetDrive( "cdrom")

    If Not @error Then
    For $j = 1 To $var[0]
    $hVolume = OpenVolume($var[$j])
    If $hVolume = $INVALID_HANDLE_VALUE Then
    MsgBox(4096, $var[$j] & " 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.")
    Else
    MsgBox(1, "Drive #" & $j & " of " & $var[0] & " drive(s) found!", "Hey, drive " & $var[$j] & " (" & String($hVolume) & ") is a good optical drive.")

    $button = MsgBox(4, "Lock the drive tray?", "Do you wish to lock the tray for drive " & $var[$j] & "?")
    If $button = 6 Then
    LockTray($hVolume)
    EndIf
    $button = MsgBox(4, "UnLock the drive tray?", "Do you wish to unlock the tray for drive " & $var[$j] & "?")
    If $button = 6 Then
    UnLockTray($hVolume)
    EndIf

    If IsTrayOpen($hVolume) Then
    MsgBox(1, "Tray Status", "The Tray for drive " & $var[$j] & " is open.")
    $button = MsgBox(4, "Close the drive tray?", "Do you wish to close the drive tray and, if applicable, load (mount) the disc in the tray for drive " & $var[$j] & "?")
    If $button = 6 Then
    LoadDisc($hVolume)
    EndIf
    Else
    MsgBox(1, "Tray Status", "The Tray for drive " & $var[$j] & " is closed.")
    $button = MsgBox(4, "Open the drive tray?", "Do you wish to eject the tray for drive " & $var[$j] & "?")
    If $button = 6 Then
    UnLoadDisc($hVolume)
    EndIf
    EndIf
    EndIf
    Next
    Else
    MsgBox(4096, "No optical drives", "There were no optical drives found in your system")
    EndIf
    EndFunc ;==>TrayStuffForAllOpticals

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    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_ptr", $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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================
    ; _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

    [/autoit] [autoit][/autoit] [autoit][/autoit]

    So long,

    Mega

  • thx euch beiden ...

    mit dem script konnte ich mir das jetzt so bauen, wie ich das vorhatte. erstmal im schnellverfahren, müsste das jetzt noch feiner machen ...

    darf man das script denn verwenden und abgeändert wieder anbieten, natürlich nicht als meins, so dass andere es auch nutzen können?
    so wie es jetzt ist, würde ich sagen, ist es ja eher nur ein proof-of-concept =)

  • also ich hätte eine lösung die so funktioniert das nachdem sich das laufwerk öffnet sofort wieder schließt und wenn man auf ESC drückt beendet sich das prog

    Es funktioniert zumindestens bei meinem rechner so

    Spoiler anzeigen
    [autoit]


    #include<Misc.au3>
    Do
    CDTray("Dein Laufwerk", "close")
    Until _IsPressed("1B")

    [/autoit]