mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-02-14 13:46:19 +00:00
Generic resource entry is now used
This commit is contained in:
@@ -3,7 +3,7 @@ namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
|
||||
/// <summary>
|
||||
/// Generic or unparsed resource data
|
||||
/// </summary>
|
||||
public abstract class GenericResourceEntry : ResourceDataType
|
||||
public class GenericResourceEntry : ResourceDataType
|
||||
{
|
||||
/// <summary>
|
||||
/// Unparsed byte data from the resource
|
||||
|
||||
@@ -10,6 +10,6 @@ namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
|
||||
/// <summary>
|
||||
/// Set of integer-keyed values
|
||||
/// </summary>
|
||||
public Dictionary<int, string?> Values { get; set; } = [];
|
||||
public Dictionary<int, string?> Data { get; set; } = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1606,6 +1606,21 @@ namespace SabreTools.Serialization.Readers
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a GenericResourceEntry
|
||||
/// </summary>
|
||||
/// <param name="data">Data to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>A filled GenericResourceEntry on success, null on error</returns>
|
||||
public static Data.Models.PortableExecutable.Resource.Entries.GenericResourceEntry ParseGenericResourceEntry(byte[] data)
|
||||
{
|
||||
var obj = new Data.Models.PortableExecutable.Resource.Entries.GenericResourceEntry();
|
||||
|
||||
obj.Data = data;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a HintNameTable
|
||||
/// </summary>
|
||||
@@ -2930,7 +2945,7 @@ namespace SabreTools.Serialization.Readers
|
||||
if (stringValue is not null)
|
||||
{
|
||||
stringValue = stringValue.Replace("\n", "\\n").Replace("\r", newValue: "\\r");
|
||||
obj.Values[stringIndex++] = stringValue;
|
||||
obj.Data[stringIndex++] = stringValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -362,7 +362,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
string resourceKey = kvp.Key;
|
||||
var value = kvp.Value;
|
||||
|
||||
if (value is null || value is not byte[] ba || ba.Length == 0)
|
||||
if (value is null || value is not Data.Models.PortableExecutable.Resource.Entries.GenericResourceEntry ba || ba.Data.Length == 0)
|
||||
continue;
|
||||
|
||||
// Set the output variables
|
||||
@@ -370,10 +370,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
string extension = string.Empty;
|
||||
|
||||
// Only process the resource if it a recognized signature
|
||||
for (; resourceOffset < 0x400 && resourceOffset < ba.Length - 0x10; resourceOffset++)
|
||||
for (; resourceOffset < 0x400 && resourceOffset < ba.Data.Length - 0x10; resourceOffset++)
|
||||
{
|
||||
int temp = resourceOffset;
|
||||
byte[] resourceSample = ba.ReadBytes(ref temp, 0x10);
|
||||
byte[] resourceSample = ba.Data.ReadBytes(ref temp, 0x10);
|
||||
|
||||
if (resourceSample.StartsWith(Data.Models.SevenZip.Constants.SignatureBytes))
|
||||
{
|
||||
@@ -506,7 +506,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Write the resource data to a temp file
|
||||
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
tempStream.Write(ba, resourceOffset, ba.Length - resourceOffset);
|
||||
tempStream.Write(ba.Data, resourceOffset, ba.Data.Length - resourceOffset);
|
||||
tempStream.Flush();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -1293,7 +1293,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var kvp in stringTable.Values)
|
||||
foreach (var kvp in stringTable.Data)
|
||||
{
|
||||
int index = kvp.Key;
|
||||
string? stringValue = kvp.Value;
|
||||
|
||||
@@ -595,7 +595,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <summary>
|
||||
/// Dictionary of resource data
|
||||
/// </summary>
|
||||
public Dictionary<string, object?> ResourceData
|
||||
public Dictionary<string, ResourceDataType?> ResourceData
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -1122,7 +1122,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// <summary>
|
||||
/// Cached resource data
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, object?> _resourceData = [];
|
||||
private readonly Dictionary<string, ResourceDataType?> _resourceData = [];
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_resourceData"/>
|
||||
@@ -1588,22 +1588,22 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
/// <param name="entry">String entry to check for</param>
|
||||
/// <returns>List of matching resources</returns>
|
||||
public List<Dictionary<int, string?>?> FindStringTableByEntry(string entry)
|
||||
public List<StringTableResource?> FindStringTableByEntry(string entry)
|
||||
{
|
||||
// Cache the resource data for easier reading
|
||||
var resourceData = ResourceData;
|
||||
if (resourceData.Count == 0)
|
||||
return [];
|
||||
|
||||
var stringTables = new List<Dictionary<int, string?>?>();
|
||||
var stringTables = new List<StringTableResource?>();
|
||||
foreach (var resource in resourceData.Values)
|
||||
{
|
||||
if (resource is null)
|
||||
continue;
|
||||
if (resource is not Dictionary<int, string?> st || st is null)
|
||||
if (resource is not StringTableResource st || st is null)
|
||||
continue;
|
||||
|
||||
foreach (string? s in st.Values)
|
||||
foreach (string? s in st.Data.Values)
|
||||
{
|
||||
#if NETFRAMEWORK || NETSTANDARD
|
||||
if (s is null || !s.Contains(entry))
|
||||
@@ -1637,10 +1637,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
if (!kvp.Key.Contains(typeName))
|
||||
continue;
|
||||
if (kvp.Value is null || kvp.Value is not byte[] b || b is null)
|
||||
if (kvp.Value is null || kvp.Value is not GenericResourceEntry b || b is null)
|
||||
continue;
|
||||
|
||||
resources.Add(b);
|
||||
resources.Add(b.Data);
|
||||
}
|
||||
|
||||
return resources;
|
||||
@@ -1663,15 +1663,15 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
if (resource is null)
|
||||
continue;
|
||||
if (resource is not byte[] b || b is null)
|
||||
if (resource is not GenericResourceEntry b || b is null)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
string? arrayAsASCII = Encoding.ASCII.GetString(b!);
|
||||
string? arrayAsASCII = Encoding.ASCII.GetString(b!.Data);
|
||||
if (arrayAsASCII.Contains(value))
|
||||
{
|
||||
resources.Add(b);
|
||||
resources.Add(b.Data);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1679,10 +1679,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
try
|
||||
{
|
||||
string? arrayAsUTF8 = Encoding.UTF8.GetString(b!);
|
||||
string? arrayAsUTF8 = Encoding.UTF8.GetString(b!.Data);
|
||||
if (arrayAsUTF8.Contains(value))
|
||||
{
|
||||
resources.Add(b);
|
||||
resources.Add(b.Data);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1690,10 +1690,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
try
|
||||
{
|
||||
string? arrayAsUnicode = Encoding.Unicode.GetString(b!);
|
||||
string? arrayAsUnicode = Encoding.Unicode.GetString(b!.Data);
|
||||
if (arrayAsUnicode.Contains(value))
|
||||
{
|
||||
resources.Add(b);
|
||||
resources.Add(b.Data);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1770,9 +1770,9 @@ namespace SabreTools.Serialization.Wrappers
|
||||
bool exeResources = false;
|
||||
foreach (var kvp in resourceData)
|
||||
{
|
||||
if (kvp.Value is null || kvp.Value is not byte[] ba)
|
||||
if (kvp.Value is null || kvp.Value is not GenericResourceEntry ba)
|
||||
continue;
|
||||
if (!ba.StartsWith(Data.Models.MSDOS.Constants.SignatureBytes))
|
||||
if (!ba.Data.StartsWith(Data.Models.MSDOS.Constants.SignatureBytes))
|
||||
continue;
|
||||
|
||||
exeResources = true;
|
||||
@@ -1866,7 +1866,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
// Create the key and value objects
|
||||
string key = string.Join(", ", Array.ConvertAll([.. types], t => t.ToString()));
|
||||
|
||||
object? value = entry.Data;
|
||||
ResourceDataType? value = Readers.PortableExecutable.ParseGenericResourceEntry(entry.Data);
|
||||
|
||||
// If we have a known resource type
|
||||
if (types.Count > 0 && types[0] is uint resourceType)
|
||||
@@ -1876,14 +1876,14 @@ namespace SabreTools.Serialization.Wrappers
|
||||
switch ((ResourceType)resourceType)
|
||||
{
|
||||
case ResourceType.RT_CURSOR:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_BITMAP:
|
||||
case ResourceType.RT_NEWBITMAP:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_ICON:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_MENU:
|
||||
case ResourceType.RT_NEWMENU:
|
||||
@@ -1897,47 +1897,47 @@ namespace SabreTools.Serialization.Wrappers
|
||||
value = Readers.PortableExecutable.ParseStringTableResource(entry.Data);
|
||||
break;
|
||||
case ResourceType.RT_FONTDIR:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_FONT:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_ACCELERATOR:
|
||||
value = Readers.PortableExecutable.ParseAcceleratorTable(entry.Data);
|
||||
break;
|
||||
case ResourceType.RT_RCDATA:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_MESSAGETABLE:
|
||||
value = Readers.PortableExecutable.ParseMessageResourceData(entry.Data);
|
||||
break;
|
||||
case ResourceType.RT_GROUP_CURSOR:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_GROUP_ICON:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_VERSION:
|
||||
_versionInfo = Readers.PortableExecutable.ParseVersionInfo(entry.Data);
|
||||
value = _versionInfo;
|
||||
break;
|
||||
case ResourceType.RT_DLGINCLUDE:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_PLUGPLAY:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_VXD:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_ANICURSOR:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_ANIICON:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_HTML:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
case ResourceType.RT_MANIFEST:
|
||||
_assemblyManifest = Readers.PortableExecutable.ParseAssemblyManifest(entry.Data);
|
||||
@@ -1950,25 +1950,25 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Error state, ignore
|
||||
case ResourceType.RT_ERROR:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
|
||||
default:
|
||||
value = entry.Data;
|
||||
// TODO: Implement specific parsing
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Fall back on byte array data for malformed items
|
||||
value = entry.Data;
|
||||
value = Readers.PortableExecutable.ParseGenericResourceEntry(entry.Data);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a custom resource type
|
||||
else if (types.Count > 0 && types[0] is string)
|
||||
{
|
||||
value = entry.Data;
|
||||
value = Readers.PortableExecutable.ParseGenericResourceEntry(entry.Data);
|
||||
}
|
||||
|
||||
// Add the key and value to the cache
|
||||
|
||||
Reference in New Issue
Block a user