Avatar
www.fr-an.de

Hardwareinformationen

Bei der Ermittlung der Laufwerke wurden bereits verschiedene Informationen ermittelt. Die Laufwerksbuchstaben und die SCSI-Adressen sind vom System abhängig, was man auch an den Screenshots der Demoprogramme sieht. Der Hersteller, die ProduktID und die Revision sind direkt von der Hardware abhängig. Für deren Ermittlung wurde das SCSI Pass Through Interface (SPTI) genutzt.

Um auf die Hardware zuzugreifen, kann man die SCSI Multi Media Commands verwenden. Die Drafts sind bei T10 verfügbar. Man benötigt dafür einen Gastzugang, für welchen man sich registrieren muss. Das bedeutet, man gibt Vor- und Zunamen, Firma und Email an. Nach dem Aktzeptieren der Notification und dem Klick auf Submit sollte die Datei angezeigt werden.

Aktuell ist das MultiMedia Command Set - 6 (MMC-6) Revision 02g vom 11.12.2009 (scheint keinen Download mehr zu geben) mit den Änderungen MultiMedia Command Set - 6 Amendment # 1 (MMC-6 AM1) Revision 00 vom 6.12.2011.

Ich weise darauf hin, dass die folgenden Darstellungen Fehler, insbesondere bei Übersetzungen, enthalten können. Für entsprechende Berichte bin jederzeit dankbar. -> Kontakt

Der Funktion DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, pSPTD, SizeOf(TSPTD), pSPTD, SizeOf(TSPTD), nReturnBytes, nil) wird ein Record vom Typ TSCSI_PASS_THROUGH_DIRECT übergeben:

 
  type
    TSCSI_PASS_THROUGH_DIRECT = record
      Length              : Word;
      ScsiStatus          : Byte;
      PathId              : Byte;
      TargetId            : Byte;
      Lun                 : Byte;
      CdbLength           : Byte;
      SenseInfoLength     : Byte;
      DataIn              : Byte;
      DataTransferLength  : ULONG;
      TimeOutValue        : ULONG;
      DataBufferOffset    : Pointer;
      SenseInfoOffset     : ULONG;
      Cdb                 : Array[0..15] of Byte;
    end;
    PSCSI_PASS_THROUGH_DIRECT = ^TSCSI_PASS_THROUGH_DIRECT;
        

Der Command Descriptor Block kann verschiedene Längen besitzen. Bei den Multi Media Commands sind sie 6, 10 oder 12 Byte lang und beginnen mit einem Operation Code.

Es gibt auch den Record TSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER:

 
  type
    TSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER = record
      Sptd     : TSCSI_PASS_THROUGH_DIRECT;
      Filler   : ULONG;
      SenseBuf : Array[0..31] of Byte;
    end;
    PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER = ^TSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
        

Wann man welchen Record verwendet, weiß ich nicht. Auf jeden Fall bekommt man bei Verwendung der Routine mit Buffer keine Fehlermeldungen wie Die Anforderung konnte wegen eines E/A-Gerätefehlers nicht ausgeführt werden. Für die Bearbeitung verwende ich diese Routine:

 
  function GET_SCSI_PASS_THROUGH_DIRECT(aDrive: AnsiChar; aCDB: array of Byte;
                                        aDataBuffer: Pointer; nDataBufferSize: ULONG)
                                        : boolean;
  {*******************************************************************************
  *  Den Befehl mit SCSI_PASS_THROUGH_DIRECT ausführen.
  }
  var
    i               : Byte;
    hDevice         : THandle;
    dwDesiredAccess : Cardinal;
    dwShareMode     : Cardinal;
    pSPTD           : PSCSI_PASS_THROUGH_DIRECT;
    buffer          : array[0..1023] of AnsiChar;
    nInBufferSize   : Cardinal;
    nOutBufferSize  : Cardinal;
    nReturned       : Cardinal;
  begin
    Result := False;
    {
    *  Handle holen.
    }
    dwDesiredAccess := GENERIC_READ or GENERIC_WRITE;
    dwShareMode     := FILE_SHARE_READ or FILE_SHARE_WRITE;
    hDevice := CreateFile(PAnsiChar(Format('\\.\%s:', [aDrive])),
                          dwDesiredAccess, dwShareMode,
                          nil, OPEN_EXISTING, 0, 0);
    {
    *  Wenn das Handle gültig ist.
    }
    if hDevice <> INVALID_HANDLE_VALUE
    then begin
      {
      *  Buffer initialisieren und Datenstruktur füllen
      }
      ZeroMemory(@buffer, 1024);
      pSPTD                     := PSCSI_PASS_THROUGH_DIRECT(@buffer);
      pSPTD^.Length             := SizeOf(TSCSI_PASS_THROUGH_DIRECT);
      pSPTD^.CdbLength          := Length(aCDB);
      pSPTD^.SenseInfoLength    := 14;
      pSPTD^.SenseInfoOffset    := SizeOf(TSCSI_PASS_THROUGH_DIRECT);
      pSPTD^.DataIn             := SCSI_IOCTL_DATA_IN;
      pSPTD^.DataTransferLength := nDataBufferSize;
      pSPTD^.TimeOutValue       := 2000;
      pSPTD^.DataBufferOffset   := aDataBuffer;
      {
      *  CDB übertragen. Mit einer Schleife, weil das Ziel eine feste und die
      *  Quelle eine dynamische Länge besitzt.
      }
      for i := 0 to Length(aCDB) - 1
      do pSPTD^.cdb[i] := aCDB[i];
      {
      *  Anfrage stellen.
      }
      nInBufferSize  := SizeOf(TSCSI_PASS_THROUGH_DIRECT);
      nOutBufferSize := SizeOf(TSCSI_PASS_THROUGH_DIRECT);
      Result := DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT,
                                pSPTD, nInBufferSize, pSPTD, nOutBufferSize,
                                nReturned, nil);
      {
      *  Handle schließen
      }
      CloseHandle(hDevice);
    end;
  end;
        

Die Buffergrößen können auch höher angegeben werden. Unter Umständen ist es sogar notwendig, da es sonst zu einem Fehler Ungültiger Parameter kommen kann.

 
  nInBufferSize  := SizeOf(TSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
  nOutBufferSize := SizeOf(TSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
        

Der Routine wird der Laufwerksbuchstabe, der Command Descriptor Block, der Pointer und die Größe des Speichers für die Antwort übergeben.

Für manche Anfragen ist es notwendig, dass der Wert für SenseInfoLength größer 0 ist. Zum Beispiel beim READ DISC INFORMATION Command wenn man die Daemon Tools Laufwerke abfragt. Im Internet findet man als Werte 14 und 24.

 

Hardwareinformationen:

Über das GET CONFIGURATION Command - OperationCode $46

Andere commands:

 

Aktuelle Demo zu den Hardwareinformationen:

Hardware (podHardware.7z - 316 kb) MD5 (1 kb). Stand: 23. Januar 2012

 

Fr_An - Erstellt: 29. Dezember 2011 - Letzte Änderung: 7. Februar 2012

seit 28. Juli 2010