Ho to read ISO 9660 in Delphi?

562 Views Asked by At

I'm currently working on a project and need to know when a DVD was burned (Date of day that DVD was burned). As far as I searched and looked for, found out all data like this are following ISO 9660 format, but I couldn't find how to access or read it, also tried some component packs and libraries related, but none of them was working as i expected and needed.

also found this link: How to find out when a disc (DVD) has been written/burned? but I couldn't find a way to use them in Delphi. How its working?

2

There are 2 best solutions below

9
LU RD On BEST ANSWER

Following the link to this answer: How to find out when a disc (DVD) has been written/burned? gives where to read the date and time information on the disk:

Reading 16 characters plus one additional byte starting with position 33582 gives the DVD creation time as:

YYYYMMDDHHMMSSCCO

where CC are centiseconds and O is the offset from GMT in 15 minute intervals, stored as an 8-bit integer (two's complement representation).

Following code can be used to read (see also How to read raw block from an USB storage device with Delphi?):

function GetDVDCreationDate: String;
// Sector size is 2048 on ISO9660 optical data discs
const
  sector_size = 2048;
  rdPos = (33582 DIV sector_size);  // 33582
  rdOfs = (33582 MOD sector_size) - 1;
var
  RawMBR  : array [0..sector_size-1] of byte;
  btsIO   : DWORD;
  hDevice : THandle;
  i       : Integer;
  GMTofs  : ShortInt;
begin
  Result := '';
  hDevice := CreateFile('\\.\E:', GENERIC_READ,  // Select drive 
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if hDevice <> INVALID_HANDLE_VALUE then
  begin
    SetFilePointer(hDevice,sector_size * rdPos,nil,FILE_BEGIN);
    ReadFile(hDevice, RawMBR[0], sector_size, btsIO, nil);
    if (btsIO = sector_size) then begin
      for i := 0 to 15 do begin
        Result := Result + AnsiChar(RawMBR[rdOfs+i]);
      end;
      GMTofs := ShortInt(RawMBR[rdOfs+16]);  // Handle GMT offset if important
    end;
    CloseHandle(hDevice);
  end;
end;

Note that reading raw data from the disc must start on even sector size positions. For ISO 9660 disks, the sector size is 2048.

0
Armin Taghavizad On

thanks to @LU RD answer, here is his code with some very little modifications:

function GetDVDCreationDate(sectorSize:integer): String;
// Sector size is 2048 on ISO9660 optical data discs
var
  RawMBR  : array [0..2047] of byte;
  btsIO   : DWORD;
  hDevice : THandle;
  i       : Integer;
  GMTofs  : ShortInt;
  rdPos, rdOfs: integer;

begin
  rdPos := (33582 DIV sectorSize);  // 33582
  rdOfs := (33582 MOD sectorSize) - 1;

  hDevice := CreateFile('\\.\H:', GENERIC_READ,  // Select drive
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if hDevice <> INVALID_HANDLE_VALUE then
  begin
    SetFilePointer(hDevice,sectorSize * rdPos,nil,FILE_BEGIN);
    ReadFile(hDevice, RawMBR[0], sectorSize, btsIO, nil);
    for i := 0 to 15 do begin
      Result := Result + AnsiChar(RawMBR[rdOfs+i]);
    end;
    GMTofs := ShortInt(RawMBR[rdOfs+16]);  // Handle GMT offset if important
    CloseHandle(hDevice);
  end;
end;

//------------------------------------------------------------------------------

procedure Tfrm_main.btn_creationReadClick(Sender: TObject);
begin
  memo_dataLog.Lines.Add(GetDVDCreationDate(StrToInt(edit_sSize.Text)))
end;