diff --git a/BurnOutSharp.Builders/PortableExecutable.cs b/BurnOutSharp.Builders/PortableExecutable.cs
index 2908b4fc..d34a116b 100644
--- a/BurnOutSharp.Builders/PortableExecutable.cs
+++ b/BurnOutSharp.Builders/PortableExecutable.cs
@@ -300,7 +300,7 @@ namespace BurnOutSharp.Builders
// Try to parse the resource directory table
data.Seek(resourceTableAddress, SeekOrigin.Begin);
- var resourceDirectoryTable = ParseResourceDirectoryTable(data, data.Position, executable.SectionTable);
+ var resourceDirectoryTable = ParseResourceDirectoryTable(data, data.Position, executable.SectionTable, optionalHeader.ResourceTable.Size, true);
if (resourceDirectoryTable == null)
return null;
@@ -1195,8 +1195,10 @@ namespace BurnOutSharp.Builders
/// Stream to parse
/// Initial offset to use in address comparisons
/// Section table to use for virtual address translation
+ /// Indicates the size of the section, only used for top-level
+ /// Indicates if this is the top level or not
/// Filled resource directory table on success, null on error
- private static ResourceDirectoryTable ParseResourceDirectoryTable(Stream data, long initialOffset, SectionHeader[] sections)
+ private static ResourceDirectoryTable ParseResourceDirectoryTable(Stream data, long initialOffset, SectionHeader[] sections, uint size = 0, bool topLevel = false)
{
// TODO: Use marshalling here instead of building
var resourceDirectoryTable = new ResourceDirectoryTable();
@@ -1287,6 +1289,34 @@ namespace BurnOutSharp.Builders
}
}
+ // If we are not at the top level
+ if (!topLevel)
+ return resourceDirectoryTable;
+
+ // Align to the 1024-byte boundary
+ while (data.Position - initialOffset < size && data.Position % 1024 != 0)
+ _ = data.ReadByteValue();
+
+ // If we have not used up the full size, parse the remaining chunk as a single resource
+ if (data.Position - initialOffset < size)
+ {
+ Array.Resize(ref resourceDirectoryTable.Entries, totalEntryCount + 1);
+ int length = (int)(data.Position - initialOffset);
+
+ resourceDirectoryTable.Entries[totalEntryCount] = new ResourceDirectoryEntry
+ {
+ Name = new ResourceDirectoryString { UnicodeString = Encoding.ASCII.GetBytes("HIDDEN RESOURCE") },
+ IntegerID = uint.MaxValue,
+ DataEntryOffset = (uint)data.Position,
+ DataEntry = new ResourceDataEntry
+ {
+ Size = (uint)length,
+ Data = data.ReadBytes(length),
+ Codepage = (uint)Encoding.Unicode.CodePage,
+ },
+ };
+ }
+
return resourceDirectoryTable;
}
diff --git a/BurnOutSharp.Wrappers/PortableExecutable.cs b/BurnOutSharp.Wrappers/PortableExecutable.cs
index 15d2fbff..b02af082 100644
--- a/BurnOutSharp.Wrappers/PortableExecutable.cs
+++ b/BurnOutSharp.Wrappers/PortableExecutable.cs
@@ -563,23 +563,26 @@ namespace BurnOutSharp.Wrappers
{
get
{
- // Use the cached data if possible
- if (_sectionNames != null)
- return _sectionNames;
-
- // Otherwise, build and return the cached array
- _sectionNames = new string[_executable.SectionTable.Length];
- for (int i = 0; i < _sectionNames.Length; i++)
+ lock (_sourceDataLock)
{
- var section = _executable.SectionTable[i];
+ // Use the cached data if possible
+ if (_sectionNames != null)
+ return _sectionNames;
- // TODO: Handle long section names with leading `/`
- byte[] sectionNameBytes = section.Name;
- string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0');
- _sectionNames[i] = sectionNameString;
+ // Otherwise, build and return the cached array
+ _sectionNames = new string[_executable.SectionTable.Length];
+ for (int i = 0; i < _sectionNames.Length; i++)
+ {
+ var section = _executable.SectionTable[i];
+
+ // TODO: Handle long section names with leading `/`
+ byte[] sectionNameBytes = section.Name;
+ string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0');
+ _sectionNames[i] = sectionNameString;
+ }
+
+ return _sectionNames;
}
-
- return _sectionNames;
}
}
@@ -3117,7 +3120,7 @@ namespace BurnOutSharp.Wrappers
///
private void ParseResourceDirectoryTable(Models.PortableExecutable.ResourceDirectoryTable table, List