Update ASN1 to 1.4.1 and IO to 1.5.1

This commit is contained in:
Matt Nadareski
2024-11-15 22:22:22 -05:00
parent d7eba27dc5
commit 511c4d09e5
6 changed files with 261 additions and 110 deletions

View File

@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
#if NET35_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
using System.Text;
using SabreTools.IO.Extensions;
using SabreTools.Models.PortableExecutable;
@@ -1052,28 +1054,62 @@ namespace SabreTools.Serialization.Deserializers
// If we have import lookup tables
if (importTable.ImportLookupTables != null && importLookupTables.Count > 0)
{
#if NET20
var addresses = new List<int>();
foreach (var kvp in importTable.ImportLookupTables)
{
if (kvp.Value == null)
continue;
var vaddrs = Array.ConvertAll(kvp.Value,
ilte => ilte == null ? 0 : (int)ilte.HintNameTableRVA.ConvertVirtualAddress(sections));
addresses.AddRange(vaddrs);
}
#else
var addresses = importTable.ImportLookupTables
.SelectMany(kvp => kvp.Value ?? [])
.Where(ilte => ilte != null)
.Select(ilte => (int)ilte!.HintNameTableRVA.ConvertVirtualAddress(sections));
#endif
hintNameTableEntryAddresses.AddRange(addresses);
}
// If we have import address tables
if (importTable.ImportAddressTables != null && importTable.ImportAddressTables.Count > 0)
{
#if NET20
var addresses = new List<int>();
foreach (var kvp in importTable.ImportAddressTables)
{
if (kvp.Value == null)
continue;
var vaddrs = Array.ConvertAll(kvp.Value,
iate => iate == null ? 0 : (int)iate.HintNameTableRVA.ConvertVirtualAddress(sections));
addresses.AddRange(vaddrs);
}
#else
var addresses = importTable.ImportAddressTables
.SelectMany(kvp => kvp.Value ?? [])
.Where(iate => iate != null)
.Select(iate => (int)iate!.HintNameTableRVA.ConvertVirtualAddress(sections));
#endif
hintNameTableEntryAddresses.AddRange(addresses);
}
// Sanitize the addresses
hintNameTableEntryAddresses = hintNameTableEntryAddresses.Where(addr => addr != 0)
.Distinct()
.OrderBy(a => a)
.ToList();
hintNameTableEntryAddresses = hintNameTableEntryAddresses.FindAll(addr => addr != 0);
#if NET20
var temp = new List<int>();
foreach (int value in hintNameTableEntryAddresses)
{
if (!temp.Contains(value))
temp.Add(value);
}
#else
hintNameTableEntryAddresses = hintNameTableEntryAddresses.Distinct().ToList();
#endif
hintNameTableEntryAddresses.Sort();
// If we have any addresses, add them to the table
if (hintNameTableEntryAddresses.Count > 0)
@@ -1214,11 +1250,12 @@ namespace SabreTools.Serialization.Deserializers
return resourceDirectoryTable;
// If we're not aligned to a section
if (!sections.Any(s => s != null && s.PointerToRawData == initialOffset))
var firstSection = Array.Find(sections, s => s != null && s.PointerToRawData == initialOffset);
if (firstSection == null)
return resourceDirectoryTable;
// Get the section size
int size = (int)sections.First(s => s != null && s.PointerToRawData == initialOffset)!.SizeOfRawData;
int size = (int)firstSection.SizeOfRawData;
// Align to the 512-byte boundary, we find the start of an MS-DOS header, or the end of the file
while (data.Position - initialOffset < size && data.Position % 0x200 != 0 && data.Position < data.Length - 1)

View File

@@ -0,0 +1,9 @@
#if NET20
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
internal sealed class ExtensionAttribute : Attribute {}
}
#endif

View File

@@ -28,16 +28,11 @@
<None Include="../README.md" Pack="true" PackagePath="" />
</ItemGroup>
<!-- Support for old .NET versions -->
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`))">
<PackageReference Include="Net30.LinqBridge" Version="1.3.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SabreTools.ASN1" Version="1.4.0" />
<PackageReference Include="SabreTools.ASN1" Version="1.4.1" />
<PackageReference Include="SabreTools.Hashing" Version="1.4.0" />
<PackageReference Include="SabreTools.IO" Version="1.5.0" />
<PackageReference Include="SabreTools.IO" Version="1.5.1" />
<PackageReference Include="SabreTools.Models" Version="1.5.1" />
</ItemGroup>

View File

@@ -1,5 +1,5 @@
using System;
using System.IO;
using System.Linq;
using SabreTools.Models.InstallShieldCabinet;
namespace SabreTools.Serialization.Wrappers
@@ -289,7 +289,7 @@ namespace SabreTools.Serialization.Wrappers
if (Model.FileGroups == null)
return null;
return Model.FileGroups.FirstOrDefault(fg => fg != null && string.Equals(fg.Name, name));
return Array.Find(Model.FileGroups, fg => fg != null && string.Equals(fg.Name, name));
}
/// <summary>

View File

@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
#if NET35_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
using System.Text;
using SabreTools.IO.Extensions;
@@ -41,10 +43,17 @@ namespace SabreTools.Serialization.Wrappers
// Populate the raw header padding data based on the source
uint headerStartAddress = Model.Stub.Header.NewExeHeaderAddr;
uint firstSectionAddress = Model.SectionTable
.Select(s => s?.PointerToRawData ?? 0)
.Where(s => s != 0 && s >= headerStartAddress)
.Min();
uint firstSectionAddress = uint.MaxValue;
foreach (var s in Model.SectionTable)
{
if (s == null || s.PointerToRawData == 0)
continue;
if (s.PointerToRawData < headerStartAddress)
continue;
if (s.PointerToRawData < firstSectionAddress)
firstSectionAddress = s.PointerToRawData;
}
// Check if the header length is more than 0 before reading data
int headerLength = (int)(firstSectionAddress - headerStartAddress);
@@ -82,10 +91,17 @@ namespace SabreTools.Serialization.Wrappers
// 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 && s >= headerStartAddress)
.Min();
uint firstSectionAddress = uint.MaxValue;
foreach (var s in Model.SectionTable)
{
if (s == null || s.PointerToRawData == 0)
continue;
if (s.PointerToRawData < headerStartAddress)
continue;
if (s.PointerToRawData < firstSectionAddress)
firstSectionAddress = s.PointerToRawData;
}
// Check if the header length is more than 0 before reading strings
int headerLength = (int)(firstSectionAddress - headerStartAddress);
@@ -643,10 +659,9 @@ namespace SabreTools.Serialization.Wrappers
get
{
var manifest = GetAssemblyManifest();
return manifest?
.AssemblyIdentities?
.FirstOrDefault(ai => !string.IsNullOrEmpty(ai?.Version))?
.Version;
var identities = manifest?.AssemblyIdentities ?? [];
var versionIdentity = Array.Find(identities, ai => !string.IsNullOrEmpty(ai?.Version));
return versionIdentity?.Version;
}
}
@@ -837,9 +852,22 @@ namespace SabreTools.Serialization.Wrappers
return null;
// Try to find a key that matches
#if NET20
Models.PortableExecutable.StringData? match = null;
foreach (var st in stringTable)
{
if (st?.Children == null)
continue;
match = Array.Find(st.Children, sd => sd != null && key.Equals(sd.Key, StringComparison.OrdinalIgnoreCase));
if (match != null)
break;
}
#else
var match = stringTable
.SelectMany(st => st?.Children ?? [])
.FirstOrDefault(sd => sd != null && key.Equals(sd.Key, StringComparison.OrdinalIgnoreCase));
#endif
// Return either the match or null
return match?.Value?.TrimEnd('\0');
@@ -878,19 +906,29 @@ namespace SabreTools.Serialization.Wrappers
if (DebugData == null)
return [];
var nb10Found = DebugData.Select(r => r.Value)
.Select(r => r as SabreTools.Models.PortableExecutable.NB10ProgramDatabase)
.Where(n => n != null)
.Where(n => n?.PdbFileName?.Contains(path) == true)
.Select(n => n as object);
var debugFound = new List<object?>();
foreach (var data in DebugData.Values)
{
if (data == null)
continue;
var rsdsFound = DebugData.Select(r => r.Value)
.Select(r => r as SabreTools.Models.PortableExecutable.RSDSProgramDatabase)
.Where(r => r != null)
.Where(r => r?.PathAndFileName?.Contains(path) == true)
.Select(r => r as object);
if (data is Models.PortableExecutable.NB10ProgramDatabase n)
{
if (n.PdbFileName == null || !n.PdbFileName.Contains(path))
continue;
return nb10Found.Concat(rsdsFound);
debugFound.Add(n);
}
else if (data is Models.PortableExecutable.RSDSProgramDatabase r)
{
if (r.PathAndFileName == null || !r.PathAndFileName.Contains(path))
continue;
debugFound.Add(r);
}
}
return debugFound;
}
/// <summary>
@@ -904,37 +942,49 @@ namespace SabreTools.Serialization.Wrappers
if (DebugData == null)
return [];
return DebugData.Select(r => r.Value)
.Select(b => b as byte[])
.Where(b => b != null)
.Where(b =>
var table = new List<byte[]?>();
foreach (var data in DebugData.Values)
{
if (data == null)
continue;
if (data is not byte[] b || b == null)
continue;
try
{
try
string? arrayAsASCII = Encoding.ASCII.GetString(b);
if (arrayAsASCII.Contains(value))
{
string? arrayAsASCII = Encoding.ASCII.GetString(b!);
if (arrayAsASCII.Contains(value))
return true;
table.Add(b);
continue;
}
catch { }
}
catch { }
try
try
{
string? arrayAsUTF8 = Encoding.UTF8.GetString(b);
if (arrayAsUTF8.Contains(value))
{
string? arrayAsUTF8 = Encoding.UTF8.GetString(b!);
if (arrayAsUTF8.Contains(value))
return true;
table.Add(b);
continue;
}
catch { }
}
catch { }
try
try
{
string? arrayAsUnicode = Encoding.Unicode.GetString(b);
if (arrayAsUnicode.Contains(value))
{
string? arrayAsUnicode = Encoding.Unicode.GetString(b!);
if (arrayAsUnicode.Contains(value))
return true;
table.Add(b);
continue;
}
catch { }
}
catch { }
}
return false;
});
return table;
}
#endregion
@@ -1027,14 +1077,21 @@ namespace SabreTools.Serialization.Wrappers
if (ResourceData == null)
return [];
return ResourceData.Select(r => r.Value)
.Select(r => r as SabreTools.Models.PortableExecutable.DialogBoxResource)
.Where(d => d != null)
.Where(d =>
{
return (d?.DialogTemplate?.TitleResource?.Contains(title) ?? false)
|| (d?.ExtendedDialogTemplate?.TitleResource?.Contains(title) ?? false);
});
var resources = new List<Models.PortableExecutable.DialogBoxResource?>();
foreach (var resource in ResourceData.Values)
{
if (resource == null)
continue;
if (resource is not Models.PortableExecutable.DialogBoxResource dbr || dbr == null)
continue;
if (dbr.DialogTemplate?.TitleResource?.Contains(title) ?? false)
resources.Add(dbr);
else if (dbr.ExtendedDialogTemplate?.TitleResource?.Contains(title) ?? false)
resources.Add(dbr);
}
return resources;
}
/// <summary>
@@ -1048,26 +1105,29 @@ namespace SabreTools.Serialization.Wrappers
if (ResourceData == null)
return [];
return ResourceData.Select(r => r.Value)
.Select(r => r as SabreTools.Models.PortableExecutable.DialogBoxResource)
.Where(d => d != null)
.Where(d =>
{
if (d?.DialogItemTemplates != null)
{
return d.DialogItemTemplates
.Where(dit => dit?.TitleResource != null)
.Any(dit => dit?.TitleResource?.Contains(title) == true);
}
else if (d?.ExtendedDialogItemTemplates != null)
{
return d.ExtendedDialogItemTemplates
.Where(edit => edit?.TitleResource != null)
.Any(edit => edit?.TitleResource?.Contains(title) == true);
}
var resources = new List<Models.PortableExecutable.DialogBoxResource?>();
foreach (var resource in ResourceData.Values)
{
if (resource == null)
continue;
if (resource is not Models.PortableExecutable.DialogBoxResource dbr || dbr == null)
continue;
return false;
});
if (dbr.DialogItemTemplates != null)
{
var templates = Array.FindAll(dbr.DialogItemTemplates, dit => dit?.TitleResource != null);
if (Array.FindIndex(templates, dit => dit?.TitleResource?.Contains(title) == true) > -1)
resources.Add(dbr);
}
else if (dbr.ExtendedDialogItemTemplates != null)
{
var templates = Array.FindAll(dbr.ExtendedDialogItemTemplates, edit => edit?.TitleResource != null);
if (Array.FindIndex(templates, edit => edit?.TitleResource?.Contains(title) == true) > -1)
resources.Add(dbr);
}
}
return resources;
}
/// <summary>
@@ -1081,11 +1141,26 @@ namespace SabreTools.Serialization.Wrappers
if (ResourceData == null)
return [];
return ResourceData.Select(r => r.Value)
#if NET20
var stringTables = new List<Dictionary<int, string?>?>();
foreach (var resource in ResourceData.Values)
{
if (resource == null)
continue;
if (resource is not Dictionary<int, string?> st || st == null)
continue;
}
return stringTables;
#else
return ResourceData.Values
.Select(r => r as Dictionary<int, string?>)
.Where(st => st != null)
.Where(st => st?.Select(kvp => kvp.Value)?
.Any(s => s != null && s.Contains(entry)) == true);
#endif
}
/// <summary>
@@ -1099,9 +1174,24 @@ namespace SabreTools.Serialization.Wrappers
if (ResourceData == null)
return [];
#if NET20
var resources = new List<byte[]?>();
foreach (var kvp in ResourceData)
{
if (!kvp.Key.Contains(typeName))
continue;
if (kvp.Value == null || kvp.Value is not byte[] b || b == null)
continue;
resources.Add(b);
}
return resources;
#else
return ResourceData.Where(kvp => kvp.Key.Contains(typeName))
.Select(kvp => kvp.Value as byte[])
.Where(b => b != null);
#endif
}
/// <summary>
@@ -1115,37 +1205,49 @@ namespace SabreTools.Serialization.Wrappers
if (ResourceData == null)
return [];
return ResourceData.Select(r => r.Value)
.Select(r => r as byte[])
.Where(b => b != null)
.Where(b =>
var resources = new List<byte[]?>();
foreach (var resource in ResourceData.Values)
{
if (resource == null)
continue;
if (resource is not byte[] b || b == null)
continue;
try
{
try
string? arrayAsASCII = Encoding.ASCII.GetString(b!);
if (arrayAsASCII.Contains(value))
{
string? arrayAsASCII = Encoding.ASCII.GetString(b!);
if (arrayAsASCII.Contains(value))
return true;
resources.Add(b);
continue;
}
catch { }
}
catch { }
try
try
{
string? arrayAsUTF8 = Encoding.UTF8.GetString(b!);
if (arrayAsUTF8.Contains(value))
{
string? arrayAsUTF8 = Encoding.UTF8.GetString(b!);
if (arrayAsUTF8.Contains(value))
return true;
resources.Add(b);
continue;
}
catch { }
}
catch { }
try
try
{
string? arrayAsUnicode = Encoding.Unicode.GetString(b!);
if (arrayAsUnicode.Contains(value))
{
string? arrayAsUnicode = Encoding.Unicode.GetString(b!);
if (arrayAsUnicode.Contains(value))
return true;
resources.Add(b);
continue;
}
catch { }
}
catch { }
}
return false;
});
return resources;
}
#endregion
@@ -1321,11 +1423,11 @@ namespace SabreTools.Serialization.Wrappers
// If we're checking exactly, return only exact matches
if (exact)
return SectionNames.Any(n => n.Equals(sectionName));
return Array.FindIndex(SectionNames, n => n.Equals(sectionName)) > -1;
// Otherwise, check if section name starts with the value
else
return SectionNames.Any(n => n.StartsWith(sectionName));
return Array.FindIndex(SectionNames, n => n.StartsWith(sectionName)) > -1;
}
/// <summary>

View File

@@ -259,14 +259,22 @@ namespace SabreTools.Serialization.Wrappers
/// <param name="encoding">Character encoding to use for checking</param>
/// <returns>String list containing the requested data, empty on error</returns>
/// <remarks>TODO: Move to IO?</remarks>
#if NET20
private List<string> ReadStringsWithEncoding(byte[] sourceData, int charLimit, Encoding encoding)
#else
private HashSet<string> ReadStringsWithEncoding(byte[] sourceData, int charLimit, Encoding encoding)
#endif
{
// If we have an invalid character limit, default to 5
if (charLimit <= 0)
charLimit = 5;
// Create the string hash set to return
#if NET20
var sourceStrings = new List<string>();
#else
var sourceStrings = new HashSet<string>();
#endif
// Setup cached data
int sourceDataIndex = 0;