diff --git a/BurnOutSharp.Wrappers/PortableExecutable.cs b/BurnOutSharp.Wrappers/PortableExecutable.cs
index 715ff7de..d68b5363 100644
--- a/BurnOutSharp.Wrappers/PortableExecutable.cs
+++ b/BurnOutSharp.Wrappers/PortableExecutable.cs
@@ -683,6 +683,11 @@ namespace BurnOutSharp.Wrappers
///
private byte[][] _sectionData = null;
+ ///
+ /// Cached found string data in sections
+ ///
+ private List[] _sectionStringData = null;
+
///
/// Cached resource data
///
@@ -3183,6 +3188,145 @@ namespace BurnOutSharp.Wrappers
}
}
+ ///
+ /// Get the first section strings based on name, if possible
+ ///
+ /// Name of the section to check for
+ /// True to enable exact matching of names, false for starts-with
+ /// Section strings on success, null on error
+ public List GetFirstSectionStrings(string name, bool exact = false)
+ {
+ // If we have no sections
+ if (SectionTable == null || !SectionTable.Any())
+ return null;
+
+ // If the section doesn't exist
+ if (!ContainsSection(name, exact))
+ return null;
+
+ // Get the first index of the section
+ int index = Array.IndexOf(SectionNames, name);
+ if (index == -1)
+ return null;
+
+ // Get the section data from the table
+ var section = SectionTable[index];
+ uint address = section.VirtualAddress.ConvertVirtualAddress(SectionTable);
+ if (address == 0)
+ return null;
+
+ // Set the section size
+ uint size = section.SizeOfRawData;
+ lock (_sourceDataLock)
+ {
+ // Create the section string array if we have to
+ if (_sectionStringData == null)
+ _sectionStringData = new List[SectionNames.Length];
+
+ // If we already have cached data, just use that immediately
+ if (_sectionStringData[index] != null)
+ return _sectionStringData[index];
+
+ // Populate the section string data based on the source
+ List sectionStringData = ReadStringsFromDataSource((int)address, (int)size);
+
+ // Cache and return the section string data, even if null
+ _sectionStringData[index] = sectionStringData;
+ return sectionStringData;
+ }
+ }
+
+ ///
+ /// Get the last section strings based on name, if possible
+ ///
+ /// Name of the section to check for
+ /// True to enable exact matching of names, false for starts-with
+ /// Section strings on success, null on error
+ public List GetLastSectionStrings(string name, bool exact = false)
+ {
+ // If we have no sections
+ if (SectionTable == null || !SectionTable.Any())
+ return null;
+
+ // If the section doesn't exist
+ if (!ContainsSection(name, exact))
+ return null;
+
+ // Get the last index of the section
+ int index = Array.LastIndexOf(SectionNames, name);
+ if (index == -1)
+ return null;
+
+ // Get the section data from the table
+ var section = SectionTable[index];
+ uint address = section.VirtualAddress.ConvertVirtualAddress(SectionTable);
+ if (address == 0)
+ return null;
+
+ // Set the section size
+ uint size = section.SizeOfRawData;
+ lock (_sourceDataLock)
+ {
+ // Create the section string array if we have to
+ if (_sectionStringData == null)
+ _sectionStringData = new List[SectionNames.Length];
+
+ // If we already have cached data, just use that immediately
+ if (_sectionStringData[index] != null)
+ return _sectionStringData[index];
+
+ // Populate the section string data based on the source
+ List sectionStringData = ReadStringsFromDataSource((int)address, (int)size);
+
+ // Cache and return the section string data, even if null
+ _sectionStringData[index] = sectionStringData;
+ return sectionStringData;
+ }
+ }
+
+ ///
+ /// Get the section strings based on index, if possible
+ ///
+ /// Name of the section to check for
+ /// True to enable exact matching of names, false for starts-with
+ /// Section strings on success, null on error
+ public List GetSectionStrings(int index)
+ {
+ // If we have no sections
+ if (SectionTable == null || !SectionTable.Any())
+ return null;
+
+ // If the section doesn't exist
+ if (index < 0 || index >= SectionTable.Length)
+ return null;
+
+ // Get the section data from the table
+ var section = SectionTable[index];
+ uint address = section.VirtualAddress.ConvertVirtualAddress(SectionTable);
+ if (address == 0)
+ return null;
+
+ // Set the section size
+ uint size = section.SizeOfRawData;
+ lock (_sourceDataLock)
+ {
+ // Create the section string array if we have to
+ if (_sectionStringData == null)
+ _sectionStringData = new List[SectionNames.Length];
+
+ // If we already have cached data, just use that immediately
+ if (_sectionStringData[index] != null)
+ return _sectionStringData[index];
+
+ // Populate the section string data based on the source
+ List sectionStringData = ReadStringsFromDataSource((int)address, (int)size);
+
+ // Cache and return the section string data, even if null
+ _sectionStringData[index] = sectionStringData;
+ return sectionStringData;
+ }
+ }
+
#endregion
}
}
\ No newline at end of file
diff --git a/BurnOutSharp.Wrappers/WrapperBase.cs b/BurnOutSharp.Wrappers/WrapperBase.cs
index ca4dd15e..f776dc5f 100644
--- a/BurnOutSharp.Wrappers/WrapperBase.cs
+++ b/BurnOutSharp.Wrappers/WrapperBase.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using static BurnOutSharp.Builder.Extensions;
@@ -93,7 +94,7 @@ namespace BurnOutSharp.Wrappers
/// Byte array containing the requested data, null on error
protected byte[] ReadFromDataSource(int position, int length)
{
- // Validate the data souece
+ // Validate the data source
if (!DataSourceIsValid())
return null;
@@ -121,6 +122,23 @@ namespace BurnOutSharp.Wrappers
return sectionData;
}
+ ///
+ /// Read string data from the source
+ ///
+ /// Position in the source to read from
+ /// Length of the requested data
+ /// String list containing the requested data, null on error
+ protected List ReadStringsFromDataSource(int position, int length)
+ {
+ // Read the data as a byte array first
+ byte[] sourceData = ReadFromDataSource(position, length);
+ if (sourceData == null)
+ return null;
+
+ // TODO: Complete implementation of string finding
+ return null;
+ }
+
///
/// Get the ending offset of the source
///