Projekte > Optische Laufwerke > Laufwerke

SCSI-Adressen

Mit der Funktion DeviceIOControl und dem ControlCode IOCTL_SCSI_GET_ADDRESS lässt sich die SCSI-Adresse eines Laufwerkes ermitteln. Dazu muss mit CreateFile das Handle auf das jeweilige Laufwerk geholt werden. Dazu kann man wie unter Counter den Device Namespace oder unter Verwendung der ermittelten Buchstaben den File Namespaces verwenden.

Deklaration für die SCSI-Adressen

type
  TSCSI_ADDRESS = record
    Length     : LongInt;
    PortNumber : Byte;
    PathId     : Byte;
    TargetId   : Byte;
    Lun        : Byte;
  end;
  PSCSI_ADDRESS = ^TSCSI_ADDRESS;

Die Ermittlung der SCSI-Adressen erfolgt in einer Funktion:

function TOptDrives.ReadSCSIAddress(aDevice: THandle): Boolean;
{*******************************************************************************
*  Die SCSI Adresse des Laufwerkes ermitteln.
}
var
  bSCSIBuffer : Array[0.. 1023] of AnsiChar;
  pSCSIAddr   : PSCSI_ADDRESS;
  nReturned   : Cardinal;
begin
  Result := False;
  if aDevice <> INVALID_HANDLE_VALUE
  then begin
    {
    *  Die SCSI Adresse für das Laufwerk ermitteln und eintragen.
    }
    ZeroMemory(@bSCSIBuffer, 1024);
    pscsiAddr := PSCSI_ADDRESS(@bSCSIBuffer);
    pscsiAddr^.Length := SizeOf(TSCSI_ADDRESS);
    Result := DeviceIoControl(aDevice, IOCTL_SCSI_GET_ADDRESS, nil, 0,
                              pscsiAddr, SizeOf(TSCSI_ADDRESS), nReturned, nil);
    if Result
    then begin
      fDrive[fActive].SCSIAddress.Port     := pscsiAddr^.PortNumber;
      fDrive[fActive].SCSIAddress.TargetId := pscsiAddr^.TargetId;
      fDrive[fActive].SCSIAddress.LUnId    := pscsiAddr^.Lun;
    end;
  end;
end;

Die SCSI-Adressen werden in der Demo beispielsweise nach der Ermittlung der Laufwerksbuchstaben geholt. Zum Holen des Handles wird die Funktion DriveHandle aus dem vorigen Kapitel in leicht abgewandelter Form verwendet.

constructor TOptDrives.Create;
{*******************************************************************************
*  Class erstellen.
}
var
  i       : Integer;
  hDevice : THandle;
begin
  {
  *  Laufwerksbuchstaben ermitteln.
  }
  if ReadDrives > 0
  then begin
    for i := 0 to Length(fDrive) - 1
    do begin
      fActive := i;
      hDevice := DriveHandle(fDrive[fActive].Letter);
      if hDevice <> INVALID_HANDLE_VALUE
      then begin
        ReadSCSIAddress(hDevice);
        CloseHandle(hDevice);
      end;
    end;
  end;
end;

Das Ergebnis des Beispiels sieht so aus:

SCSI Address (podSCSIAddress.7z - 226 kb) MD5 (1 kb). Stand: 28. April 2013

Änderungen an der Demo

28.04.2013Leichte Überarbeitung und neuer Name.
04.04.2013Überarbeitung.