⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isoimage.pas

📁 用于CD/DVD烧录的Delphi源码,包括source和demo
💻 PAS
📖 第 1 页 / 共 4 页
字号:
{-----------------------------------------------------------------------------
 Unit Name: ISOImage
 Author:    Paul Fisher , Andrew Semack
 Purpose:   ISO9660 create and edit class
 History:
-----------------------------------------------------------------------------}

unit ISOImage;

interface

uses
  CustomImage, Math, CovertFuncs, SysUtils, windows, ComCtrls, Classes,
    DeviceTypes,
  ISO9660ClassTypes, ISO9660BootClass, ISO9660PrimaryVolClass,
    ISO9660SupplementVolClass,
  ISO9660streamHandler, ISO9660ImageTree;

type
  TISOImage = class(TCustomImage)
  private
    FOnISOStatus: TCDStatusEvent;
    FFileName: string;
    FVolID: string;
    procedure GetImageData(const ALength: Cardinal);
  protected
    FImage: TImageStreamHandler;
    FISOHeader: TISOHeader;
    FBRClass: TBootRecordVolumeDescriptor;
    FPVDClass: TPrimaryVolumeDescriptor;
    FSVDClass: TSupplementaryVolumeDescriptor;
    FVDSTClass: TVolumeDescriptorSetTerminator;
    FTree: TImageTree;
    procedure SetVolID(VolName: string);
    procedure CreateVolumeDescriptors;
    procedure Log(const AFunction, AMessage: string);
    function ParseDirectory(const AUsePrimaryVD: Boolean = True): Boolean;
    function ParseDirectorySub(AParentDir: TDirectoryEntry; const AFileName:
      string; var ADirectoryEntry: PDirectoryRecord): Boolean;
    procedure WriteStructureTree(Primary: Boolean; ISOStream:
      TImageStreamHandler; ADirEntry: TDirectoryEntry);
    procedure WriteRootStructureTree(Primary: Boolean; ISOStream:
      TImageStreamHandler; ADirEntry: TDirectoryEntry);
    procedure WriteFileData(ISOStream: TImageStreamHandler; ADirEntry:
      TDirectoryEntry);
    procedure WritePathTableData(ISOStream: TImageStreamHandler; CurrentPointer:
      Integer);
    procedure WriteJolietPathTableData(ISOStream: TImageStreamHandler;
      CurrentPointer: Integer);
  public
    constructor Create;
    destructor Destroy; override;
    function OpenImage: Boolean;
    function SaveImageToDisk(Mode: Integer): Boolean;
    function SaveDVDImageToDisk: Boolean;
    function ParsePathTable(ATreeView: TTreeView = nil): Boolean;
    function ExtractFile(const AFileEntry: TFileEntry; const AFileName: string):
      Boolean;
    function CloseImage: Boolean;
  published
    property OnISOStatus: TCDStatusEvent read FOnISOStatus write FOnISOStatus;
    property Filename: string read FFileName write FFileName;
    property Structure: TImageTree read FTree;
    property Volume_ID: string read FVolID write SetVolID;
    property BootRecordVolumeDescriptor: TBootRecordVolumeDescriptor read
      FBRClass write FBRClass;
    property PrimaryVolumeDescriptor: TPrimaryVolumeDescriptor read FPVDClass
      write FPVDClass;
    property SupplementaryVolumeDescriptor: TSupplementaryVolumeDescriptor read
      FSVDClass write FSVDClass;
  end;

implementation

constructor TISOImage.Create;
begin
  inherited Create;
  FFileName := '';
  FImage := nil;
  FPVDClass := nil;
  FSVDClass := nil;
  FBRClass := nil;
  ImageType := IT9660Image;
  FTree := TImageTree.Create;
  CreateVolumeDescriptors; // does this need to be moved ??
end;

destructor TISOImage.Destroy;
begin
  if (Assigned(FTree)) then
    FreeAndNil(FTree);
  if (Assigned(FImage)) then
    FreeAndNil(FImage);
  if (Assigned(FPVDClass)) then
    FreeAndNil(FPVDClass);
  if (Assigned(FSVDClass)) then
    FreeAndNil(FSVDClass);
  if (Assigned(FBRClass)) then
    FreeAndNil(FBRClass);
  inherited;
end;

function TISOImage.CloseImage: Boolean;
begin
  FFileName := '';
  if Assigned(FImage) then
    FreeAndNil(FImage);
  if Assigned(FPVDClass) then
    FreeAndNil(FPVDClass);
  if Assigned(FSVDClass) then
    FreeAndNil(FSVDClass);
  if Assigned(FBRClass) then
    FreeAndNil(FBRClass);
  if Assigned(FTree) then
    FreeAndNil(FTree);
  Result := True;
end;

procedure TISOImage.SetVolID(VolName: string);

begin
  FVolID := VolName;
  if (Assigned(fPVDClass)) then
      fPVDClass.VolumeIdentifier := VolName;
  if (Assigned(fSVDClass)) then
      fSVDClass.VolumeIdentifier := VolName;
end;

procedure TISOImage.GetImageData(const ALength: Cardinal);
var
  OrgPtr,
    Buffer: PByte;
  Row: Cardinal;
  Col: Word;
  CharStr,
    DumpStr: string;
begin
  GetMem(Buffer, ALength);
  OrgPtr := Buffer;
  try
    FImage.Stream.ReadBuffer(Buffer^, ALength);

    for Row := 0 to ((ALength - 1) div 16) do
    begin
      DumpStr := IntToHex(Cardinal(fImage.Stream.Position) - ALength + Row * 16,
        8) + 'h | ';
      CharStr := '';
      for Col := 0 to Min(16, ALength - (Row + 1) * 16) do
      begin
        DumpStr := DumpStr + IntToHex(Buffer^, 2) + ' ';
        if (Buffer^ > 32) then
          CharStr := CharStr + Chr(Buffer^)
        else
          CharStr := CharStr + ' ';
        Inc(Buffer);
      end;
      DumpStr := DumpStr + StringOfChar(' ', 61 - Length(DumpStr)) + '| ' +
        CharStr;
      Log('Dump', DumpStr);
    end;
  finally
    FreeMem(OrgPtr, ALength);
  end;
end;

function TISOImage.ExtractFile(const AFileEntry: TFileEntry; const AFileName:
  string): Boolean;
var
  lFStream: TFileStream;
  lFSize: Int64;
  lBuffer: Pointer;
begin
  Result := False;

  if Assigned(AFileEntry) then
  begin
    fImage.SeekSector(AFileEntry.ISOData.LocationOfExtent.LittleEndian);
    lFStream := TFileStream.Create(AFileName, fmCreate);
    lFSize := AFileEntry.ISOData.DataLength.LittleEndian;
    GetMem(lBuffer, fImage.SectorDataSize);
    try
      while (lFSize > 0) do
      begin
        fImage.ReadSector_Data(lBuffer^, fImage.SectorDataSize);
        lFStream.WriteBuffer(lBuffer^, Min(lFSize, fImage.SectorDataSize));
        Dec(lFSize, fImage.SectorDataSize);
      end;
      Result := True;
    finally
      lFStream.Free;
      FreeMem(lBuffer, fImage.SectorDataSize);
    end;
  end;
end;


procedure TISOImage.Log(const AFunction, AMessage: string);
begin
  if Assigned(OnISOStatus) then
    OnISOStatus(AFunction + ' : ' + AMessage);
end;

function TISOImage.OpenImage: Boolean;
var
  VD: TVolumeDescriptor;
  Primary : Boolean;
  TempStr : String;
begin
  Result := False;
  Primary := True;
  if (FileExists(FFileName)) then
  begin
    fImage := TImageStreamHandler.Create(FFileName, ifAuto);
    Log('OpenImage', 'file "' + FFileName + '" opened...');
    fImage.SeekSector(16);
    if (fImage.ImageFormat = ifCompleteSectors) then
      Log('OpenImage', 'image contains RAW data')
    else if (fImage.ImageFormat = ifOnlyData) then
      Log('OpenImage', 'image contains sector data');

    if (fImage.ISOBookFormat = ybfMode1) then
      Log('OpenImage', 'image contains yellow book mode 1 data')
    else if (fImage.ISOBookFormat = ybfMode2) then
      Log('OpenImage', 'image contains yellow book mode 2 data');

    Log('OpenImage', 'user data sector size is ' +
      IntToStr(fImage.SectorDataSize) + ' bytes');
    Log('OpenImage', 'image data offset in image file is ' +
      IntToStr(fImage.ImageOffset) + ' bytes');

    if (fImage.SectorDataSize <> 2048) then
    begin
      Log('OpenImage',
        'sorry, but sector size other than 2048 bytes are not yet supported...');
      Exit;
    end;

    repeat
      FImage.ReadSector_Data(VD, SizeOf(TVolumeDescriptor));

      case Byte(VD.DescriptorType) of
        vdtBR:
          begin
            Log('OpenImage', 'Boot Record Volume Descriptor found');
              // Boot Record VD

            if (Assigned(fBRClass)) then // newer PVD
              fBRClass.Free;
            fBRClass := TBootRecordVolumeDescriptor.Create(VD);
          end;
        vdtPVD:
          begin
            Log('OpenImage', 'Primary Volume Descriptor found');

            if (Assigned(fPVDClass)) then // newer PVD
              fPVDClass.Free;
            fPVDClass := TPrimaryVolumeDescriptor.Create(VD);
            FVolID := fPVDClass.VolumeIdentifier;
          end;
        vdtSVD:
          begin
            Log('OpenImage', 'Supplementary Volume Descriptor found');
              // Supplementary Volume Descriptor

            if (Assigned(fSVDClass)) then // newer SVD
              fSVDClass.Free;
            fSVDClass := TSupplementaryVolumeDescriptor.Create(VD);
            TempStr := fSVDClass.VolumeIdentifier;
            FVolID := UnicodeToStr(TempStr);
            Primary := False;
          end;
      end;
    until (VD.DescriptorType = vdtVDST);

    ParseDirectory(Primary); // use primary Vol Disc
    Result := True;
  end
  else
  begin
    Log('OpenImage', 'file "' + FFileName + '" not found');
  end;
end;


procedure TISOImage.CreateVolumeDescriptors;
begin
  Log('CreateImage', 'ISO Header Created'); // ISO Header 32k of 0
  FillChar(FISOHeader, SizeOf(FISOHeader), Char(0));

  Log('CreateImage', 'Boot Record Volume Descriptor Created'); // Boot Record VD
  if (Assigned(fBRClass)) then
    fBRClass.Free;
  FBRClass := TBootRecordVolumeDescriptor.Create;

  Log('CreateImage', 'Primary Volume Descriptor Created');
    // Primary Volume Descriptor
  if (Assigned(fPVDClass)) then
    fPVDClass.Free;
  FPVDClass := TPrimaryVolumeDescriptor.Create;

  Log('CreateImage', 'Supplementary Volume Descriptor Created');
    // Supplementary Volume Descriptor
  if (Assigned(FSVDClass)) then
    FSVDClass.Free;
  FSVDClass := TSupplementaryVolumeDescriptor.Create;

  Log('CreateImage', 'Volume Descriptor Set Terminator Created');
    // Volume Descriptor Set Terminator
  FillChar(FVDSTClass, SizeOf(FVDSTClass), Char(0));

  FVDSTClass.VolumeDescriptorType := vdtVDST;
  FVDSTClass.StandardIdentifier := ISO_STANDARD_ID;
  FVDSTClass.VolumeDescriptorVersion := 1;
end;

procedure TISOImage.WriteRootStructureTree(Primary: Boolean; ISOStream:
  TImageStreamHandler; ADirEntry: TDirectoryEntry);
var
  DirIndex, FileIndex, Padd: Integer;
  Dir: TDirectoryEntry;
  RootDir: TRootDirectoryrecord;
  Fil: TFileEntry;
  TempPchar: PChar;
  TempPWideChr: PWideChar;
  PadByte, FileID: Byte;
  FillBlock: array[0..2047] of Byte;
  WideArray: array[0..127] of byte;
  CurrentLBA, StreamPos, PadIndex: Integer;
  DIRRecSize: Integer;
  Sector: Integer;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -