Reading ISO files.

Hi

I need to read the root directory of an ISO file, and detect if it's an DVD or a CD. Anyone can help with this ?
tadzio_blahAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

TECH_NETCommented:
Use MagicISO s.w

Check this link:
http://www.magiciso.com/tutorials/miso-burnwin.htm
0
tadzio_blahAuthor Commented:
um... this is the programming/delphi zone of EE, so as you can imagine I don't want to know what apps can do that (i know a lot of those, IMO a lot better than magicISO)... i need a code that can do that
0
TECH_NETCommented:
I would have recommended using clonedvd but i figured that CloneCD detect CD iso images as DVD
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

TECH_NETCommented:
sorry, my bad...
0
tadzio_blahAuthor Commented:
...anyways... can anyone post some DELPHI CODE that i can use (or a unit that handles ISO files), and NOT an app name ?
0
Dagan HooverDeveloperCommented:
Your in luck. I was just doing something along these lines.  Unfortunately I don't know how to differentiate between DVD's and CD's. But you can get a list of all files, directories, and their size/location with the code below.


unit uISO;
 
interface
 
uses
  Windows, Sysutils, Math;
 
type
  PDirectoryRecord = ^TDirectoryRecord;
  TDirectoryRecord = packed record
    DirectoryLength   : Byte;
    XARLength         : Byte;
    ExtentLocation    : LongWord;
    ExtentLocationBE  : LongWord;
    DataLength        : LongWord;
    DataLengthBE      : LongWord;
    DateTime          : Array[0..6] Of Byte;
    FileFlags         : Byte;
    FileUnitSize      : Byte;
    InterleaveGapSize : Byte;
    ValueSequenceNum  : LongWord;
    FileNameLength    : Byte;
    FileName          : Array[0..255] Of Char;
  end;
  TDirectoryArrayRecord = Array Of TDirectoryRecord;
  PSearchFilter = ^TSearchFilter;
  TSearchFilter = record
    Flags    : LongWord;
    Name     : Array[0..255] Of Char;
    lwType   : LongWord;
    Size     : LongWord;
    SizeType : LongWord;
    Data     : Pointer;
    DataSize : LongWord;
  end;
 
const
  SECTOR_SIZE          = 2048;
  ISO_FLAG_FILE        = $00;
  ISO_FLAG_EXISTENCE   = $01;
  ISO_FLAG_DIRECTORY   = $02;
  ISO_FLAG_ASSOCIATED  = $04;
  ISO_FLAG_RECORD      = $08;
  ISO_FLAG_PROTECTION  = $10;
  ISO_FLAG_MULTIEXTENT = $80;
  FILTER_BY_NAME       = $01;
  FILTER_BY_TYPE       = $02;
  FILTER_BY_SIZE       = $04;
  FILTER_BY_DATA       = $08;
  SIZE_EQUAL           = $00;
  SIZE_GREATER         = $01;
  SIZE_LOWER           = $02;
 
function ISOSearchFiles(ISOFile: Cardinal; Output: TDirectoryArrayRecord; Max: Integer; Filter: PSearchFilter; Start: Integer = 0): Integer;
 
implementation
 
function PosLen(SubStr, Str: PChar; Length: Integer): Bool;
begin
  Result := Not(CompareMem(SubStr,Str,Length));
end;
 
function ISOScanFiles(ISOFile: Cardinal; Output: TDirectoryArrayRecord; Max: Integer; Filter: PSearchFilter; I: Integer): Integer;
var
  DR : TDirectoryRecord;
  fPointer : Cardinal;
  Add : Integer;
  OldDirLen : Cardinal;
  BytesRead : Cardinal;
  Data : PByte;
begin
  OldDirLen := 0;
  fPointer := SetFilePointer(ISOFile,0,nil,FILE_CURRENT);
  While True Do
    begin
    FillChar(DR,SizeOf(TDirectoryRecord),0);
    ReadFile(ISOFile,DR,SizeOf(TDirectoryRecord),BytesRead,nil);
    If DR.DirectoryLength = 0 Then
      begin
      If (SECTOR_SIZE - (fPointer mod SECTOR_SIZE)) <= OldDirLen Then
        begin
        Inc(fPointer,SECTOR_SIZE - (fPointer mod SECTOR_SIZE));
        SetFilePointer(ISOFile,fPointer,nil,FILE_BEGIN);
        ReadFile(ISOFile,DR,SizeOf(TDirectoryRecord),BytesRead,nil);
        If DR.DirectoryLength = 0 Then Break;
      end
      Else
        begin
        Break;
      end;
    end;
    If (DR.FileName[1] <> #0) And (DR.FileName[1] <> #1) Then
      begin
      Add := 1;
      If Filter <> nil Then
        begin
        If (Filter^.Flags And FILTER_BY_NAME) <> 0 Then
          begin
          If PosLen(PChar(String(DR.FileName)),PChar(String(Filter^.Name)),Filter^.DataSize) Then
            begin
            Add := 0;
          end;
        end;
        If (Filter^.Flags And FILTER_BY_TYPE) <> 0 Then
          begin
          If (Filter^.lwType = ISO_FLAG_FILE) And ((DR.FileFlags And ISO_FLAG_DIRECTORY) <> 0) Then
            begin
            Add := 0;
          end
          Else If (Filter^.lwType = ISO_FLAG_DIRECTORY) And Not((DR.FileFlags And ISO_FLAG_DIRECTORY) <> 0) Then
            begin
            Add := 0;
          end;
        end;
        If (Filter^.Flags And FILTER_BY_SIZE) <> 0 Then
          begin
          If (Filter^.SizeType = SIZE_EQUAL) And (DR.DataLength <> Filter^.Size) Then
            begin
            Add := 0;
          end
          Else If (Filter^.SizeType = SIZE_GREATER) And (DR.DataLength <= Filter^.Size) Then
            begin
            Add := 0;
          end
          Else If (Filter^.SizeType = SIZE_LOWER) And (DR.DataLength >= Filter^.Size) Then
            begin
            Add := 0;
          end;
        end
        Else If (Filter^.Flags And FILTER_BY_DATA) <> 0 Then
          begin
          Data := AllocMem(Filter^.DataSize);
          SetFilePointer(ISOFile,DR.ExtentLocation * SECTOR_SIZE,nil,FILE_BEGIN);
          ReadFile(ISOFile,Data^,Filter^.DataSize,BytesRead,nil);
          If Not(CompareMem(Data,Filter^.Data,Filter^.DataSize)) Then
            begin
            Add := 0;
          end;
        end;
      end;
      If (DR.FileFlags And ISO_FLAG_DIRECTORY) <> 0 Then
        begin
        SetFilePointer(ISOFile,DR.ExtentLocation * SECTOR_SIZE,nil,FILE_BEGIN);
        I := ISOScanFiles(ISOFile,Output,Max,Filter,I);
      end;
      If I = Max Then Break;
      If (Add <> 0) And(DR.DataLength <> 0) Then
        begin
        Output[I] := DR;
        Inc(I);
      end;
    end;
    Inc(fPointer,DR.DirectoryLength);
    OldDirLen := DR.DirectoryLength;
    SetFilePointer(ISOFile,fPointer,nil,FILE_BEGIN);
  end;
  Result := I;
end;
 
function ISOSearchFiles(ISOFile: Cardinal; Output: TDirectoryArrayRecord; Max: Integer; Filter: PSearchFilter; Start: Integer = 0): Integer;
var
  DR : TDirectoryRecord;
  BytesRead : Cardinal;
begin
  SetFilePointer(ISOFile,(16 * SECTOR_SIZE) + 156,nil,FILE_BEGIN);
  ReadFile(ISOFile,DR,SizeOf(TDirectoryRecord),BytesRead,nil);
  SetFilePointer(ISOFile,DR.ExtentLocation * SECTOR_SIZE,nil,FILE_BEGIN);
  Result := ISOScanFiles(ISOFile,Output,Max,Filter,Start);
end;
 
end.

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Dagan HooverDeveloperCommented:
Here's an example on how to use it. It gets some data from the file named param.sfo inside the iso.
function TfrmMain.LoadISOName(FileName: String): String;
var
  ISOFile : Cardinal;
  Files : TDirectoryArrayRecord;
  Filter : TSearchFilter;
  FilesFound : Cardinal;
  Offset : Cardinal;
  Size : Cardinal;
  BytesRead : Cardinal;
  Buffer : Array Of Char;
  ISOName : String;
  I,
  Max : Integer;
begin
  Result := '';
  ISOFile := CreateFile(PChar(FileName),GENERIC_READ,0,nil,OPEN_EXISTING,0,0);
  If ISOFile = INVALID_HANDLE_VALUE Then Exit;
  Try
    SetLength(Files,1);
    FillChar(Filter,SizeOf(TSearchFilter),0);
    Filter.Flags := FILTER_BY_NAME;
    Filter.lwType := ISO_FLAG_FILE;
    Filter.Name := 'PARAM.SFO';
    Filter.DataSize := 9;
    FilesFound := ISOSearchFiles(ISOFile,Files,1,@Filter);
    If FilesFound = 0 Then Exit;
    Offset := Files[0].ExtentLocation * SECTOR_SIZE;
    Size := Files[0].DataLength;
    If Size > 0 Then
      begin
      SetLength(Buffer,Size);
      SetFilePointer(ISOFile,Offset,nil,FILE_BEGIN);
      ReadFile(ISOFile,Buffer[0],Size,BytesRead,nil);
      ISOName := Copy(String(Buffer),$159,255);
      ISOName := Copy(ISOName,1,Pos(#0,ISOName) - 1);
      I := 1;
      Max := Length(ISOName);
      While I <= Max Do
        begin
        If Not(ISOName[I] in ['a'..'z','A'..'Z','0'..'9','-','+','.',' ']) Then
          begin
          Delete(ISOName,I,1);
          Dec(Max);
        end
        Else
          begin
          Inc(I);
        end;
      end;
      Result := ISOName;
    end;
  Finally
    CloseHandle(ISOFile);
  end;
end;

Open in new window

0
tadzio_blahAuthor Commented:
i'm getting stack overflow in the ISOScanFiles function.
0
tadzio_blahAuthor Commented:
the stack overflow error surfaces when the searched file is not in the iso. (i've tried it with an iso that contained just 49 files and 2 dirs, and also with one that contained couple thousand files - so it's not the file count that produces the error).
0
Dagan HooverDeveloperCommented:
Have you stepped through the code to find exactly where it's coming from? Because I've used this on iso files that are missing the searched file.
0
tadzio_blahAuthor Commented:
most likely it's this line:

  While True Do
    begin
    FillChar(DR,SizeOf(TDirectoryRecord),0);
>>>    ReadFile(ISOFile,DR,SizeOf(TDirectoryRecord),BytesRead,nil);
    If DR.DirectoryLength = 0 Then

in ISOScanFiles. I think it's trying to read beyond the directory contents until it finds the correct file name (just a suggestion, hanen't had the time to properly step it).
0
Dagan HooverDeveloperCommented:
That wouldn't give you a stack overflow error. If the ReadFile fails, then the DR.DirectoryLength would be 0 because we initialized the DR variable that way. In that case the infinite loop fails. You should step through it or use a logging device inside the function(Log event results and find out where it last gets to before fail).
0
tadzio_blahAuthor Commented:
i've stepped throught 200 repeats (don't have the patience to do more) of that while loop, and i've used iso with 49 files and 2 directories - are those 200 repeats normal with that small amount of files/dirs ?
0
tadzio_blahAuthor Commented:
sorry, by loops i meant recursive executions of ISOScanFiles, as after 200 it didn't even start to come back from the recursion.
0
tadzio_blahAuthor Commented:
since, i need to only look for the file in the root dir of the iso i've shortened your code a little.
now it doesn't produce the exception (that's not a surprise since i've removed the recursive part).
nevertheless, there's something wrong with the recirsion in your code.
unit uISO;
 
interface
 
uses
  Windows, Sysutils, Math, StrUtils;
 
type
  PDirectoryRecord = ^TDirectoryRecord;
  TDirectoryRecord = packed record
    DirectoryLength   : Byte;
    XARLength         : Byte;
    ExtentLocation    : LongWord;
    ExtentLocationBE  : LongWord;
    DataLength        : LongWord;
    DataLengthBE      : LongWord;
    DateTime          : Array[0..6] Of Byte;
    FileFlags         : Byte;
    FileUnitSize      : Byte;
    InterleaveGapSize : Byte;
    ValueSequenceNum  : LongWord;
    FileNameLength    : Byte;
    FileName          : Array[0..255] Of Char;
  end;
  TDirectoryArrayRecord = Array Of TDirectoryRecord;
  PSearchFilter = ^TSearchFilter;
  TSearchFilter = record
    Flags    : LongWord;
    Name     : Array[0..255] Of Char;
    lwType   : LongWord;
    Size     : LongWord;
    SizeType : LongWord;
    Data     : Pointer;
    DataSize : LongWord;
  end;
 
const
  SECTOR_SIZE          = 2048;
  ISO_FLAG_FILE        = $00;
  ISO_FLAG_EXISTENCE   = $01;
  ISO_FLAG_DIRECTORY   = $02;
  ISO_FLAG_ASSOCIATED  = $04;
  ISO_FLAG_RECORD      = $08;
  ISO_FLAG_PROTECTION  = $10;
  ISO_FLAG_MULTIEXTENT = $80;
  FILTER_BY_NAME       = $01;
 
function ISOSearchFiles(ISOFile: Cardinal; Output: TDirectoryArrayRecord; Max: Integer; Start: Integer = 0): Integer;
 
implementation
 
function PosLen(SubStr, Str: PChar; Length: Integer): Bool;
begin
  Result := Not(CompareMem(SubStr,Str,Length));
end;
 
function ISOScanFiles(ISOFile: Cardinal; Output: TDirectoryArrayRecord; Max: Integer; i: integer) : integer;
var
  DR : TDirectoryRecord;
  fPointer : Cardinal;
  Add : Integer;
  OldDirLen : Cardinal;
  BytesRead : Cardinal;
 
begin
  OldDirLen := 0;
  fPointer := SetFilePointer(ISOFile, 0, nil, FILE_CURRENT);
  while True do
    begin
      FillChar(DR, SizeOf(TDirectoryRecord), 0);
      ReadFile(ISOFile, DR, SizeOf(TDirectoryRecord), BytesRead, nil);
      if (DR.DirectoryLength = 0) then
        begin
          if ((SECTOR_SIZE - (fPointer mod SECTOR_SIZE)) <= OldDirLen) then
            begin
              fPointer := fPointer + (SECTOR_SIZE - (fPointer mod SECTOR_SIZE));
              SetFilePointer(ISOFile, fPointer, nil, FILE_BEGIN);
              ReadFile(ISOFile, DR, SizeOf(TDirectoryRecord), BytesRead, nil);
              if (DR.DirectoryLength = 0) then Break;
            end
          else
            Break;
        end;
      if ((DR.FileName[1] <> #0) AND (DR.FileName[1] <> #1)) then
        begin
          Add := 1;
          if not(ContainsText(string(DR.FileName), 'system.cnf')) then Add := 0;
          if (i = Max) then Break;
          if ((Add <> 0) AND (DR.DataLength <> 0)) then
            begin
              Output[i] := DR;
              i := i + 1;
            end;
        end;
    fPointer := fPointer + DR.DirectoryLength;
    OldDirLen := DR.DirectoryLength;
    SetFilePointer(ISOFile, fPointer, nil, FILE_BEGIN);
  end;
  Result := i;
end;
 
function ISOSearchFiles(ISOFile: Cardinal; Output: TDirectoryArrayRecord; Max: Integer; Start: integer = 0): integer;
var
  DR : TDirectoryRecord;
  BytesRead : Cardinal;
 
begin
  SetFilePointer(ISOFile, (16 * SECTOR_SIZE) + 156, nil, FILE_BEGIN);
  ReadFile(ISOFile, DR, SizeOf(TDirectoryRecord), BytesRead, nil);
  SetFilePointer(ISOFile, DR.ExtentLocation * SECTOR_SIZE, nil, FILE_BEGIN);
  Result := ISOScanFiles(ISOFile, Output, Max, Start);
end;
 
end.

Open in new window

0
Dagan HooverDeveloperCommented:
The iso's I'm dealing with might be a tad different from yours. But the code works for me. With your modification does it now work for you?
0
tadzio_blahAuthor Commented:
yes, it works. maybe some time later i'll try to find out what's wrong with the recursion.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.