Einzelnen Beitrag anzeigen

Benutzerbild von Garfield
Garfield

Registriert seit: 9. Jul 2004
Ort: Aken (Anhalt-Bitterfeld)
1.334 Beiträge
 
Delphi XE5 Professional
 
#1

RPC State (Region Code) auslesen.

  Alt 1. Apr 2008, 18:55
Auf http://www.codeproject.com/KB/system/mydvdregion.aspx gibt es ein Tool, mit welchem man ein paar Informationen zum Region Code von DVD-Laufwerken auslesen kann. Die Dokumentation gibt es es unter http://www.t10.org/drafts.htm#SCSI3_CMNDSETS -> http://www.t10.org/ftp/t10/drafts/mmc5/mmc5r04.pdf (ab Seite 513).

Jetzt wollte ich das in Delphi ausprobieren.

Delphi-Quellcode:
procedure TCDDVDDrives.DVDFeature(i: Byte);
const
  KEY_FORMAT_RPC_STATE = 8;

type
  _REPORT_KEY_DATA_RPC_STATE = record
    REPORT_KEY_Data_Length : Word;
    Reserved1 : array[2..3] of Byte;
    RPC_State : Byte;
    Region_Mask : Byte;
    RPC_Scheme : Byte;
    Reserved2 : Byte;
  end;

const
  // Type Code Field Definitions
  TCFD_NONE = $00; // 00b No Drive region setting
  TCFD_SET = $01; // 01b Drive region is set
  TCFD_LAST_CHANCE = $02; // 10b Drive Region is set. Additional restrictions required to make a change.
  TCFD_PERM = $03; // 11b Drive Region has been set permanently, but may be reset by the

const
  // RPC Scheme Field Definition
  RSFD_Unknown = $00; // Drive does enforce Region
  RSFD_RPC_Phase_II = $01; // Drive region shall adhere to this standard and all requirements of the
                                  // CSS license agreement coceming RPC.
type
  // REPORT KEY Data Format
  _REPORT_KEY_CDB = record
    OperationCode : Byte;
    Reserved1 : Byte;
    LogicalBlockAddress : Array[2..5] of Byte;
    Reserved2 : Byte;
    KeyClass : Byte;
    AllocationLength : Word;
    AGID_KeyFormat : Byte; // 0-5 = Keyformat, 6-7 AGID
    Control : Byte;
  end;

var
  buf : array[0..1023] of Char;
  hDevice : THandle;
  pcmd : PSCSI_PASS_THROUGH_DIRECT;
  rb : Cardinal;
  REPORT_KEY_DATA : _REPORT_KEY_DATA_RPC_STATE;
  REPORT_KEY_CDB : _REPORT_KEY_CDB;

begin
  Drive[i].DVDFeature.User_changes := $FF;
  Drive[i].DVDFeature.Vendor_resets := $FF;
  Drive[i].DVDFeature.Type_code := $FF;
  Drive[i].DVDFeature.Region_mask := $FF;
  Drive[i].DVDFeature.RPC_scheme := $FF;

  hDevice := CreateFile(PChar(Format('\\.\%s:', [Drive[i].Letter])),
                   GENERIC_READ or GENERIC_WRITE,
                   FILE_SHARE_READ,
                   nil,
                   OPEN_EXISTING,
                   0,
                   0 );

  if hDevice <> INVALID_HANDLE_VALUE
  then begin
    ZeroMemory(@buf, 1024);
    ZeroMemory(@REPORT_KEY_CDB, SizeOf(REPORT_KEY_CDB));

    pcmd := PSCSI_PASS_THROUGH_DIRECT(@buf);
    pcmd^.Length := SizeOf(SCSI_PASS_THROUGH_DIRECT);
    pcmd^.CdbLength := CDB10GENERIC_LENGTH;
    pcmd^.SenseInfoLength := SizeOf(SCSI_PASS_THROUGH_DIRECT);
    pcmd^.DataIn := SCSI_IOCTL_DATA_IN;
    pcmd^.DataTransferLength := sizeof(_REPORT_KEY_DATA_RPC_STATE);
    pcmd^.TimeOutValue := 6000;
    pcmd^.DataBufferOffset := @REPORT_KEY_DATA;

    REPORT_KEY_CDB.OperationCode := SCSIOP_REPORT_KEY;
    REPORT_KEY_CDB.KeyClass := $00;
    REPORT_KEY_CDB.AllocationLength := SizeOf(_REPORT_KEY_DATA_RPC_STATE);
    REPORT_KEY_CDB.AGID_KeyFormat := KEY_FORMAT_RPC_STATE; // AGID = 0;

    pcmd^.cdb[0] := REPORT_KEY_CDB.OperationCode;
    pcmd^.cdb[1] := REPORT_KEY_CDB.Reserved1;
    pcmd^.Cdb[2] := REPORT_KEY_CDB.LogicalBlockAddress[2];
    pcmd^.Cdb[3] := REPORT_KEY_CDB.LogicalBlockAddress[3];
    pcmd^.Cdb[4] := REPORT_KEY_CDB.LogicalBlockAddress[4];
    pcmd^.Cdb[5] := REPORT_KEY_CDB.LogicalBlockAddress[5];
    pcmd^.Cdb[6] := REPORT_KEY_CDB.Reserved2;
    pcmd^.Cdb[7] := REPORT_KEY_CDB.KeyClass;
    pcmd^.Cdb[8] := LoByte(REPORT_KEY_CDB.AllocationLength);
    pcmd^.Cdb[9] := HiByte(REPORT_KEY_CDB.AllocationLength);
    pcmd^.Cdb[10] := REPORT_KEY_CDB.AGID_KeyFormat;
    pcmd^.Cdb[11] := REPORT_KEY_CDB.Control;

    if DeviceIoControl(hDevice,
                       IOCTL_SCSI_PASS_THROUGH_DIRECT,
                       pcmd,
                       SizeOf(SCSI_PASS_THROUGH_DIRECT),
                       pcmd,
                       SizeOf(SCSI_PASS_THROUGH_DIRECT),
                       rb,
                       nil)
    then begin
      Drive[i].DVDFeature.User_changes := REPORT_KEY_DATA.RPC_State and $07;
      Drive[i].DVDFeature.Vendor_resets := (REPORT_KEY_DATA.RPC_State shr 3) and $07;
      Drive[i].DVDFeature.Type_code := REPORT_KEY_DATA.RPC_State shr 6;
      Drive[i].DVDFeature.Region_mask := REPORT_KEY_DATA.Region_Mask;
      Drive[i].DVDFeature.RPC_scheme := REPORT_KEY_DATA.RPC_Scheme;
    end
    else
      ShowMessage(GetStatus);
  end;
  CloseHandle(hDevice);
end;
Die Fehlermeldung lautet: "Falscher Parameter."
Angehängte Dateien
Dateityp: 7z dvdregion_184.7z (183,9 KB, 5x aufgerufen)
Gruss Garfield
Ubuntu 22.04: Laz2.2.2/FPC3.2.2 - VirtBox6.1+W10: D7PE, DXE5Prof
  Mit Zitat antworten Zitat