📄 isoimage.pas
字号:
{-----------------------------------------------------------------------------
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 + -