diff --git a/SabreTools.Serialization/Deserializers/PortableExecutable.cs b/SabreTools.Serialization/Deserializers/PortableExecutable.cs index f5e59f36..87220078 100644 --- a/SabreTools.Serialization/Deserializers/PortableExecutable.cs +++ b/SabreTools.Serialization/Deserializers/PortableExecutable.cs @@ -275,6 +275,9 @@ namespace SabreTools.Serialization.Deserializers int tableOffset = 0; pex.ResourceDirectoryTable = ParseResourceDirectoryTable(tableData, ref tableOffset); + // Parse the resource data, if possible + ParseResourceData(data, initialOffset, pex.ResourceDirectoryTable, pex.SectionTable); + #region Hidden Resources // If we have not used up the full size, parse the remaining chunk as a single resource @@ -1513,6 +1516,36 @@ namespace SabreTools.Serialization.Deserializers return obj; } + /// + /// Fill in resource data + /// + /// Stream to parse + /// Initial offset to use in address comparisons + /// Resource table to fill in + /// Section table to use for virtual address translation + /// Filled ResourceDataEntry on success, null on error + public static void ParseResourceData(Stream data, long initialOffset, ResourceDirectoryTable? table, SectionHeader[] sections) + { + if (table?.Entries == null) + return; + + foreach (var entry in table.Entries) + { + // Handle directory entries directly + if (entry.DataEntry != null && entry.DataEntry.Size > 0) + { + // Read the data from the offset + long dataOffset = initialOffset + entry.DataEntry.DataRVA.ConvertVirtualAddress(sections); + if (dataOffset > initialOffset && dataOffset + entry.DataEntry.Size < data.Length) + entry.DataEntry.Data = data.ReadFrom(dataOffset, (int)entry.DataEntry.Size, retainPosition: true); + } + + // Handle subdirectories by recursion + else if (entry.Subdirectory != null) + ParseResourceData(data, initialOffset, entry.Subdirectory, sections); + } + } + /// /// Parse a byte array into an ResourceDataEntry /// @@ -1528,17 +1561,6 @@ namespace SabreTools.Serialization.Deserializers obj.Codepage = data.ReadUInt32LittleEndian(ref offset); obj.Reserved = data.ReadUInt32LittleEndian(ref offset); - // Ignore empty resources - if (obj.Size == 0) - return obj; - - // Read the data from the offset - if (obj.DataRVA > 0 && obj.DataRVA + obj.Size < data.Length) - { - int dataOffset = (int)obj.DataRVA; - obj.Data = data.ReadBytes(ref dataOffset, (int)obj.Size); - } - return obj; }