Pliki *.iso

0

Witam wszystkich

Czy ktoś już się tym bawił ?
Konkretnie chodzi mi o to, aby z pliku *.iso wyciągnąć jeden pliczek.
Jakoś nie mogę znaleźć nic konkretnego.
Próbowałem za pomocą unrar.exe, ale ten krzyczy, że nie jest to archiwum rara.

Wszelki wskazówki mile widziane.

Pozdrawiam.

0
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.

Poszperaj tutaj coś.
Więcej:
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_23850889.html

0

Serdeczne dzięki [browar]

0

A czy mógłbyś zarzucić jakiś mały przykładzik użycia tych funkcji ?
Czy udało się Tobie to jakoś uruchomić?

Niestety nie można nic z tym zrobić :(
Do tego jest też przykład użycia :

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;

Niestety, tak samo jak w linku powyżej, dostajemy "Stack Overflow";

Poprawiony unit bez rekurencji :

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.

Błędu już nie ma, ale niestety nie zwraca nic :(

0

Czyżby nikt już więcej nie potrafił pomóc :(

1 użytkowników online, w tym zalogowanych: 0, gości: 1