Fix resource parsing, fix MS-CAB SFX

This commit is contained in:
Matt Nadareski
2021-09-11 21:41:17 -07:00
parent 2c2aee6797
commit 7b71d7b4bf
9 changed files with 88 additions and 105 deletions

View File

@@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using BurnOutSharp.Tools;
@@ -37,7 +35,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
while ((r.Length = stream.ReadUInt16()) == 0x0000);
r.Length = stream.ReadUInt16();
r.ValueLength = stream.ReadUInt16();
r.Type = stream.ReadUInt16();
r.Key = stream.ReadString(Encoding.Unicode);
@@ -51,18 +48,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
while ((r.Length = content.ReadUInt16(ref offset)) == 0x0000);
offset += 2;
r.ValueLength = content.ReadUInt16(ref offset);
r.Type = content.ReadUInt16(ref offset);
List<char> keyChars = new List<char>();
while (BitConverter.ToUInt16(content, offset) != 0x0000)
{
keyChars.Add(Encoding.Unicode.GetChars(content, offset, 2)[0]); offset += 2;
}
offset += 2;
r.Key = new string(keyChars.ToArray());
r.Key = content.ReadString(ref offset, Encoding.Unicode);
return r;
}

View File

@@ -10,18 +10,21 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
/// </summary>
public StringTable Children;
public StringFileInfo(Resource resource)
{
this.Length = resource?.Length ?? default;
this.ValueLength = resource?.ValueLength ?? default;
this.Type = resource?.Type ?? default;
this.Key = resource?.Key ?? default;
}
public static new StringFileInfo Deserialize(Stream stream)
{
StringFileInfo sfi = new StringFileInfo();
Resource resource = Resource.Deserialize(stream);
if (resource.Key != "StringFileInfo")
return null;
sfi.Length = resource.Length;
sfi.ValueLength = resource.ValueLength;
sfi.Type = resource.Type;
sfi.Key = resource.Key;
StringFileInfo sfi = new StringFileInfo(resource);
sfi.Children = StringTable.Deserialize(stream);
return sfi;
@@ -29,16 +32,11 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
public static new StringFileInfo Deserialize(byte[] content, ref int offset)
{
StringFileInfo sfi = new StringFileInfo();
Resource resource = Resource.Deserialize(content, ref offset);
if (resource.Key != "StringFileInfo")
return null;
sfi.Length = resource.Length;
sfi.ValueLength = resource.ValueLength;
sfi.Type = resource.Type;
sfi.Key = resource.Key;
StringFileInfo sfi = new StringFileInfo(resource);
sfi.Children = StringTable.Deserialize(content, ref offset);
return sfi;

View File

@@ -11,16 +11,18 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
/// </summary>
public string Value;
public StringStruct(Resource resource)
{
this.Length = resource?.Length ?? default;
this.ValueLength = resource?.ValueLength ?? default;
this.Type = resource?.Type ?? default;
this.Key = resource?.Key ?? default;
}
public static new StringStruct Deserialize(Stream stream)
{
StringStruct s = new StringStruct();
Resource resource = Resource.Deserialize(stream);
s.Length = resource.Length;
s.ValueLength = resource.ValueLength;
s.Type = resource.Type;
s.Key = resource.Key;
StringStruct s = new StringStruct(resource);
stream.Seek(stream.Position % 4 == 0 ? 0 : 4 - (stream.Position % 4), SeekOrigin.Current);
s.Value = new string(stream.ReadChars(s.ValueLength));
@@ -29,14 +31,8 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
public static new StringStruct Deserialize(byte[] content, ref int offset)
{
StringStruct s = new StringStruct();
Resource resource = Resource.Deserialize(content, ref offset);
s.Length = resource.Length;
s.ValueLength = resource.ValueLength;
s.Type = resource.Type;
s.Key = resource.Key;
StringStruct s = new StringStruct(resource);
offset += offset % 4 == 0 ? 0 : 4 - (offset % 4);
s.Value = Encoding.Unicode.GetString(content, offset, s.ValueLength * 2); offset += s.ValueLength * 2;

View File

@@ -10,19 +10,22 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
/// </summary>
public StringStruct[] Children;
public StringTable(Resource resource)
{
this.Length = resource?.Length ?? default;
this.ValueLength = resource?.ValueLength ?? default;
this.Type = resource?.Type ?? default;
this.Key = resource?.Key ?? default;
}
public static new StringTable Deserialize(Stream stream)
{
long originalPosition = stream.Position;
StringTable st = new StringTable();
Resource resource = Resource.Deserialize(stream);
if (resource.Key.Length != 8)
return null;
st.Length = resource.Length;
st.ValueLength = resource.ValueLength;
st.Type = resource.Type;
st.Key = resource.Key;
StringTable st = new StringTable(resource);
var tempValue = new List<StringStruct>();
while (stream.Position - originalPosition < st.Length)
@@ -38,16 +41,11 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
public static new StringTable Deserialize(byte[] content, ref int offset)
{
int originalPosition = offset;
StringTable st = new StringTable();
Resource resource = Resource.Deserialize(content, ref offset);
if (resource.Key.Length != 8)
return null;
st.Length = resource.Length;
st.ValueLength = resource.ValueLength;
st.Type = resource.Type;
st.Key = resource.Key;
StringTable st = new StringTable(resource);
var tempValue = new List<StringStruct>();
while (offset - originalPosition < st.Length)

View File

@@ -16,19 +16,22 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
/// </summary>
public LanguageCodePage[] Value;
public Var(Resource resource)
{
this.Length = resource?.Length ?? default;
this.ValueLength = resource?.ValueLength ?? default;
this.Type = resource?.Type ?? default;
this.Key = resource?.Key ?? default;
}
public static new Var Deserialize(Stream stream)
{
long originalPosition = stream.Position;
Var v = new Var();
Resource resource = Resource.Deserialize(stream);
if (resource.Key != "Translation")
return null;
v.Length = resource.Length;
v.ValueLength = resource.ValueLength;
v.Type = resource.Type;
v.Key = resource.Key;
Var v = new Var(resource);
var tempValue = new List<LanguageCodePage>();
while (stream.Position - originalPosition < v.Length)
@@ -44,16 +47,11 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
public static new Var Deserialize(byte[] content, ref int offset)
{
int originalPosition = offset;
Var v = new Var();
Resource resource = Resource.Deserialize(content, ref offset);
if (resource.Key != "Translation")
return null;
v.Length = resource.Length;
v.ValueLength = resource.ValueLength;
v.Type = resource.Type;
v.Key = resource.Key;
Var v = new Var(resource);
var tempValue = new List<LanguageCodePage>();
while (offset - originalPosition < v.Length)

View File

@@ -9,18 +9,21 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
/// </summary>
public Var Children;
public VarFileInfo(Resource resource)
{
this.Length = resource?.Length ?? default;
this.ValueLength = resource?.ValueLength ?? default;
this.Type = resource?.Type ?? default;
this.Key = resource?.Key ?? default;
}
public static new VarFileInfo Deserialize(Stream stream)
{
VarFileInfo vfi = new VarFileInfo();
Resource resource = Resource.Deserialize(stream);
if (resource.Key != "VarFileInfo")
return null;
vfi.Length = resource.Length;
vfi.ValueLength = resource.ValueLength;
vfi.Type = resource.Type;
vfi.Key = resource.Key;
VarFileInfo vfi = new VarFileInfo(resource);
vfi.Children = Var.Deserialize(stream);
return vfi;
@@ -28,16 +31,11 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
public static new VarFileInfo Deserialize(byte[] content, ref int offset)
{
VarFileInfo vfi = new VarFileInfo();
Resource resource = Resource.Deserialize(content, ref offset);
if (resource.Key != "VarFileInfo")
return null;
vfi.Length = resource.Length;
vfi.ValueLength = resource.ValueLength;
vfi.Type = resource.Type;
vfi.Key = resource.Key;
VarFileInfo vfi = new VarFileInfo(resource);
vfi.Children = Var.Deserialize(content, ref offset);
return vfi;

View File

@@ -23,19 +23,22 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
/// </summary>
public VarFileInfo ChildrenVarFileInfo;
public VersionInfo(Resource resource)
{
this.Length = resource?.Length ?? default;
this.ValueLength = resource?.ValueLength ?? default;
this.Type = resource?.Type ?? default;
this.Key = resource?.Key ?? default;
}
public static new VersionInfo Deserialize(Stream stream)
{
long originalPosition = stream.Position;
VersionInfo vi = new VersionInfo();
Resource resource = Resource.Deserialize(stream);
if (resource.Key != "VS_VERSION_INFO")
return null;
vi.Length = resource.Length;
vi.ValueLength = resource.ValueLength;
vi.Type = resource.Type;
vi.Key = resource.Key;
VersionInfo vi = new VersionInfo(resource);
if (vi.ValueLength > 0)
vi.Value = FixedFileInfo.Deserialize(stream);
@@ -78,16 +81,11 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
public static new VersionInfo Deserialize(byte[] content, ref int offset)
{
int originalOffset = offset;
VersionInfo vi = new VersionInfo();
Resource resource = Resource.Deserialize(content, ref offset);
if (resource.Key != "VS_VERSION_INFO")
return null;
vi.Length = resource.Length;
vi.ValueLength = resource.ValueLength;
vi.Type = resource.Type;
vi.Key = resource.Key;
VersionInfo vi = new VersionInfo(resource);
if (vi.ValueLength > 0)
vi.Value = FixedFileInfo.Deserialize(content, ref offset);

View File

@@ -24,11 +24,11 @@ namespace BurnOutSharp.PackerType
string name = Utilities.GetInternalName(pex);
if (!string.IsNullOrWhiteSpace(name) && name.Equals("Wextract", StringComparison.OrdinalIgnoreCase))
return $"Microsoft CAB SFX v{Utilities.GetFileVersion(pex)}".TrimEnd('v');
return $"Microsoft CAB SFX {GetVersion(pex)}";
name = Utilities.GetOriginalFileName(pex);
if (!string.IsNullOrWhiteSpace(name) && name.Equals("WEXTRACT.EXE", StringComparison.OrdinalIgnoreCase))
return $"Microsoft CAB SFX v{Utilities.GetFileVersion(pex)}".TrimEnd('v');
return $"Microsoft CAB SFX {GetVersion(pex)}";
// Get the .data section, if it exists
if (pex.DataSectionRaw != null)
@@ -45,7 +45,7 @@ namespace BurnOutSharp.PackerType
string match = MatchUtil.GetFirstMatch(file, pex.DataSectionRaw, matchers, includeDebug);
if (!string.IsNullOrWhiteSpace(match))
return $"Microsoft CAB SFX v{Utilities.GetFileVersion(pex)}".TrimEnd('v');
return $"Microsoft CAB SFX {GetVersion(pex)}";
}
// Get the .text section, if it exists
@@ -61,7 +61,7 @@ namespace BurnOutSharp.PackerType
string match = MatchUtil.GetFirstMatch(file, pex.TextSectionRaw, matchers, includeDebug);
if (!string.IsNullOrWhiteSpace(match))
return $"Microsoft CAB SFX v{Utilities.GetFileVersion(pex)}".TrimEnd('v');
return $"Microsoft CAB SFX {GetVersion(pex)}";
}
return null;
@@ -84,5 +84,18 @@ namespace BurnOutSharp.PackerType
{
return null;
}
private string GetVersion(PortableExecutable pex)
{
string version = Utilities.GetFileVersion(pex);
if (!string.IsNullOrWhiteSpace(version))
return $"v{version}";
version = Utilities.GetManifestVersion(pex);
if (!string.IsNullOrWhiteSpace(version))
return $"v{version}";
return string.Empty;
}
}
}

View File

@@ -126,21 +126,17 @@ namespace BurnOutSharp.Tools
/// </summary>
public static string ReadString(this byte[] content, ref int offset, Encoding encoding)
{
// TODO: Fix the code below to make it work with byte arrays and not streams
return null;
byte[] nullTerminator = encoding.GetBytes(new char[] { '\0' });
int charWidth = nullTerminator.Length;
// byte[] nullTerminator = encoding.GetBytes(new char[] { '\0' });
// int charWidth = nullTerminator.Length;
List<char> keyChars = new List<char>();
while (BitConverter.ToUInt16(content, offset) != 0x0000)
{
keyChars.Add(encoding.GetChars(content, offset, charWidth)[0]); offset += charWidth;
}
offset += 2;
// List<byte> tempBuffer = new List<byte>();
// byte[] buffer = new byte[charWidth];
// while (stream.Read(buffer, 0, charWidth) != 0 && buffer.SequenceEqual(nullTerminator))
// {
// tempBuffer.AddRange(buffer);
// }
// return encoding.GetString(tempBuffer.ToArray());
return new string(keyChars.ToArray());
}
/// <summary>