mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-07-08 18:06:41 +00:00
Fix major issues in IS-CAB
This commit is contained in:
@@ -17,12 +17,14 @@ namespace SabreTools.Data.Models.InstallShieldCabinet
|
||||
/// <summary>
|
||||
/// Size of the expanded data
|
||||
/// </summary>
|
||||
public uint ExpandedSize { get; set; }
|
||||
/// <remarks>32-bit in versions 5 and below</remarks>
|
||||
public ulong ExpandedSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the compressed data
|
||||
/// </summary>
|
||||
public uint CompressedSize { get; set; }
|
||||
/// <remarks>32-bit in versions 5 and below</remarks>
|
||||
public ulong CompressedSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Attributes (junk2)
|
||||
@@ -54,26 +56,51 @@ namespace SabreTools.Data.Models.InstallShieldCabinet
|
||||
/// </summary>
|
||||
public uint LanguageOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Language
|
||||
/// </summary>
|
||||
public string Language { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Offset to the HTTP location
|
||||
/// </summary>
|
||||
public uint HTTPLocationOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// HTTP location
|
||||
/// </summary>
|
||||
public string HTTPLocation { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Offset to the FTP location
|
||||
/// </summary>
|
||||
public uint FTPLocationOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FTP location
|
||||
/// </summary>
|
||||
public string FTPLocation { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Misc offset
|
||||
/// </summary>
|
||||
public uint MiscOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Misc string
|
||||
/// </summary>
|
||||
public string Misc { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Offset to the target directory
|
||||
/// </summary>
|
||||
public uint TargetDirectoryOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Target directory
|
||||
/// </summary>
|
||||
public string TargetDirectory { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Overwrite setting flags
|
||||
/// </summary>
|
||||
|
||||
@@ -4,36 +4,29 @@ namespace SabreTools.Data.Models.InstallShieldCabinet
|
||||
/// TODO: Should standard and high values be combined?
|
||||
public sealed class VolumeHeader
|
||||
{
|
||||
public uint DataOffset { get; set; }
|
||||
|
||||
public uint DataOffsetHigh { get; set; }
|
||||
/// <remarks>32-bit in versions 5 and below</remarks>
|
||||
public ulong DataOffset { get; set; }
|
||||
|
||||
public uint FirstFileIndex { get; set; }
|
||||
|
||||
public uint LastFileIndex { get; set; }
|
||||
|
||||
public uint FirstFileOffset { get; set; }
|
||||
/// <remarks>32-bit in versions 5 and below</remarks>
|
||||
public ulong FirstFileOffset { get; set; }
|
||||
|
||||
public uint FirstFileOffsetHigh { get; set; }
|
||||
/// <remarks>32-bit in versions 5 and below</remarks>
|
||||
public ulong FirstFileSizeExpanded { get; set; }
|
||||
|
||||
public uint FirstFileSizeExpanded { get; set; }
|
||||
/// <remarks>32-bit in versions 5 and below</remarks>
|
||||
public ulong FirstFileSizeCompressed { get; set; }
|
||||
|
||||
public uint FirstFileSizeExpandedHigh { get; set; }
|
||||
/// <remarks>32-bit in versions 5 and below</remarks>
|
||||
public ulong LastFileOffset { get; set; }
|
||||
|
||||
public uint FirstFileSizeCompressed { get; set; }
|
||||
/// <remarks>32-bit in versions 5 and below</remarks>
|
||||
public ulong LastFileSizeExpanded { get; set; }
|
||||
|
||||
public uint FirstFileSizeCompressedHigh { get; set; }
|
||||
|
||||
public uint LastFileOffset { get; set; }
|
||||
|
||||
public uint LastFileOffsetHigh { get; set; }
|
||||
|
||||
public uint LastFileSizeExpanded { get; set; }
|
||||
|
||||
public uint LastFileSizeExpandedHigh { get; set; }
|
||||
|
||||
public uint LastFileSizeCompressed { get; set; }
|
||||
|
||||
public uint LastFileSizeCompressedHigh { get; set; }
|
||||
/// <remarks>32-bit in versions 5 and below</remarks>
|
||||
public ulong LastFileSizeCompressed { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ namespace SabreTools.Serialization.Readers
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: Read the setup types table (SETUPTYPEHEADER and SETUPTYPEDESC)
|
||||
|
||||
#region File Descriptor Offsets
|
||||
|
||||
// Get the file table offset
|
||||
@@ -163,7 +165,7 @@ namespace SabreTools.Serialization.Readers
|
||||
|
||||
// Create and fill the file group offsets
|
||||
cabinet.FileGroupOffsets = [];
|
||||
for (int i = 0; i < (cabinet.Descriptor.FileGroupOffsets?.Length ?? 0); i++)
|
||||
for (int i = 0; i < cabinet.Descriptor.FileGroupOffsets.Length; i++)
|
||||
{
|
||||
// Get the file group offset
|
||||
long offset = cabinet.Descriptor.FileGroupOffsets![i];
|
||||
@@ -215,17 +217,11 @@ namespace SabreTools.Serialization.Readers
|
||||
// Get the offset
|
||||
OffsetList? list = kvp.Value;
|
||||
if (list is null)
|
||||
{
|
||||
fileGroupId++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we have an invalid offset
|
||||
if (list.DescriptorOffset <= 0)
|
||||
{
|
||||
fileGroupId++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/// Seek to the file group
|
||||
data.SeekIfPossible(descriptorOffset + list.DescriptorOffset, SeekOrigin.Begin);
|
||||
@@ -234,13 +230,16 @@ namespace SabreTools.Serialization.Readers
|
||||
cabinet.FileGroups[fileGroupId++] = ParseFileGroup(data, majorVersion, descriptorOffset);
|
||||
}
|
||||
|
||||
// Order the groups by first file index
|
||||
Array.Sort(cabinet.FileGroups, (a, b) => (int)a.FirstFile - (int)b.FirstFile);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Component Offsets
|
||||
|
||||
// Create and fill the component offsets
|
||||
cabinet.ComponentOffsets = [];
|
||||
for (int i = 0; i < (cabinet.Descriptor.ComponentOffsets?.Length ?? 0); i++)
|
||||
for (int i = 0; i < cabinet.Descriptor.ComponentOffsets.Length; i++)
|
||||
{
|
||||
// Get the component offset
|
||||
long offset = cabinet.Descriptor.ComponentOffsets![i];
|
||||
@@ -292,17 +291,11 @@ namespace SabreTools.Serialization.Readers
|
||||
// Get the offset
|
||||
OffsetList? list = kvp.Value;
|
||||
if (list is null)
|
||||
{
|
||||
componentId++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we have an invalid offset
|
||||
if (list.DescriptorOffset <= 0)
|
||||
{
|
||||
componentId++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Seek to the component
|
||||
data.SeekIfPossible(descriptorOffset + list.DescriptorOffset, SeekOrigin.Begin);
|
||||
@@ -313,8 +306,6 @@ namespace SabreTools.Serialization.Readers
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: Parse setup types
|
||||
|
||||
return cabinet;
|
||||
}
|
||||
catch
|
||||
@@ -407,7 +398,7 @@ namespace SabreTools.Serialization.Readers
|
||||
// Read the display name, if possible
|
||||
if (obj.DisplayNameOffset != 0)
|
||||
{
|
||||
// Seek to the name
|
||||
// Seek to the string
|
||||
data.SeekIfPossible(descriptorOffset + obj.DisplayNameOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
@@ -420,7 +411,7 @@ namespace SabreTools.Serialization.Readers
|
||||
// Read the name, if possible
|
||||
if (obj.NameOffset != 0)
|
||||
{
|
||||
// Seek to the name
|
||||
// Seek to the string
|
||||
data.SeekIfPossible(descriptorOffset + obj.NameOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
@@ -456,7 +447,7 @@ namespace SabreTools.Serialization.Readers
|
||||
// Cache the current offset
|
||||
long preNameOffset = data.Position;
|
||||
|
||||
// Seek to the name offset
|
||||
// Seek to the string offset
|
||||
data.SeekIfPossible(descriptorOffset + nameOffset, SeekOrigin.Begin);
|
||||
|
||||
if (majorVersion >= 17)
|
||||
@@ -501,6 +492,7 @@ namespace SabreTools.Serialization.Readers
|
||||
obj.ComponentTableOffset = data.ReadUInt32LittleEndian();
|
||||
obj.Reserved5 = data.ReadUInt32LittleEndian();
|
||||
obj.Reserved6 = data.ReadUInt32LittleEndian();
|
||||
|
||||
obj.FileGroupOffsets = new uint[71];
|
||||
for (int i = 0; i < 71; i++)
|
||||
{
|
||||
@@ -569,10 +561,23 @@ namespace SabreTools.Serialization.Readers
|
||||
obj.CompressedSize = data.ReadUInt64LittleEndian();
|
||||
obj.DataOffset = data.ReadUInt64LittleEndian();
|
||||
obj.MD5 = data.ReadBytes(0x10);
|
||||
|
||||
// TODO: This is actually 3 fields
|
||||
// - DWORD dwVerMS;
|
||||
// - DWORD dwVerLS;
|
||||
// - DWORD junk1[2];
|
||||
_ = data.ReadBytes(0x10); // Skip 0x10 bytes, unknown data?
|
||||
|
||||
obj.NameOffset = data.ReadUInt32LittleEndian();
|
||||
obj.DirectoryIndex = data.ReadUInt16LittleEndian();
|
||||
|
||||
// TODO: This is actually 4 fields
|
||||
// - DWORD Attrs;
|
||||
// - WORD FatDate
|
||||
// - WORD FatTime;
|
||||
// - DWORD junk2;
|
||||
_ = data.ReadBytes(0x0C); // Skip 0x0C bytes, unknown data?
|
||||
|
||||
obj.LinkPrevious = data.ReadUInt32LittleEndian();
|
||||
obj.LinkNext = data.ReadUInt32LittleEndian();
|
||||
obj.LinkFlags = (LinkFlags)data.ReadByteValue();
|
||||
@@ -585,7 +590,7 @@ namespace SabreTools.Serialization.Readers
|
||||
// Read the name, if possible
|
||||
if (obj.NameOffset != 0)
|
||||
{
|
||||
// Seek to the name
|
||||
// Seek to the string
|
||||
data.SeekIfPossible(descriptorOffset + obj.NameOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
@@ -613,8 +618,18 @@ namespace SabreTools.Serialization.Readers
|
||||
var obj = new FileGroup();
|
||||
|
||||
obj.NameOffset = data.ReadUInt32LittleEndian();
|
||||
obj.ExpandedSize = data.ReadUInt32LittleEndian();
|
||||
obj.CompressedSize = data.ReadUInt32LittleEndian();
|
||||
|
||||
if (majorVersion <= 5)
|
||||
{
|
||||
obj.ExpandedSize = data.ReadUInt32LittleEndian();
|
||||
obj.CompressedSize = data.ReadUInt32LittleEndian();
|
||||
}
|
||||
else
|
||||
{
|
||||
obj.ExpandedSize = data.ReadUInt64LittleEndian();
|
||||
obj.CompressedSize = data.ReadUInt64LittleEndian();
|
||||
}
|
||||
|
||||
obj.Attributes = (FileGroupAttributes)data.ReadUInt16LittleEndian();
|
||||
|
||||
// TODO: Figure out what data lives in this area for V5 and below
|
||||
@@ -643,7 +658,7 @@ namespace SabreTools.Serialization.Readers
|
||||
// Read the name, if possible
|
||||
if (obj.NameOffset != 0)
|
||||
{
|
||||
// Seek to the name
|
||||
// Seek to the string
|
||||
data.SeekIfPossible(descriptorOffset + obj.NameOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
@@ -653,6 +668,71 @@ namespace SabreTools.Serialization.Readers
|
||||
obj.Name = data.ReadNullTerminatedAnsiString() ?? string.Empty;
|
||||
}
|
||||
|
||||
// Read the language, if possible
|
||||
if (obj.LanguageOffset != 0)
|
||||
{
|
||||
// Seek to the string
|
||||
data.SeekIfPossible(descriptorOffset + obj.LanguageOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
if (majorVersion >= 17)
|
||||
obj.Language = data.ReadNullTerminatedUnicodeString() ?? string.Empty;
|
||||
else
|
||||
obj.Language = data.ReadNullTerminatedAnsiString() ?? string.Empty;
|
||||
}
|
||||
|
||||
// Read the HTTP location, if possible
|
||||
if (obj.HTTPLocationOffset != 0)
|
||||
{
|
||||
// Seek to the string
|
||||
data.SeekIfPossible(descriptorOffset + obj.HTTPLocationOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
if (majorVersion >= 17)
|
||||
obj.HTTPLocation = data.ReadNullTerminatedUnicodeString() ?? string.Empty;
|
||||
else
|
||||
obj.HTTPLocation = data.ReadNullTerminatedAnsiString() ?? string.Empty;
|
||||
}
|
||||
|
||||
// Read the FTP location, if possible
|
||||
if (obj.FTPLocationOffset != 0)
|
||||
{
|
||||
// Seek to the string
|
||||
data.SeekIfPossible(descriptorOffset + obj.FTPLocationOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
if (majorVersion >= 17)
|
||||
obj.FTPLocation = data.ReadNullTerminatedUnicodeString() ?? string.Empty;
|
||||
else
|
||||
obj.FTPLocation = data.ReadNullTerminatedAnsiString() ?? string.Empty;
|
||||
}
|
||||
|
||||
// Read the target directory, if possible
|
||||
if (obj.MiscOffset != 0)
|
||||
{
|
||||
// Seek to the string
|
||||
data.SeekIfPossible(descriptorOffset + obj.MiscOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
if (majorVersion >= 17)
|
||||
obj.Misc = data.ReadNullTerminatedUnicodeString() ?? string.Empty;
|
||||
else
|
||||
obj.Misc = data.ReadNullTerminatedAnsiString() ?? string.Empty;
|
||||
}
|
||||
|
||||
// Read the target directory, if possible
|
||||
if (obj.TargetDirectoryOffset != 0)
|
||||
{
|
||||
// Seek to the string
|
||||
data.SeekIfPossible(descriptorOffset + obj.TargetDirectoryOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
if (majorVersion >= 17)
|
||||
obj.TargetDirectory = data.ReadNullTerminatedUnicodeString() ?? string.Empty;
|
||||
else
|
||||
obj.TargetDirectory = data.ReadNullTerminatedAnsiString() ?? string.Empty;
|
||||
}
|
||||
|
||||
// Seek back to the correct offset
|
||||
data.SeekIfPossible(currentPosition, SeekOrigin.Begin);
|
||||
|
||||
@@ -677,7 +757,7 @@ namespace SabreTools.Serialization.Readers
|
||||
// Cache the current offset
|
||||
long currentOffset = data.Position;
|
||||
|
||||
// Seek to the name offset
|
||||
// Seek to the string offset
|
||||
data.SeekIfPossible(descriptorOffset + obj.NameOffset, SeekOrigin.Begin);
|
||||
|
||||
// Read the string
|
||||
@@ -718,22 +798,15 @@ namespace SabreTools.Serialization.Readers
|
||||
}
|
||||
else
|
||||
{
|
||||
obj.DataOffset = data.ReadUInt32LittleEndian();
|
||||
obj.DataOffsetHigh = data.ReadUInt32LittleEndian();
|
||||
obj.DataOffset = data.ReadUInt64LittleEndian();
|
||||
obj.FirstFileIndex = data.ReadUInt32LittleEndian();
|
||||
obj.LastFileIndex = data.ReadUInt32LittleEndian();
|
||||
obj.FirstFileOffset = data.ReadUInt32LittleEndian();
|
||||
obj.FirstFileOffsetHigh = data.ReadUInt32LittleEndian();
|
||||
obj.FirstFileSizeExpanded = data.ReadUInt32LittleEndian();
|
||||
obj.FirstFileSizeExpandedHigh = data.ReadUInt32LittleEndian();
|
||||
obj.FirstFileSizeCompressed = data.ReadUInt32LittleEndian();
|
||||
obj.FirstFileSizeCompressedHigh = data.ReadUInt32LittleEndian();
|
||||
obj.LastFileOffset = data.ReadUInt32LittleEndian();
|
||||
obj.LastFileOffsetHigh = data.ReadUInt32LittleEndian();
|
||||
obj.LastFileSizeExpanded = data.ReadUInt32LittleEndian();
|
||||
obj.LastFileSizeExpandedHigh = data.ReadUInt32LittleEndian();
|
||||
obj.LastFileSizeCompressed = data.ReadUInt32LittleEndian();
|
||||
obj.LastFileSizeCompressedHigh = data.ReadUInt32LittleEndian();
|
||||
obj.FirstFileOffset = data.ReadUInt64LittleEndian();
|
||||
obj.FirstFileSizeExpanded = data.ReadUInt64LittleEndian();
|
||||
obj.FirstFileSizeCompressed = data.ReadUInt64LittleEndian();
|
||||
obj.LastFileOffset = data.ReadUInt64LittleEndian();
|
||||
obj.LastFileSizeExpanded = data.ReadUInt64LittleEndian();
|
||||
obj.LastFileSizeCompressed = data.ReadUInt64LittleEndian();
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
||||
@@ -241,11 +241,29 @@ namespace SabreTools.Wrappers
|
||||
if (!cabinet.FileIsValid(i))
|
||||
continue;
|
||||
|
||||
// Build the full path from the cabinet
|
||||
// Retrieve all output file pieces
|
||||
string filename = cabinet.GetFileName(i) ?? $"BAD_FILENAME{i}";
|
||||
uint dirIndex = cabinet.GetDirectoryIndexFromFile(i);
|
||||
string dir = cabinet.GetDirectoryName((int)dirIndex) ?? $"BAD_DIRNAME{dirIndex}";
|
||||
filename = Path.Combine(dir, filename);
|
||||
string group = cabinet.GetFileGroupNameFromFile(i) ?? $"BAD_GROUPNAME{dirIndex}";
|
||||
|
||||
// Consistently replace problematic path characters
|
||||
foreach (char c in PathReplacementCharacters)
|
||||
{
|
||||
dir = dir.Replace(c, '_');
|
||||
}
|
||||
|
||||
foreach (char c in PathReplacementCharacters)
|
||||
{
|
||||
group = group.Replace(c, '_');
|
||||
}
|
||||
|
||||
// Build the full path
|
||||
#if NET20 || NET35
|
||||
filename = Path.Combine(Path.Combine(group, dir), filename);
|
||||
#else
|
||||
filename = Path.Combine(group, dir, filename);
|
||||
#endif
|
||||
|
||||
// Ensure directory separators are consistent
|
||||
if (Path.DirectorySeparatorChar == '\\')
|
||||
@@ -253,12 +271,6 @@ namespace SabreTools.Wrappers
|
||||
else if (Path.DirectorySeparatorChar == '/')
|
||||
filename = filename.Replace('\\', '/');
|
||||
|
||||
// Consistently replace problematic path characters
|
||||
foreach (char c in PathReplacementCharacters)
|
||||
{
|
||||
filename = filename.Replace(c, '_');
|
||||
}
|
||||
|
||||
// Ensure the full output directory exists
|
||||
filename = Path.Combine(outputDirectory, filename);
|
||||
var directoryName = Path.GetDirectoryName(filename);
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace SabreTools.Wrappers
|
||||
|
||||
// Headers
|
||||
Print(builder, Model.CommonHeader, MajorVersion);
|
||||
Print(builder, Model.VolumeHeader, MajorVersion);
|
||||
Print(builder, Model.VolumeHeader);
|
||||
Print(builder, Model.Descriptor);
|
||||
|
||||
// File Descriptors
|
||||
@@ -53,42 +53,19 @@ namespace SabreTools.Wrappers
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
private static void Print(StringBuilder builder, VolumeHeader header, int majorVersion)
|
||||
private static void Print(StringBuilder builder, VolumeHeader header)
|
||||
{
|
||||
builder.AppendLine(" Volume Header Information:");
|
||||
builder.AppendLine(" -------------------------");
|
||||
if (majorVersion <= 5)
|
||||
{
|
||||
builder.AppendLine(header.DataOffset, " Data offset");
|
||||
builder.AppendLine(header.FirstFileIndex, " First file index");
|
||||
builder.AppendLine(header.LastFileIndex, " Last file index");
|
||||
builder.AppendLine(header.FirstFileOffset, " First file offset");
|
||||
builder.AppendLine(header.FirstFileSizeExpanded, " First file size expanded");
|
||||
builder.AppendLine(header.FirstFileSizeCompressed, " First file size compressed");
|
||||
builder.AppendLine(header.LastFileOffset, " Last file offset");
|
||||
builder.AppendLine(header.LastFileSizeExpanded, " Last file size expanded");
|
||||
builder.AppendLine(header.LastFileSizeCompressed, " Last file size compressed");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine(header.DataOffset, " Data offset");
|
||||
builder.AppendLine(header.DataOffsetHigh, " Data offset high");
|
||||
builder.AppendLine(header.FirstFileIndex, " First file index");
|
||||
builder.AppendLine(header.LastFileIndex, " Last file index");
|
||||
builder.AppendLine(header.FirstFileOffset, " First file offset");
|
||||
builder.AppendLine(header.FirstFileOffsetHigh, " First file offset high");
|
||||
builder.AppendLine(header.FirstFileSizeExpanded, " First file size expanded");
|
||||
builder.AppendLine(header.FirstFileSizeExpandedHigh, " First file size expanded high");
|
||||
builder.AppendLine(header.FirstFileSizeCompressed, " First file size compressed");
|
||||
builder.AppendLine(header.FirstFileSizeCompressedHigh, " First file size compressed high");
|
||||
builder.AppendLine(header.LastFileOffset, " Last file offset");
|
||||
builder.AppendLine(header.LastFileOffsetHigh, " Last file offset high");
|
||||
builder.AppendLine(header.LastFileSizeExpanded, " Last file size expanded");
|
||||
builder.AppendLine(header.LastFileSizeExpandedHigh, " Last file size expanded high");
|
||||
builder.AppendLine(header.LastFileSizeCompressed, " Last file size compressed");
|
||||
builder.AppendLine(header.LastFileSizeCompressedHigh, " Last file size compressed high");
|
||||
}
|
||||
|
||||
builder.AppendLine(header.DataOffset, " Data offset");
|
||||
builder.AppendLine(header.FirstFileIndex, " First file index");
|
||||
builder.AppendLine(header.LastFileIndex, " Last file index");
|
||||
builder.AppendLine(header.FirstFileOffset, " First file offset");
|
||||
builder.AppendLine(header.FirstFileSizeExpanded, " First file size expanded");
|
||||
builder.AppendLine(header.FirstFileSizeCompressed, " First file size compressed");
|
||||
builder.AppendLine(header.LastFileOffset, " Last file offset");
|
||||
builder.AppendLine(header.LastFileSizeExpanded, " Last file size expanded");
|
||||
builder.AppendLine(header.LastFileSizeCompressed, " Last file size compressed");
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user