mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-02-06 05:35:35 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7978cafa5 | ||
|
|
17f376c76f | ||
|
|
2774fdf158 | ||
|
|
11081efcb0 | ||
|
|
1b412c3027 | ||
|
|
73ec66e627 | ||
|
|
4ae4cd80b1 | ||
|
|
6eb27c66fc | ||
|
|
f96fd17fd3 | ||
|
|
c255a2494d | ||
|
|
86a9846300 | ||
|
|
db877d253c | ||
|
|
0acf1e3b08 | ||
|
|
362ed3a9b6 |
@@ -27,7 +27,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.6" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.8" />
|
||||
<PackageReference Include="xunit" Version="2.8.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.InstallShieldArchiveV3;
|
||||
|
||||
@@ -114,7 +115,17 @@ namespace SabreTools.Serialization.Deserializers
|
||||
/// <returns>Filled directory on success, null on error</returns>
|
||||
public static Models.InstallShieldArchiveV3.Directory? ParseDirectory(Stream data)
|
||||
{
|
||||
return data.ReadType<Models.InstallShieldArchiveV3.Directory>();
|
||||
var directory = new Models.InstallShieldArchiveV3.Directory();
|
||||
|
||||
directory.FileCount = data.ReadUInt16();
|
||||
directory.ChunkSize = data.ReadUInt16();
|
||||
|
||||
// TODO: Is there any equivilent automatic type for UInt16-prefixed ANSI?
|
||||
ushort nameLength = data.ReadUInt16();
|
||||
byte[] nameBytes = data.ReadBytes(nameLength);
|
||||
directory.Name = Encoding.ASCII.GetString(nameBytes);
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -489,7 +489,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (majorVersion >= 17)
|
||||
fileGroup.Name = data.ReadNullTerminatedUnicodeString();
|
||||
else
|
||||
fileGroup.Name = data.ReadNullTerminatedUnicodeString();
|
||||
fileGroup.Name = data.ReadNullTerminatedAnsiString();
|
||||
}
|
||||
|
||||
// Seek back to the correct offset
|
||||
|
||||
@@ -476,7 +476,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var entry = new ResidentNamesTableEntry();
|
||||
|
||||
entry.Length = data.ReadByteValue();
|
||||
if (entry.Length > 0)
|
||||
if (entry.Length > 0 && data.Position + entry.Length <= data.Length)
|
||||
{
|
||||
byte[]? name = data.ReadBytes(entry.Length);
|
||||
if (name != null)
|
||||
@@ -810,7 +810,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var entry = new ImportModuleNameTableEntry();
|
||||
|
||||
entry.Length = data.ReadByteValue();
|
||||
if (entry.Length > 0)
|
||||
if (entry.Length > 0 && data.Position + entry.Length <= data.Length)
|
||||
{
|
||||
byte[]? name = data.ReadBytes(entry.Length);
|
||||
if (name != null)
|
||||
@@ -831,7 +831,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var entry = new ImportModuleProcedureNameTableEntry();
|
||||
|
||||
entry.Length = data.ReadByteValue();
|
||||
if (entry.Length > 0)
|
||||
if (entry.Length > 0 && data.Position + entry.Length <= data.Length)
|
||||
{
|
||||
byte[]? name = data.ReadBytes(entry.Length);
|
||||
if (name != null)
|
||||
@@ -862,7 +862,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var entry = new NonResidentNamesTableEntry();
|
||||
|
||||
entry.Length = data.ReadByteValue();
|
||||
if (entry.Length > 0)
|
||||
if (entry.Length > 0 && data.Position + entry.Length <= data.Length)
|
||||
{
|
||||
byte[]? name = data.ReadBytes(entry.Length);
|
||||
if (name != null)
|
||||
|
||||
@@ -372,7 +372,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// TODO: Use marshalling here instead of building
|
||||
var residentNameTable = new List<ResidentNameTableEntry>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
while (data.Position < endOffset && data.Position < data.Length)
|
||||
{
|
||||
var entry = ParseResidentNameTableEntry(data);
|
||||
if (entry == null)
|
||||
@@ -445,7 +445,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// TODO: Use marshalling here instead of building
|
||||
var importedNameTable = new Dictionary<ushort, ImportedNameTableEntry>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
while (data.Position < endOffset && data.Position < data.Length)
|
||||
{
|
||||
ushort currentOffset = (ushort)data.Position;
|
||||
var entry = ParseImportedNameTableEntry(data);
|
||||
@@ -485,7 +485,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entryTable = new List<EntryTableBundle>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
while (data.Position < endOffset && data.Position < data.Length)
|
||||
{
|
||||
var entry = new EntryTableBundle();
|
||||
entry.EntryCount = data.ReadByteValue();
|
||||
@@ -524,7 +524,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// TODO: Use marshalling here instead of building
|
||||
var residentNameTable = new List<NonResidentNameTableEntry>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
while (data.Position < endOffset && data.Position < data.Length)
|
||||
{
|
||||
var entry = ParseNonResidentNameTableEntry(data);
|
||||
if (entry == null)
|
||||
|
||||
@@ -368,7 +368,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
record.CentralDirectorySize = data.ReadUInt32();
|
||||
record.CentralDirectoryOffset = data.ReadUInt32();
|
||||
record.FileCommentLength = data.ReadUInt16();
|
||||
if (record.FileCommentLength > 0)
|
||||
if (record.FileCommentLength > 0 && data.Position + record.FileCommentLength <= data.Length)
|
||||
{
|
||||
byte[] commentBytes = data.ReadBytes(record.FileCommentLength);
|
||||
if (commentBytes.Length != record.FileCommentLength)
|
||||
@@ -501,7 +501,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
header.ExternalFileAttributes = data.ReadUInt32();
|
||||
header.RelativeOffsetOfLocalHeader = data.ReadUInt32();
|
||||
|
||||
if (header.FileNameLength > 0)
|
||||
if (header.FileNameLength > 0 && data.Position + header.FileNameLength <= data.Length)
|
||||
{
|
||||
byte[] filenameBytes = data.ReadBytes(header.FileNameLength);
|
||||
if (filenameBytes.Length != header.FileNameLength)
|
||||
@@ -509,7 +509,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
header.FileName = Encoding.ASCII.GetString(filenameBytes);
|
||||
}
|
||||
if (header.ExtraFieldLength > 0)
|
||||
if (header.ExtraFieldLength > 0 && data.Position + header.ExtraFieldLength <= data.Length)
|
||||
{
|
||||
byte[] extraBytes = data.ReadBytes(header.ExtraFieldLength);
|
||||
if (extraBytes.Length != header.ExtraFieldLength)
|
||||
@@ -517,7 +517,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
header.ExtraField = extraBytes;
|
||||
}
|
||||
if (header.FileCommentLength > 0)
|
||||
if (header.FileCommentLength > 0 && data.Position + header.FileCommentLength <= data.Length)
|
||||
{
|
||||
byte[] commentBytes = data.ReadBytes(header.FileCommentLength);
|
||||
if (commentBytes.Length != header.FileCommentLength)
|
||||
@@ -593,7 +593,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
return null;
|
||||
|
||||
record.ExtraFieldLength = data.ReadUInt32();
|
||||
if (record.ExtraFieldLength > 0)
|
||||
if (record.ExtraFieldLength > 0 && data.Position + record.ExtraFieldLength <= data.Length)
|
||||
{
|
||||
byte[] extraBytes = data.ReadBytes((int)record.ExtraFieldLength);
|
||||
if (extraBytes.Length != record.ExtraFieldLength)
|
||||
@@ -630,7 +630,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
header.FileNameLength = data.ReadUInt16();
|
||||
header.ExtraFieldLength = data.ReadUInt16();
|
||||
|
||||
if (header.FileNameLength > 0)
|
||||
if (header.FileNameLength > 0 && data.Position + header.FileNameLength <= data.Length)
|
||||
{
|
||||
byte[] filenameBytes = data.ReadBytes(header.FileNameLength);
|
||||
if (filenameBytes.Length != header.FileNameLength)
|
||||
@@ -638,7 +638,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
header.FileName = Encoding.ASCII.GetString(filenameBytes);
|
||||
}
|
||||
if (header.ExtraFieldLength > 0)
|
||||
if (header.ExtraFieldLength > 0 && data.Position + header.ExtraFieldLength <= data.Length)
|
||||
{
|
||||
byte[] extraBytes = data.ReadBytes(header.ExtraFieldLength);
|
||||
if (extraBytes.Length != header.ExtraFieldLength)
|
||||
|
||||
@@ -668,7 +668,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
entry.CertificateType = (WindowsCertificateType)data.ReadUInt16();
|
||||
|
||||
int certificateDataLength = (int)(entry.Length - 8);
|
||||
if (certificateDataLength > 0)
|
||||
if (certificateDataLength > 0 && data.Position + certificateDataLength <= data.Length)
|
||||
entry.Certificate = data.ReadBytes(certificateDataLength);
|
||||
|
||||
attributeCertificateTable.Add(entry);
|
||||
@@ -703,7 +703,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// TODO: Use marshalling here instead of building
|
||||
var baseRelocationTable = new List<BaseRelocationBlock>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
while (data.Position < endOffset && data.Position < data.Length)
|
||||
{
|
||||
var baseRelocationBlock = new BaseRelocationBlock();
|
||||
|
||||
@@ -724,12 +724,12 @@ namespace SabreTools.Serialization.Deserializers
|
||||
totalSize += 2;
|
||||
}
|
||||
|
||||
baseRelocationBlock.TypeOffsetFieldEntries = typeOffsetFieldEntries.ToArray();
|
||||
baseRelocationBlock.TypeOffsetFieldEntries = [.. typeOffsetFieldEntries];
|
||||
|
||||
baseRelocationTable.Add(baseRelocationBlock);
|
||||
}
|
||||
|
||||
return baseRelocationTable.ToArray();
|
||||
return [.. baseRelocationTable];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -745,7 +745,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
var debugDirectoryTable = new List<DebugDirectoryEntry>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
while (data.Position < endOffset && data.Position < data.Length)
|
||||
{
|
||||
var debugDirectoryEntry = data.ReadType<DebugDirectoryEntry>();
|
||||
if (debugDirectoryEntry == null)
|
||||
@@ -1164,7 +1164,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var resourceDirectoryString = new ResourceDirectoryString();
|
||||
|
||||
resourceDirectoryString.Length = data.ReadUInt16();
|
||||
if (resourceDirectoryString.Length > 0)
|
||||
if (resourceDirectoryString.Length > 0 && data.Position + resourceDirectoryString.Length <= data.Length)
|
||||
resourceDirectoryString.UnicodeString = data.ReadBytes(resourceDirectoryString.Length * 2);
|
||||
|
||||
entry.Name = resourceDirectoryString;
|
||||
|
||||
@@ -67,7 +67,10 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
#region Archive Hashes
|
||||
|
||||
if (header?.Version == 2 && file.ExtendedHeader != null && file.ExtendedHeader.ArchiveHashLength > 0)
|
||||
if (header?.Version == 2
|
||||
&& file.ExtendedHeader != null
|
||||
&& file.ExtendedHeader.ArchiveHashLength > 0
|
||||
&& data.Position + file.ExtendedHeader.ArchiveHashLength <= data.Length)
|
||||
{
|
||||
// Create the archive hashes list
|
||||
var archiveHashes = new List<ArchiveHash>();
|
||||
@@ -218,7 +221,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Get the preload data pointer
|
||||
long preloadDataPointer = -1; int preloadDataLength = -1;
|
||||
if (directoryEntry.ArchiveIndex == HL_VPK_NO_ARCHIVE && directoryEntry.EntryLength > 0)
|
||||
if (directoryEntry.ArchiveIndex == HL_VPK_NO_ARCHIVE
|
||||
&& directoryEntry.EntryLength > 0
|
||||
&& data.Position + directoryEntry.EntryLength <= data.Length)
|
||||
{
|
||||
preloadDataPointer = directoryEntry.EntryOffset;
|
||||
preloadDataLength = (int)directoryEntry.EntryLength;
|
||||
@@ -231,7 +236,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// If we had a valid preload data pointer
|
||||
byte[]? preloadData = null;
|
||||
if (preloadDataPointer >= 0 && preloadDataLength > 0)
|
||||
if (preloadDataPointer >= 0
|
||||
&& preloadDataLength > 0
|
||||
&& data.Position + preloadDataLength <= data.Length)
|
||||
{
|
||||
// Cache the current offset
|
||||
long initialOffset = data.Position;
|
||||
|
||||
@@ -604,7 +604,11 @@ namespace SabreTools.Serialization
|
||||
#region Class resource
|
||||
|
||||
currentOffset = offset;
|
||||
ushort classResourceIdentifier = entry.Data.ReadUInt16(ref offset);
|
||||
ushort classResourceIdentifier;
|
||||
if (offset >= entry.Data.Length)
|
||||
classResourceIdentifier = 0x0000;
|
||||
else
|
||||
classResourceIdentifier = entry.Data.ReadUInt16(ref offset);
|
||||
offset = currentOffset;
|
||||
|
||||
// 0x0000 means no elements
|
||||
@@ -640,7 +644,11 @@ namespace SabreTools.Serialization
|
||||
#region Title resource
|
||||
|
||||
currentOffset = offset;
|
||||
ushort titleResourceIdentifier = entry.Data.ReadUInt16(ref offset);
|
||||
ushort titleResourceIdentifier;
|
||||
if (offset >= entry.Data.Length)
|
||||
titleResourceIdentifier = 0x0000;
|
||||
else
|
||||
titleResourceIdentifier = entry.Data.ReadUInt16(ref offset);
|
||||
offset = currentOffset;
|
||||
|
||||
// 0x0000 means no elements
|
||||
@@ -900,7 +908,7 @@ namespace SabreTools.Serialization
|
||||
if (menuHeaderExtended == null)
|
||||
return null;
|
||||
|
||||
menuResource.ExtendedMenuHeader = menuHeaderExtended;
|
||||
menuResource.MenuHeader = menuHeaderExtended;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -929,7 +937,7 @@ namespace SabreTools.Serialization
|
||||
}
|
||||
}
|
||||
|
||||
menuResource.ExtendedMenuItems = [.. extendedMenuItems];
|
||||
menuResource.MenuItems = [.. extendedMenuItems];
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -937,7 +945,7 @@ namespace SabreTools.Serialization
|
||||
{
|
||||
#region Menu header
|
||||
|
||||
var menuHeader = entry.Data.ReadType<MenuHeader>(ref offset);
|
||||
var menuHeader = entry.Data.ReadType<NormalMenuHeader>(ref offset);
|
||||
if (menuHeader == null)
|
||||
return null;
|
||||
|
||||
@@ -1076,21 +1084,9 @@ namespace SabreTools.Serialization
|
||||
// Loop through and add
|
||||
while (offset < entry.Data.Length)
|
||||
{
|
||||
ushort stringLength = entry.Data.ReadUInt16(ref offset);
|
||||
if (stringLength == 0)
|
||||
string? stringValue = entry.Data.ReadPrefixedUnicodeString(ref offset);
|
||||
if (stringValue != null)
|
||||
{
|
||||
stringTable[stringIndex++] = "[EMPTY]";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stringLength * 2 > entry.Data.Length - offset)
|
||||
{
|
||||
Console.WriteLine($"{stringLength * 2} requested but {entry.Data.Length - offset} remains");
|
||||
stringLength = (ushort)((entry.Data.Length - offset) / 2);
|
||||
}
|
||||
|
||||
string stringValue = Encoding.Unicode.GetString(entry.Data, offset, stringLength * 2);
|
||||
offset += stringLength * 2;
|
||||
stringValue = stringValue.Replace("\n", "\\n").Replace("\r", newValue: "\\r");
|
||||
stringTable[stringIndex++] = stringValue;
|
||||
}
|
||||
@@ -1127,7 +1123,7 @@ namespace SabreTools.Serialization
|
||||
versionInfo.Padding1 = entry.Data.ReadUInt16(ref offset);
|
||||
|
||||
// Read fixed file info
|
||||
if (versionInfo.ValueLength > 0)
|
||||
if (versionInfo.ValueLength > 0 && offset + versionInfo.ValueLength <= entry.Data.Length)
|
||||
{
|
||||
var fixedFileInfo = entry.Data.ReadType<FixedFileInfo>(ref offset);
|
||||
|
||||
|
||||
@@ -1120,79 +1120,67 @@ namespace SabreTools.Serialization.Printers
|
||||
|
||||
if (menu.MenuHeader != null)
|
||||
{
|
||||
builder.AppendLine(menu.MenuHeader.Version, $"{padding}Version");
|
||||
builder.AppendLine(menu.MenuHeader.HeaderSize, $"{padding}Header size");
|
||||
if (menu.MenuHeader is NormalMenuHeader normalMenuHeader)
|
||||
{
|
||||
builder.AppendLine(normalMenuHeader.Version, $"{padding}Version");
|
||||
builder.AppendLine(normalMenuHeader.HeaderSize, $"{padding}Header size");
|
||||
}
|
||||
else if (menu.MenuHeader is MenuHeaderExtended menuHeaderExtended)
|
||||
{
|
||||
builder.AppendLine(menuHeaderExtended.Version, $"{padding}Version");
|
||||
builder.AppendLine(menuHeaderExtended.Offset, $"{padding}Offset");
|
||||
builder.AppendLine(menuHeaderExtended.HelpID, $"{padding}Help ID");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine($"{padding}Menu header found, but malformed");
|
||||
}
|
||||
builder.AppendLine();
|
||||
builder.AppendLine($"{padding}Menu items");
|
||||
builder.AppendLine($"{padding}-------------------------");
|
||||
if (menu.MenuItems == null || menu.MenuItems.Length == 0)
|
||||
{
|
||||
builder.AppendLine($"{padding}No menu items");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < menu.MenuItems.Length; i++)
|
||||
{
|
||||
var menuItem = menu.MenuItems[i];
|
||||
builder.AppendLine($"{padding}Menu item {i}");
|
||||
if (menuItem == null)
|
||||
{
|
||||
builder.AppendLine($"{padding} [NULL]");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (menuItem is NormalMenuItem normalMenuItem)
|
||||
{
|
||||
builder.AppendLine($"{padding} Resource info: {normalMenuItem.NormalResInfo} (0x{normalMenuItem.NormalResInfo:X})");
|
||||
builder.AppendLine(normalMenuItem.NormalMenuText, $"{padding} Menu text");
|
||||
}
|
||||
else if (menuItem is PopupMenuItem popupMenuItem)
|
||||
{
|
||||
builder.AppendLine($"{padding} Item type: {popupMenuItem.PopupItemType} (0x{popupMenuItem.PopupItemType:X})");
|
||||
builder.AppendLine($"{padding} State: {popupMenuItem.PopupState} (0x{popupMenuItem.PopupState:X})");
|
||||
builder.AppendLine(popupMenuItem.PopupID, $"{padding} ID");
|
||||
builder.AppendLine($"{padding} Resource info: {popupMenuItem.PopupResInfo} (0x{popupMenuItem.PopupResInfo:X})");
|
||||
builder.AppendLine(popupMenuItem.PopupMenuText, $"{padding} Menu text");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (menu.ExtendedMenuHeader != null)
|
||||
|
||||
builder.AppendLine($"{padding}Menu items");
|
||||
builder.AppendLine($"{padding}-------------------------");
|
||||
if (menu.MenuItems == null || menu.MenuItems.Length == 0)
|
||||
{
|
||||
builder.AppendLine(menu.ExtendedMenuHeader.Version, $"{padding}Version");
|
||||
builder.AppendLine(menu.ExtendedMenuHeader.Offset, $"{padding}Offset");
|
||||
builder.AppendLine(menu.ExtendedMenuHeader.HelpID, $"{padding}Help ID");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine($"{padding}Menu items");
|
||||
builder.AppendLine($"{padding}-------------------------");
|
||||
if (menu.ExtendedMenuHeader.Offset == 0
|
||||
|| menu.ExtendedMenuItems == null
|
||||
|| menu.ExtendedMenuItems.Length == 0)
|
||||
{
|
||||
builder.AppendLine($"{padding}No menu items");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < menu.ExtendedMenuItems.Length; i++)
|
||||
{
|
||||
var menuItem = menu.ExtendedMenuItems[i];
|
||||
|
||||
builder.AppendLine($"{padding}Menu item {i}");
|
||||
if (menuItem == null)
|
||||
{
|
||||
builder.AppendLine($"{padding} [NULL]");
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.AppendLine($"{padding} Item type: {menuItem.ItemType} (0x{menuItem.ItemType:X})");
|
||||
builder.AppendLine($"{padding} State: {menuItem.State} (0x{menuItem.State:X})");
|
||||
builder.AppendLine(menuItem.ID, $"{padding} ID");
|
||||
builder.AppendLine($"{padding} Flags: {menuItem.Flags} (0x{menuItem.Flags:X})");
|
||||
builder.AppendLine(menuItem.MenuText, $"{padding} Menu text");
|
||||
}
|
||||
builder.AppendLine($"{padding}No menu items");
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
for (int i = 0; i < menu.MenuItems.Length; i++)
|
||||
{
|
||||
builder.AppendLine($"{padding}Menu resource found, but malformed");
|
||||
var menuItem = menu.MenuItems[i];
|
||||
builder.AppendLine($"{padding}Menu item {i}");
|
||||
if (menuItem == null)
|
||||
{
|
||||
builder.AppendLine($"{padding} [NULL]");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (menuItem is NormalMenuItem normalMenuItem)
|
||||
{
|
||||
builder.AppendLine($"{padding} Resource info: {normalMenuItem.NormalResInfo} (0x{normalMenuItem.NormalResInfo:X})");
|
||||
builder.AppendLine(normalMenuItem.NormalMenuText, $"{padding} Menu text");
|
||||
}
|
||||
else if (menuItem is PopupMenuItem popupMenuItem)
|
||||
{
|
||||
builder.AppendLine($"{padding} Item type: {popupMenuItem.PopupItemType} (0x{popupMenuItem.PopupItemType:X})");
|
||||
builder.AppendLine($"{padding} State: {popupMenuItem.PopupState} (0x{popupMenuItem.PopupState:X})");
|
||||
builder.AppendLine(popupMenuItem.PopupID, $"{padding} ID");
|
||||
builder.AppendLine($"{padding} Resource info: {popupMenuItem.PopupResInfo} (0x{popupMenuItem.PopupResInfo:X})");
|
||||
builder.AppendLine(popupMenuItem.PopupMenuText, $"{padding} Menu text");
|
||||
}
|
||||
else if (menuItem is MenuItemExtended menuItemExtended)
|
||||
{
|
||||
builder.AppendLine($"{padding} Item type: {menuItemExtended.ItemType} (0x{menuItemExtended.ItemType:X})");
|
||||
builder.AppendLine($"{padding} State: {menuItemExtended.State} (0x{menuItemExtended.State:X})");
|
||||
builder.AppendLine(menuItemExtended.ID, $"{padding} ID");
|
||||
builder.AppendLine($"{padding} Flags: {menuItemExtended.Flags} (0x{menuItemExtended.Flags:X})");
|
||||
builder.AppendLine(menuItemExtended.MenuText, $"{padding} Menu text");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine($"{padding} Menu item found, but malformed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.6.4</Version>
|
||||
<Version>1.6.7</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
@@ -31,7 +31,7 @@
|
||||
<PackageReference Include="SabreTools.ASN1" Version="1.3.2" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.4.11" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.6" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.8" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -18,12 +18,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <summary>
|
||||
/// Normal sector size in bytes
|
||||
/// </summary>
|
||||
public long SectorSize => (long)Math.Pow(2, this.Model.Header?.SectorShift ?? 0);
|
||||
public long SectorSize => (long)Math.Pow(2, Model.Header?.SectorShift ?? 0);
|
||||
|
||||
/// <summary>
|
||||
/// Mini sector size in bytes
|
||||
/// </summary>
|
||||
public long MiniSectorSize => (long)Math.Pow(2, this.Model.Header?.MiniSectorShift ?? 0);
|
||||
public long MiniSectorSize => (long)Math.Pow(2, Model.Header?.MiniSectorShift ?? 0);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<Models.CFB.SectorNumber?>? GetFATSectorChain(Models.CFB.SectorNumber? startingSector)
|
||||
{
|
||||
// If we have an invalid sector
|
||||
if (startingSector == null || startingSector < 0 || this.Model.FATSectorNumbers == null || (long)startingSector >= this.Model.FATSectorNumbers.Length)
|
||||
if (startingSector == null || startingSector < 0 || Model.FATSectorNumbers == null || (long)startingSector >= Model.FATSectorNumbers.Length)
|
||||
return null;
|
||||
|
||||
// Setup the returned list
|
||||
@@ -114,10 +114,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
break;
|
||||
|
||||
// Get the next sector from the lookup table
|
||||
var nextSector = this.Model.FATSectorNumbers[(uint)lastSector!.Value];
|
||||
var nextSector = Model.FATSectorNumbers[(uint)lastSector!.Value];
|
||||
|
||||
// If we have an end of chain or free sector
|
||||
if (nextSector == SabreTools.Models.CFB.SectorNumber.ENDOFCHAIN || nextSector == SabreTools.Models.CFB.SectorNumber.FREESECT)
|
||||
if (nextSector == Models.CFB.SectorNumber.ENDOFCHAIN || nextSector == Models.CFB.SectorNumber.FREESECT)
|
||||
break;
|
||||
|
||||
// Add the next sector to the list and replace the last sector
|
||||
@@ -188,7 +188,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<Models.CFB.SectorNumber?>? GetMiniFATSectorChain(Models.CFB.SectorNumber? startingSector)
|
||||
{
|
||||
// If we have an invalid sector
|
||||
if (startingSector == null || startingSector < 0 || this.Model.MiniFATSectorNumbers == null || (long)startingSector >= this.Model.MiniFATSectorNumbers.Length)
|
||||
if (startingSector == null || startingSector < 0 || Model.MiniFATSectorNumbers == null || (long)startingSector >= Model.MiniFATSectorNumbers.Length)
|
||||
return null;
|
||||
|
||||
// Setup the returned list
|
||||
@@ -201,10 +201,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
break;
|
||||
|
||||
// Get the next sector from the lookup table
|
||||
var nextSector = this.Model.MiniFATSectorNumbers[(uint)lastSector!.Value];
|
||||
var nextSector = Model.MiniFATSectorNumbers[(uint)lastSector!.Value];
|
||||
|
||||
// If we have an end of chain or free sector
|
||||
if (nextSector == SabreTools.Models.CFB.SectorNumber.ENDOFCHAIN || nextSector == SabreTools.Models.CFB.SectorNumber.FREESECT)
|
||||
if (nextSector == Models.CFB.SectorNumber.ENDOFCHAIN || nextSector == Models.CFB.SectorNumber.FREESECT)
|
||||
break;
|
||||
|
||||
// Add the next sector to the list and replace the last sector
|
||||
|
||||
@@ -26,16 +26,16 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return _files;
|
||||
|
||||
// If we don't have a required property
|
||||
if (this.Model.DirectoryEntries == null || this.Model.DirectoryMapEntries == null || this.Model.BlockEntries == null)
|
||||
if (Model.DirectoryEntries == null || Model.DirectoryMapEntries == null || Model.BlockEntries == null)
|
||||
return null;
|
||||
|
||||
// Otherwise, scan and build the files
|
||||
var files = new List<FileInfo>();
|
||||
for (int i = 0; i < this.Model.DirectoryEntries.Length; i++)
|
||||
for (int i = 0; i < Model.DirectoryEntries.Length; i++)
|
||||
{
|
||||
// Get the directory entry
|
||||
var directoryEntry = this.Model.DirectoryEntries[i];
|
||||
var directoryMapEntry = this.Model.DirectoryMapEntries[i];
|
||||
var directoryEntry = Model.DirectoryEntries[i];
|
||||
var directoryMapEntry = Model.DirectoryMapEntries[i];
|
||||
if (directoryEntry == null || directoryMapEntry == null)
|
||||
continue;
|
||||
|
||||
@@ -57,26 +57,26 @@ namespace SabreTools.Serialization.Wrappers
|
||||
Encrypted = directoryEntry.DirectoryFlags.HasFlag(Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_ENCRYPTED),
|
||||
#endif
|
||||
};
|
||||
var pathParts = new List<string> { this.Model.DirectoryNames![directoryEntry.NameOffset] ?? string.Empty };
|
||||
var pathParts = new List<string> { Model.DirectoryNames![directoryEntry.NameOffset] ?? string.Empty };
|
||||
var blockEntries = new List<Models.GCF.BlockEntry?>();
|
||||
|
||||
// Traverse the parent tree
|
||||
uint index = directoryEntry.ParentIndex;
|
||||
while (index != 0xFFFFFFFF)
|
||||
{
|
||||
var parentDirectoryEntry = this.Model.DirectoryEntries[index];
|
||||
var parentDirectoryEntry = Model.DirectoryEntries[index];
|
||||
if (parentDirectoryEntry == null)
|
||||
break;
|
||||
|
||||
pathParts.Add(this.Model.DirectoryNames![parentDirectoryEntry.NameOffset] ?? string.Empty);
|
||||
pathParts.Add(Model.DirectoryNames![parentDirectoryEntry.NameOffset] ?? string.Empty);
|
||||
index = parentDirectoryEntry.ParentIndex;
|
||||
}
|
||||
|
||||
// Traverse the block entries
|
||||
index = directoryMapEntry.FirstBlockIndex;
|
||||
while (index != this.Model.DataBlockHeader?.BlockCount)
|
||||
while (index != Model.DataBlockHeader?.BlockCount)
|
||||
{
|
||||
var nextBlock = this.Model.BlockEntries[index];
|
||||
var nextBlock = Model.BlockEntries[index];
|
||||
if (nextBlock == null)
|
||||
break;
|
||||
|
||||
@@ -134,14 +134,14 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return _dataBlockOffsets;
|
||||
|
||||
// If we don't have a block count, offset, or size
|
||||
if (this.Model.DataBlockHeader?.BlockCount == null || this.Model.DataBlockHeader?.FirstBlockOffset == null || this.Model.DataBlockHeader?.BlockSize == null)
|
||||
if (Model.DataBlockHeader?.BlockCount == null || Model.DataBlockHeader?.FirstBlockOffset == null || Model.DataBlockHeader?.BlockSize == null)
|
||||
return null;
|
||||
|
||||
// Otherwise, build the data block set
|
||||
_dataBlockOffsets = new long[this.Model.DataBlockHeader.BlockCount];
|
||||
for (int i = 0; i < this.Model.DataBlockHeader.BlockCount; i++)
|
||||
_dataBlockOffsets = new long[Model.DataBlockHeader.BlockCount];
|
||||
for (int i = 0; i < Model.DataBlockHeader.BlockCount; i++)
|
||||
{
|
||||
long dataBlockOffset = this.Model.DataBlockHeader.FirstBlockOffset + (i * this.Model.DataBlockHeader.BlockSize);
|
||||
long dataBlockOffset = Model.DataBlockHeader.FirstBlockOffset + (i * Model.DataBlockHeader.BlockSize);
|
||||
_dataBlockOffsets[i] = dataBlockOffset;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
uint majorVersion = this.Model.CommonHeader?.Version ?? 0;
|
||||
uint majorVersion = Model.CommonHeader?.Version ?? 0;
|
||||
if (majorVersion >> 24 == 1)
|
||||
{
|
||||
majorVersion = (majorVersion >> 12) & 0x0F;
|
||||
|
||||
@@ -124,11 +124,11 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public DateTime? GetDateTime(int fileIndex)
|
||||
{
|
||||
// If we have an invalid file index
|
||||
if (fileIndex < 0 || this.Model.Files == null || fileIndex >= this.Model.Files.Length)
|
||||
if (fileIndex < 0 || Model.Files == null || fileIndex >= Model.Files.Length)
|
||||
return null;
|
||||
|
||||
// Get the file header
|
||||
var file = this.Model.Files[fileIndex];
|
||||
var file = Model.Files[fileIndex];
|
||||
if (file == null)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -33,19 +33,26 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// TODO: Don't scan the known header data as well
|
||||
|
||||
// If the section table is missing
|
||||
if (this.Model.SectionTable == null)
|
||||
return null;
|
||||
// If any required pieces are missing
|
||||
if (Model.Stub?.Header == null)
|
||||
return [];
|
||||
if (Model.SectionTable == null)
|
||||
return [];
|
||||
|
||||
// Populate the raw header padding data based on the source
|
||||
uint headerStartAddress = this.Model.Stub?.Header?.NewExeHeaderAddr ?? 0;
|
||||
uint firstSectionAddress = this.Model.SectionTable
|
||||
uint headerStartAddress = Model.Stub.Header.NewExeHeaderAddr;
|
||||
uint firstSectionAddress = Model.SectionTable
|
||||
.Select(s => s?.PointerToRawData ?? 0)
|
||||
.Where(s => s != 0)
|
||||
.Where(s => s != 0 && s >= headerStartAddress)
|
||||
.OrderBy(s => s)
|
||||
.First();
|
||||
.FirstOrDefault();
|
||||
|
||||
// Check if the header length is more than 0 before reading data
|
||||
int headerLength = (int)(firstSectionAddress - headerStartAddress);
|
||||
_headerPaddingData = ReadFromDataSource((int)headerStartAddress, headerLength);
|
||||
if (headerLength <= 0)
|
||||
_headerPaddingData = [];
|
||||
else
|
||||
_headerPaddingData = ReadFromDataSource((int)headerStartAddress, headerLength);
|
||||
|
||||
// Cache and return the header padding data, even if null
|
||||
return _headerPaddingData;
|
||||
@@ -68,19 +75,26 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// TODO: Don't scan the known header data as well
|
||||
|
||||
// If the section table is missing
|
||||
if (this.Model.SectionTable == null)
|
||||
return null;
|
||||
// If any required pieces are missing
|
||||
if (Model.Stub?.Header == null)
|
||||
return [];
|
||||
if (Model.SectionTable == null)
|
||||
return [];
|
||||
|
||||
// Populate the raw header padding data based on the source
|
||||
uint headerStartAddress = this.Model.Stub?.Header?.NewExeHeaderAddr ?? 0;
|
||||
uint firstSectionAddress = this.Model.SectionTable
|
||||
// Populate the header padding strings based on the source
|
||||
uint headerStartAddress = Model.Stub.Header.NewExeHeaderAddr;
|
||||
uint firstSectionAddress = Model.SectionTable
|
||||
.Select(s => s?.PointerToRawData ?? 0)
|
||||
.Where(s => s != 0)
|
||||
.Where(s => s != 0 && s >= headerStartAddress)
|
||||
.OrderBy(s => s)
|
||||
.First();
|
||||
.FirstOrDefault();
|
||||
|
||||
// Check if the header length is more than 0 before reading strings
|
||||
int headerLength = (int)(firstSectionAddress - headerStartAddress);
|
||||
_headerPaddingStrings = ReadStringsFromDataSource((int)headerStartAddress, headerLength, charLimit: 3);
|
||||
if (headerLength <= 0)
|
||||
_headerPaddingStrings = [];
|
||||
else
|
||||
_headerPaddingStrings = ReadStringsFromDataSource((int)headerStartAddress, headerLength, charLimit: 3);
|
||||
|
||||
// Cache and return the header padding data, even if null
|
||||
return _headerPaddingStrings;
|
||||
@@ -98,21 +112,21 @@ namespace SabreTools.Serialization.Wrappers
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// If the section table is missing
|
||||
if (this.Model.SectionTable == null)
|
||||
if (Model.SectionTable == null)
|
||||
return null;
|
||||
|
||||
// If the address is missing
|
||||
if (this.Model.OptionalHeader?.AddressOfEntryPoint == null)
|
||||
if (Model.OptionalHeader?.AddressOfEntryPoint == null)
|
||||
return null;
|
||||
|
||||
// If we have no entry point
|
||||
int entryPointAddress = (int)this.Model.OptionalHeader.AddressOfEntryPoint.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
int entryPointAddress = (int)Model.OptionalHeader.AddressOfEntryPoint.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (entryPointAddress == 0)
|
||||
return null;
|
||||
|
||||
// If the entry point matches with the start of a section, use that
|
||||
int entryPointSection = FindEntryPointSectionIndex();
|
||||
if (entryPointSection >= 0 && this.Model.OptionalHeader.AddressOfEntryPoint == this.Model.SectionTable[entryPointSection]?.VirtualAddress)
|
||||
if (entryPointSection >= 0 && Model.OptionalHeader.AddressOfEntryPoint == Model.SectionTable[entryPointSection]?.VirtualAddress)
|
||||
return GetSectionData(entryPointSection);
|
||||
|
||||
// If we already have cached data, just use that immediately
|
||||
@@ -148,27 +162,27 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return -1;
|
||||
|
||||
// If the section table is missing
|
||||
if (this.Model.SectionTable == null)
|
||||
if (Model.SectionTable == null)
|
||||
return -1;
|
||||
|
||||
// If we have certificate data, use that as the end
|
||||
if (this.Model.OptionalHeader?.CertificateTable != null)
|
||||
if (Model.OptionalHeader?.CertificateTable != null)
|
||||
{
|
||||
int certificateTableAddress = (int)this.Model.OptionalHeader.CertificateTable.VirtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
int certificateTableAddress = (int)Model.OptionalHeader.CertificateTable.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (certificateTableAddress != 0 && certificateTableAddress < endOfFile)
|
||||
endOfFile = certificateTableAddress;
|
||||
}
|
||||
|
||||
// Search through all sections and find the furthest a section goes
|
||||
int endOfSectionData = -1;
|
||||
foreach (var section in this.Model.SectionTable)
|
||||
foreach (var section in Model.SectionTable)
|
||||
{
|
||||
// If we have an invalid section
|
||||
if (section == null)
|
||||
continue;
|
||||
|
||||
// If we have an invalid section address
|
||||
int sectionAddress = (int)section.VirtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
int sectionAddress = (int)section.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (sectionAddress == 0)
|
||||
continue;
|
||||
|
||||
@@ -219,27 +233,27 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// If the section table is missing
|
||||
if (this.Model.SectionTable == null)
|
||||
if (Model.SectionTable == null)
|
||||
return null;
|
||||
|
||||
// If we have certificate data, use that as the end
|
||||
if (this.Model.OptionalHeader?.CertificateTable != null)
|
||||
if (Model.OptionalHeader?.CertificateTable != null)
|
||||
{
|
||||
int certificateTableAddress = (int)this.Model.OptionalHeader.CertificateTable.VirtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
int certificateTableAddress = (int)Model.OptionalHeader.CertificateTable.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (certificateTableAddress != 0 && certificateTableAddress < endOfFile)
|
||||
endOfFile = certificateTableAddress;
|
||||
}
|
||||
|
||||
// Search through all sections and find the furthest a section goes
|
||||
int endOfSectionData = -1;
|
||||
foreach (var section in this.Model.SectionTable)
|
||||
foreach (var section in Model.SectionTable)
|
||||
{
|
||||
// If we have an invalid section
|
||||
if (section == null)
|
||||
continue;
|
||||
|
||||
// If we have an invalid section address
|
||||
int sectionAddress = (int)section.VirtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
int sectionAddress = (int)section.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (sectionAddress == 0)
|
||||
continue;
|
||||
|
||||
@@ -297,27 +311,27 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// If the section table is missing
|
||||
if (this.Model.SectionTable == null)
|
||||
if (Model.SectionTable == null)
|
||||
return null;
|
||||
|
||||
// If we have certificate data, use that as the end
|
||||
if (this.Model.OptionalHeader?.CertificateTable != null)
|
||||
if (Model.OptionalHeader?.CertificateTable != null)
|
||||
{
|
||||
int certificateTableAddress = (int)this.Model.OptionalHeader.CertificateTable.VirtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
int certificateTableAddress = (int)Model.OptionalHeader.CertificateTable.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (certificateTableAddress != 0 && certificateTableAddress < endOfFile)
|
||||
endOfFile = certificateTableAddress;
|
||||
}
|
||||
|
||||
// Search through all sections and find the furthest a section goes
|
||||
int endOfSectionData = -1;
|
||||
foreach (var section in this.Model.SectionTable)
|
||||
foreach (var section in Model.SectionTable)
|
||||
{
|
||||
// If we have an invalid section
|
||||
if (section == null)
|
||||
continue;
|
||||
|
||||
// If we have an invalid section address
|
||||
int sectionAddress = (int)section.VirtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
int sectionAddress = (int)section.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (sectionAddress == 0)
|
||||
continue;
|
||||
|
||||
@@ -370,14 +384,14 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return _sectionNames;
|
||||
|
||||
// If there are no sections
|
||||
if (this.Model.SectionTable == null)
|
||||
if (Model.SectionTable == null)
|
||||
return null;
|
||||
|
||||
// Otherwise, build and return the cached array
|
||||
_sectionNames = new string[this.Model.SectionTable.Length];
|
||||
_sectionNames = new string[Model.SectionTable.Length];
|
||||
for (int i = 0; i < _sectionNames.Length; i++)
|
||||
{
|
||||
var section = this.Model.SectionTable[i];
|
||||
var section = Model.SectionTable[i];
|
||||
if (section == null)
|
||||
continue;
|
||||
|
||||
@@ -408,12 +422,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (_stubExecutableData != null)
|
||||
return _stubExecutableData;
|
||||
|
||||
if (this.Model.Stub?.Header?.NewExeHeaderAddr == null)
|
||||
if (Model.Stub?.Header?.NewExeHeaderAddr == null)
|
||||
return null;
|
||||
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)this.Model.Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
int lengthOfStubExecutableData = (int)Model.Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = ReadFromDataSource(endOfStubHeader, lengthOfStubExecutableData);
|
||||
|
||||
// Cache and return the stub executable data, even if null
|
||||
@@ -436,8 +450,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return _debugData;
|
||||
|
||||
// If we have no resource table, just return
|
||||
if (this.Model.DebugTable?.DebugDirectoryTable == null
|
||||
|| this.Model.DebugTable.DebugDirectoryTable.Length == 0)
|
||||
if (Model.DebugTable?.DebugDirectoryTable == null
|
||||
|| Model.DebugTable.DebugDirectoryTable.Length == 0)
|
||||
return null;
|
||||
|
||||
// Otherwise, build and return the cached dictionary
|
||||
@@ -461,13 +475,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return _resourceData;
|
||||
|
||||
// If we have no resource table, just return
|
||||
if (this.Model.OptionalHeader?.ResourceTable == null
|
||||
|| this.Model.OptionalHeader.ResourceTable.VirtualAddress == 0
|
||||
|| this.Model.ResourceDirectoryTable == null)
|
||||
if (Model.OptionalHeader?.ResourceTable == null
|
||||
|| Model.OptionalHeader.ResourceTable.VirtualAddress == 0
|
||||
|| Model.ResourceDirectoryTable == null)
|
||||
return null;
|
||||
|
||||
// Otherwise, build and return the cached dictionary
|
||||
ParseResourceDirectoryTable(this.Model.ResourceDirectoryTable, types: []);
|
||||
ParseResourceDirectoryTable(Model.ResourceDirectoryTable, types: []);
|
||||
return _resourceData;
|
||||
}
|
||||
}
|
||||
@@ -585,15 +599,15 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <remarks>The internal version is either the file version, product version, or assembly version, in that order</remarks>
|
||||
public string? GetInternalVersion()
|
||||
{
|
||||
string? version = this.FileVersion;
|
||||
string? version = FileVersion;
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version!.Replace(", ", ".");
|
||||
|
||||
version = this.ProductVersion;
|
||||
version = ProductVersion;
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version!.Replace(", ", ".");
|
||||
|
||||
version = this.AssemblyVersion;
|
||||
version = AssemblyVersion;
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
|
||||
@@ -864,7 +878,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
// Ensure that we have the debug data cached
|
||||
if (DebugData == null)
|
||||
return Enumerable.Empty<object?>();
|
||||
return [];
|
||||
|
||||
var nb10Found = DebugData.Select(r => r.Value)
|
||||
.Select(r => r as SabreTools.Models.PortableExecutable.NB10ProgramDatabase)
|
||||
@@ -890,7 +904,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
// Ensure that we have the resource data cached
|
||||
if (DebugData == null)
|
||||
return Enumerable.Empty<byte[]?>();
|
||||
return [];
|
||||
|
||||
return DebugData.Select(r => r.Value)
|
||||
.Select(b => b as byte[])
|
||||
@@ -935,13 +949,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
private void ParseDebugTable()
|
||||
{
|
||||
// If there is no debug table
|
||||
if (this.Model.DebugTable?.DebugDirectoryTable == null)
|
||||
if (Model.DebugTable?.DebugDirectoryTable == null)
|
||||
return;
|
||||
|
||||
// Loop through all debug table entries
|
||||
for (int i = 0; i < this.Model.DebugTable.DebugDirectoryTable.Length; i++)
|
||||
for (int i = 0; i < Model.DebugTable.DebugDirectoryTable.Length; i++)
|
||||
{
|
||||
var entry = this.Model.DebugTable.DebugDirectoryTable[i];
|
||||
var entry = Model.DebugTable.DebugDirectoryTable[i];
|
||||
if (entry == null)
|
||||
continue;
|
||||
|
||||
@@ -953,7 +967,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
continue;
|
||||
|
||||
// If we have CodeView debug data, try to parse it
|
||||
if (entry.DebugType == SabreTools.Models.PortableExecutable.DebugType.IMAGE_DEBUG_TYPE_CODEVIEW)
|
||||
if (entry.DebugType == Models.PortableExecutable.DebugType.IMAGE_DEBUG_TYPE_CODEVIEW)
|
||||
{
|
||||
// Read the signature
|
||||
int offset = 0;
|
||||
@@ -1004,7 +1018,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
// Ensure that we have the resource data cached
|
||||
if (ResourceData == null)
|
||||
return Enumerable.Empty<Models.PortableExecutable.DialogBoxResource?>();
|
||||
return [];
|
||||
|
||||
return ResourceData.Select(r => r.Value)
|
||||
.Select(r => r as SabreTools.Models.PortableExecutable.DialogBoxResource)
|
||||
@@ -1025,7 +1039,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
// Ensure that we have the resource data cached
|
||||
if (ResourceData == null)
|
||||
return Enumerable.Empty<Models.PortableExecutable.DialogBoxResource?>();
|
||||
return [];
|
||||
|
||||
return ResourceData.Select(r => r.Value)
|
||||
.Select(r => r as SabreTools.Models.PortableExecutable.DialogBoxResource)
|
||||
@@ -1058,7 +1072,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
// Ensure that we have the resource data cached
|
||||
if (ResourceData == null)
|
||||
return Enumerable.Empty<Dictionary<int, string?>?>();
|
||||
return [];
|
||||
|
||||
return ResourceData.Select(r => r.Value)
|
||||
.Select(r => r as Dictionary<int, string?>)
|
||||
@@ -1076,7 +1090,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
// Ensure that we have the resource data cached
|
||||
if (ResourceData == null)
|
||||
return Enumerable.Empty<byte[]?>();
|
||||
return [];
|
||||
|
||||
return ResourceData.Where(kvp => kvp.Key.Contains(typeName))
|
||||
.Select(kvp => kvp.Value as byte[])
|
||||
@@ -1092,7 +1106,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
// Ensure that we have the resource data cached
|
||||
if (ResourceData == null)
|
||||
return Enumerable.Empty<byte[]?>();
|
||||
return [];
|
||||
|
||||
return ResourceData.Select(r => r.Value)
|
||||
.Select(r => r as byte[])
|
||||
@@ -1188,68 +1202,68 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
switch ((Models.PortableExecutable.ResourceType)resourceType)
|
||||
{
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_CURSOR:
|
||||
case Models.PortableExecutable.ResourceType.RT_CURSOR:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_BITMAP:
|
||||
case Models.PortableExecutable.ResourceType.RT_BITMAP:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_ICON:
|
||||
case Models.PortableExecutable.ResourceType.RT_ICON:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_MENU:
|
||||
case Models.PortableExecutable.ResourceType.RT_MENU:
|
||||
value = entry.AsMenu();
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_DIALOG:
|
||||
case Models.PortableExecutable.ResourceType.RT_DIALOG:
|
||||
value = entry.AsDialogBox();
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_STRING:
|
||||
case Models.PortableExecutable.ResourceType.RT_STRING:
|
||||
value = entry.AsStringTable();
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_FONTDIR:
|
||||
case Models.PortableExecutable.ResourceType.RT_FONTDIR:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_FONT:
|
||||
case Models.PortableExecutable.ResourceType.RT_FONT:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_ACCELERATOR:
|
||||
case Models.PortableExecutable.ResourceType.RT_ACCELERATOR:
|
||||
value = entry.AsAcceleratorTableResource();
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_RCDATA:
|
||||
case Models.PortableExecutable.ResourceType.RT_RCDATA:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_MESSAGETABLE:
|
||||
case Models.PortableExecutable.ResourceType.RT_MESSAGETABLE:
|
||||
value = entry.AsMessageResourceData();
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_GROUP_CURSOR:
|
||||
case Models.PortableExecutable.ResourceType.RT_GROUP_CURSOR:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_GROUP_ICON:
|
||||
case Models.PortableExecutable.ResourceType.RT_GROUP_ICON:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_VERSION:
|
||||
case Models.PortableExecutable.ResourceType.RT_VERSION:
|
||||
_versionInfo = entry.AsVersionInfo();
|
||||
value = _versionInfo;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_DLGINCLUDE:
|
||||
case Models.PortableExecutable.ResourceType.RT_DLGINCLUDE:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_PLUGPLAY:
|
||||
case Models.PortableExecutable.ResourceType.RT_PLUGPLAY:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_VXD:
|
||||
case Models.PortableExecutable.ResourceType.RT_VXD:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_ANICURSOR:
|
||||
case Models.PortableExecutable.ResourceType.RT_ANICURSOR:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_ANIICON:
|
||||
case Models.PortableExecutable.ResourceType.RT_ANIICON:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_HTML:
|
||||
case Models.PortableExecutable.ResourceType.RT_HTML:
|
||||
value = entry.Data;
|
||||
break;
|
||||
case SabreTools.Models.PortableExecutable.ResourceType.RT_MANIFEST:
|
||||
case Models.PortableExecutable.ResourceType.RT_MANIFEST:
|
||||
_assemblyManifest = entry.AsAssemblyManifest();
|
||||
value = _versionInfo;
|
||||
break;
|
||||
@@ -1311,19 +1325,19 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public int FindEntryPointSectionIndex()
|
||||
{
|
||||
// If the section table is missing
|
||||
if (this.Model.SectionTable == null)
|
||||
if (Model.SectionTable == null)
|
||||
return -1;
|
||||
|
||||
// If the address is missing
|
||||
if (this.Model.OptionalHeader?.AddressOfEntryPoint == null)
|
||||
if (Model.OptionalHeader?.AddressOfEntryPoint == null)
|
||||
return -1;
|
||||
|
||||
// If we don't have an entry point
|
||||
if (this.Model.OptionalHeader.AddressOfEntryPoint.ConvertVirtualAddress(this.Model.SectionTable) == 0)
|
||||
if (Model.OptionalHeader.AddressOfEntryPoint.ConvertVirtualAddress(Model.SectionTable) == 0)
|
||||
return -1;
|
||||
|
||||
// Otherwise, find the section it exists within
|
||||
return this.Model.OptionalHeader.AddressOfEntryPoint.ContainingSectionIndex(this.Model.SectionTable
|
||||
return Model.OptionalHeader.AddressOfEntryPoint.ContainingSectionIndex(Model.SectionTable
|
||||
.Where(sh => sh != null)
|
||||
.Cast<Models.PortableExecutable.SectionHeader>()
|
||||
.ToArray());
|
||||
@@ -1335,10 +1349,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <param name="name">Name of the section to check for</param>
|
||||
/// <param name="exact">True to enable exact matching of names, false for starts-with</param>
|
||||
/// <returns>Section data on success, null on error</returns>
|
||||
public SabreTools.Models.PortableExecutable.SectionHeader? GetFirstSection(string? name, bool exact = false)
|
||||
public Models.PortableExecutable.SectionHeader? GetFirstSection(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
|
||||
if (SectionNames == null || !SectionNames.Any() || Model.SectionTable == null || !Model.SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1351,7 +1365,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// Return the section
|
||||
return this.Model.SectionTable[index];
|
||||
return Model.SectionTable[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1360,10 +1374,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <param name="name">Name of the section to check for</param>
|
||||
/// <param name="exact">True to enable exact matching of names, false for starts-with</param>
|
||||
/// <returns>Section data on success, null on error</returns>
|
||||
public SabreTools.Models.PortableExecutable.SectionHeader? GetLastSection(string? name, bool exact = false)
|
||||
public Models.PortableExecutable.SectionHeader? GetLastSection(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
|
||||
if (SectionNames == null || !SectionNames.Any() || Model.SectionTable == null || !Model.SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1376,7 +1390,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// Return the section
|
||||
return this.Model.SectionTable[index];
|
||||
return Model.SectionTable[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1384,18 +1398,18 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the section to check for</param>
|
||||
/// <returns>Section data on success, null on error</returns>
|
||||
public SabreTools.Models.PortableExecutable.SectionHeader? GetSection(int index)
|
||||
public Models.PortableExecutable.SectionHeader? GetSection(int index)
|
||||
{
|
||||
// If we have no sections
|
||||
if (this.Model.SectionTable == null || !this.Model.SectionTable.Any())
|
||||
if (Model.SectionTable == null || !Model.SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
if (index < 0 || index >= this.Model.SectionTable.Length)
|
||||
if (index < 0 || index >= Model.SectionTable.Length)
|
||||
return null;
|
||||
|
||||
// Return the section
|
||||
return this.Model.SectionTable[index];
|
||||
return Model.SectionTable[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1407,7 +1421,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public byte[]? GetFirstSectionData(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
|
||||
if (SectionNames == null || !SectionNames.Any() || Model.SectionTable == null || !Model.SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1428,7 +1442,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public byte[]? GetLastSectionData(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
|
||||
if (SectionNames == null || !SectionNames.Any() || Model.SectionTable == null || !Model.SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1448,19 +1462,19 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public byte[]? GetSectionData(int index)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
|
||||
if (SectionNames == null || !SectionNames.Any() || Model.SectionTable == null || !Model.SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
if (index < 0 || index >= this.Model.SectionTable.Length)
|
||||
if (index < 0 || index >= Model.SectionTable.Length)
|
||||
return null;
|
||||
|
||||
// Get the section data from the table
|
||||
var section = this.Model.SectionTable[index];
|
||||
var section = Model.SectionTable[index];
|
||||
if (section == null)
|
||||
return null;
|
||||
|
||||
uint address = section.VirtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
uint address = section.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (address == 0)
|
||||
return null;
|
||||
|
||||
@@ -1493,7 +1507,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<string>? GetFirstSectionStrings(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
|
||||
if (SectionNames == null || !SectionNames.Any() || Model.SectionTable == null || !Model.SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1514,7 +1528,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<string>? GetLastSectionStrings(string? name, bool exact = false)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
|
||||
if (SectionNames == null || !SectionNames.Any() || Model.SectionTable == null || !Model.SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
@@ -1534,19 +1548,19 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<string>? GetSectionStrings(int index)
|
||||
{
|
||||
// If we have no sections
|
||||
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
|
||||
if (SectionNames == null || !SectionNames.Any() || Model.SectionTable == null || !Model.SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If the section doesn't exist
|
||||
if (index < 0 || index >= this.Model.SectionTable.Length)
|
||||
if (index < 0 || index >= Model.SectionTable.Length)
|
||||
return null;
|
||||
|
||||
// Get the section data from the table
|
||||
var section = this.Model.SectionTable[index];
|
||||
var section = Model.SectionTable[index];
|
||||
if (section == null)
|
||||
return null;
|
||||
|
||||
uint address = section.VirtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
uint address = section.VirtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (address == 0)
|
||||
return null;
|
||||
|
||||
@@ -1582,7 +1596,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public byte[]? GetTableData(int index)
|
||||
{
|
||||
// If the table doesn't exist
|
||||
if (this.Model.OptionalHeader == null || index < 0 || index > 16)
|
||||
if (Model.OptionalHeader == null || index < 0 || index > 16)
|
||||
return null;
|
||||
|
||||
// Get the virtual address and size from the entries
|
||||
@@ -1590,64 +1604,64 @@ namespace SabreTools.Serialization.Wrappers
|
||||
switch (index)
|
||||
{
|
||||
case 1:
|
||||
virtualAddress = this.Model.OptionalHeader.ExportTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ExportTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ExportTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ExportTable?.Size ?? 0;
|
||||
break;
|
||||
case 2:
|
||||
virtualAddress = this.Model.OptionalHeader.ImportTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ImportTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ImportTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ImportTable?.Size ?? 0;
|
||||
break;
|
||||
case 3:
|
||||
virtualAddress = this.Model.OptionalHeader.ResourceTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ResourceTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ResourceTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ResourceTable?.Size ?? 0;
|
||||
break;
|
||||
case 4:
|
||||
virtualAddress = this.Model.OptionalHeader.ExceptionTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ExceptionTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ExceptionTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ExceptionTable?.Size ?? 0;
|
||||
break;
|
||||
case 5:
|
||||
virtualAddress = this.Model.OptionalHeader.CertificateTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.CertificateTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.CertificateTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.CertificateTable?.Size ?? 0;
|
||||
break;
|
||||
case 6:
|
||||
virtualAddress = this.Model.OptionalHeader.BaseRelocationTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.BaseRelocationTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.BaseRelocationTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.BaseRelocationTable?.Size ?? 0;
|
||||
break;
|
||||
case 7:
|
||||
virtualAddress = this.Model.OptionalHeader.Debug?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.Debug?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.Debug?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.Debug?.Size ?? 0;
|
||||
break;
|
||||
case 8: // Architecture Table
|
||||
virtualAddress = 0;
|
||||
size = 0;
|
||||
break;
|
||||
case 9:
|
||||
virtualAddress = this.Model.OptionalHeader.GlobalPtr?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.GlobalPtr?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.GlobalPtr?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.GlobalPtr?.Size ?? 0;
|
||||
break;
|
||||
case 10:
|
||||
virtualAddress = this.Model.OptionalHeader.ThreadLocalStorageTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ThreadLocalStorageTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ThreadLocalStorageTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ThreadLocalStorageTable?.Size ?? 0;
|
||||
break;
|
||||
case 11:
|
||||
virtualAddress = this.Model.OptionalHeader.LoadConfigTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.LoadConfigTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.LoadConfigTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.LoadConfigTable?.Size ?? 0;
|
||||
break;
|
||||
case 12:
|
||||
virtualAddress = this.Model.OptionalHeader.BoundImport?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.BoundImport?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.BoundImport?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.BoundImport?.Size ?? 0;
|
||||
break;
|
||||
case 13:
|
||||
virtualAddress = this.Model.OptionalHeader.ImportAddressTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ImportAddressTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ImportAddressTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ImportAddressTable?.Size ?? 0;
|
||||
break;
|
||||
case 14:
|
||||
virtualAddress = this.Model.OptionalHeader.DelayImportDescriptor?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.DelayImportDescriptor?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.DelayImportDescriptor?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.DelayImportDescriptor?.Size ?? 0;
|
||||
break;
|
||||
case 15:
|
||||
virtualAddress = this.Model.OptionalHeader.CLRRuntimeHeader?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.CLRRuntimeHeader?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.CLRRuntimeHeader?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.CLRRuntimeHeader?.Size ?? 0;
|
||||
break;
|
||||
case 16: // Reserved
|
||||
virtualAddress = 0;
|
||||
@@ -1656,11 +1670,11 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
|
||||
// If there is no section table
|
||||
if (this.Model.SectionTable == null)
|
||||
if (Model.SectionTable == null)
|
||||
return null;
|
||||
|
||||
// Get the physical address from the virtual one
|
||||
uint address = virtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
uint address = virtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (address == 0 || size == 0)
|
||||
return null;
|
||||
|
||||
@@ -1690,7 +1704,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
public List<string>? GetTableStrings(int index)
|
||||
{
|
||||
// If the table doesn't exist
|
||||
if (this.Model.OptionalHeader == null || index < 0 || index > 16)
|
||||
if (Model.OptionalHeader == null || index < 0 || index > 16)
|
||||
return null;
|
||||
|
||||
// Get the virtual address and size from the entries
|
||||
@@ -1698,64 +1712,64 @@ namespace SabreTools.Serialization.Wrappers
|
||||
switch (index)
|
||||
{
|
||||
case 1:
|
||||
virtualAddress = this.Model.OptionalHeader.ExportTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ExportTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ExportTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ExportTable?.Size ?? 0;
|
||||
break;
|
||||
case 2:
|
||||
virtualAddress = this.Model.OptionalHeader.ImportTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ImportTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ImportTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ImportTable?.Size ?? 0;
|
||||
break;
|
||||
case 3:
|
||||
virtualAddress = this.Model.OptionalHeader.ResourceTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ResourceTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ResourceTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ResourceTable?.Size ?? 0;
|
||||
break;
|
||||
case 4:
|
||||
virtualAddress = this.Model.OptionalHeader.ExceptionTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ExceptionTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ExceptionTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ExceptionTable?.Size ?? 0;
|
||||
break;
|
||||
case 5:
|
||||
virtualAddress = this.Model.OptionalHeader.CertificateTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.CertificateTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.CertificateTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.CertificateTable?.Size ?? 0;
|
||||
break;
|
||||
case 6:
|
||||
virtualAddress = this.Model.OptionalHeader.BaseRelocationTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.BaseRelocationTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.BaseRelocationTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.BaseRelocationTable?.Size ?? 0;
|
||||
break;
|
||||
case 7:
|
||||
virtualAddress = this.Model.OptionalHeader.Debug?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.Debug?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.Debug?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.Debug?.Size ?? 0;
|
||||
break;
|
||||
case 8: // Architecture Table
|
||||
virtualAddress = 0;
|
||||
size = 0;
|
||||
break;
|
||||
case 9:
|
||||
virtualAddress = this.Model.OptionalHeader.GlobalPtr?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.GlobalPtr?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.GlobalPtr?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.GlobalPtr?.Size ?? 0;
|
||||
break;
|
||||
case 10:
|
||||
virtualAddress = this.Model.OptionalHeader.ThreadLocalStorageTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ThreadLocalStorageTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ThreadLocalStorageTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ThreadLocalStorageTable?.Size ?? 0;
|
||||
break;
|
||||
case 11:
|
||||
virtualAddress = this.Model.OptionalHeader.LoadConfigTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.LoadConfigTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.LoadConfigTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.LoadConfigTable?.Size ?? 0;
|
||||
break;
|
||||
case 12:
|
||||
virtualAddress = this.Model.OptionalHeader.BoundImport?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.BoundImport?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.BoundImport?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.BoundImport?.Size ?? 0;
|
||||
break;
|
||||
case 13:
|
||||
virtualAddress = this.Model.OptionalHeader.ImportAddressTable?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.ImportAddressTable?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.ImportAddressTable?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.ImportAddressTable?.Size ?? 0;
|
||||
break;
|
||||
case 14:
|
||||
virtualAddress = this.Model.OptionalHeader.DelayImportDescriptor?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.DelayImportDescriptor?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.DelayImportDescriptor?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.DelayImportDescriptor?.Size ?? 0;
|
||||
break;
|
||||
case 15:
|
||||
virtualAddress = this.Model.OptionalHeader.CLRRuntimeHeader?.VirtualAddress ?? 0;
|
||||
size = this.Model.OptionalHeader.CLRRuntimeHeader?.Size ?? 0;
|
||||
virtualAddress = Model.OptionalHeader.CLRRuntimeHeader?.VirtualAddress ?? 0;
|
||||
size = Model.OptionalHeader.CLRRuntimeHeader?.Size ?? 0;
|
||||
break;
|
||||
case 16: // Reserved
|
||||
virtualAddress = 0;
|
||||
@@ -1764,11 +1778,11 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
|
||||
// If there is no section table
|
||||
if (this.Model.SectionTable == null)
|
||||
if (Model.SectionTable == null)
|
||||
return null;
|
||||
|
||||
// Get the physical address from the virtual one
|
||||
uint address = virtualAddress.ConvertVirtualAddress(this.Model.SectionTable);
|
||||
uint address = virtualAddress.ConvertVirtualAddress(Model.SectionTable);
|
||||
if (address == 0 || size == 0)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// Get the archive count
|
||||
int archiveCount = this.Model.DirectoryItems == null
|
||||
int archiveCount = Model.DirectoryItems == null
|
||||
? 0
|
||||
: this.Model.DirectoryItems
|
||||
: Model.DirectoryItems
|
||||
.Select(di => di?.DirectoryEntry)
|
||||
.Select(de => de?.ArchiveIndex ?? 0)
|
||||
.Where(ai => ai != HL_VPK_NO_ARCHIVE)
|
||||
|
||||
@@ -29,6 +29,11 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
protected DataSource _dataSource = DataSource.UNKNOWN;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for reading from the source
|
||||
/// </summary>
|
||||
private readonly object _streamDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Source byte array data
|
||||
/// </summary>
|
||||
@@ -86,7 +91,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
|
||||
this.Model = model;
|
||||
Model = model;
|
||||
_dataSource = DataSource.ByteArray;
|
||||
_byteArrayData = data;
|
||||
_byteArrayOffset = offset;
|
||||
@@ -104,7 +109,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (data.Length == 0 || !data.CanSeek || !data.CanRead)
|
||||
throw new ArgumentOutOfRangeException(nameof(data));
|
||||
|
||||
this.Model = model;
|
||||
Model = model;
|
||||
_dataSource = DataSource.Stream;
|
||||
_streamData = data;
|
||||
}
|
||||
@@ -193,11 +198,14 @@ namespace SabreTools.Serialization.Wrappers
|
||||
break;
|
||||
|
||||
case DataSource.Stream:
|
||||
long currentLocation = _streamData!.Position;
|
||||
_streamData.Seek(position, SeekOrigin.Begin);
|
||||
sectionData = _streamData.ReadBytes(length);
|
||||
_streamData.Seek(currentLocation, SeekOrigin.Begin);
|
||||
break;
|
||||
lock (_streamDataLock)
|
||||
{
|
||||
long currentLocation = _streamData!.Position;
|
||||
_streamData.Seek(position, SeekOrigin.Begin);
|
||||
sectionData = _streamData.ReadBytes(length);
|
||||
_streamData.Seek(currentLocation, SeekOrigin.Begin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sectionData;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
var publisherIdentifier = this.Model.PublisherIdentifier;
|
||||
var publisherIdentifier = Model.PublisherIdentifier;
|
||||
if (string.IsNullOrEmpty(publisherIdentifier))
|
||||
return "Unknown";
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
var regionIdentifier = this.Model.RegionIdentifier;
|
||||
var regionIdentifier = Model.RegionIdentifier;
|
||||
if (Regions.ContainsKey(regionIdentifier))
|
||||
return Regions[regionIdentifier];
|
||||
|
||||
@@ -51,12 +51,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <summary>
|
||||
/// Get the human-readable serial string
|
||||
/// </summary>
|
||||
public string Serial => $"{this.Model.PublisherIdentifier}-{this.Model.GameID}";
|
||||
public string Serial => $"{Model.PublisherIdentifier}-{Model.GameID}";
|
||||
|
||||
/// <summary>
|
||||
/// Get the human-readable version string
|
||||
/// </summary>
|
||||
public string Version => $"1.{this.Model.VersionNumber}";
|
||||
public string Version => $"1.{Model.VersionNumber}";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
char mediaSubtype = this.Model.MediaSubtypeIdentifier;
|
||||
char mediaSubtype = Model.MediaSubtypeIdentifier;
|
||||
if (MediaSubtypes.ContainsKey(mediaSubtype))
|
||||
return MediaSubtypes[mediaSubtype];
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
var publisherIdentifier = this.Model.PublisherIdentifier;
|
||||
var publisherIdentifier = Model.PublisherIdentifier;
|
||||
if (string.IsNullOrEmpty(publisherIdentifier))
|
||||
return "Unknown";
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
var regionIdentifier = this.Model.RegionIdentifier;
|
||||
var regionIdentifier = Model.RegionIdentifier;
|
||||
if (Regions.ContainsKey(regionIdentifier))
|
||||
return Regions[regionIdentifier];
|
||||
|
||||
@@ -66,12 +66,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <summary>
|
||||
/// Get the human-readable serial string
|
||||
/// </summary>
|
||||
public string Serial => $"{this.Model.PublisherIdentifier}-{this.Model.PlatformIdentifier}{this.Model.GameID}";
|
||||
public string Serial => $"{Model.PublisherIdentifier}-{Model.PlatformIdentifier}{Model.GameID}";
|
||||
|
||||
/// <summary>
|
||||
/// Get the human-readable version string
|
||||
/// </summary>
|
||||
public string Version => $"1.{this.Model.SKU}";
|
||||
public string Version => $"1.{Model.SKU}";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
Reference in New Issue
Block a user