From 07882f7632e3f326d5a383f2e357e08e85de6241 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sat, 20 Mar 2021 17:34:31 -0700 Subject: [PATCH] Create and use manifesr version utility --- BurnOutSharp/PackerType/SetupFactory.cs | 58 +++----------- BurnOutSharp/PackerType/WinZipSFX.cs | 102 +++++++++--------------- BurnOutSharp/Utilities.cs | 52 ++++++++++++ 3 files changed, 101 insertions(+), 111 deletions(-) diff --git a/BurnOutSharp/PackerType/SetupFactory.cs b/BurnOutSharp/PackerType/SetupFactory.cs index 81129e12..e67961f5 100644 --- a/BurnOutSharp/PackerType/SetupFactory.cs +++ b/BurnOutSharp/PackerType/SetupFactory.cs @@ -22,24 +22,17 @@ namespace BurnOutSharp.PackerType byte[] check = new byte[] { 0x53, 0x00, 0x65, 0x00, 0x74, 0x00, 0x75, 0x00, 0x70, 0x00, 0x20, 0x00, 0x46, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00 }; if (fileContent.Contains(check, out int position)) { - // " - byte[] check = new byte[] { 0x3C, 0x2F, 0x61, 0x73, 0x73, 0x65, 0x6D, 0x62, 0x6C, 0x79, 0x3E }; - if (fileContent.Contains(check, out int position, start: xmlStartPosition)) - { - int offset = position + 11 - xmlStartPosition; - string xmlString = Encoding.ASCII.GetString(fileContent, xmlStartPosition, offset); - - try - { - // Load the XML string as a document - var xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(xmlString); - - // Get the version attribute, if possible - string xmlVersion = xmlDoc["assembly"]["assemblyIdentity"].GetAttributeNode("version").InnerXml; - - return $"Version {xmlVersion}"; - } - catch - { - return null; - } - } - return null; - } } } diff --git a/BurnOutSharp/PackerType/WinZipSFX.cs b/BurnOutSharp/PackerType/WinZipSFX.cs index f4b0f25e..7eaac48a 100644 --- a/BurnOutSharp/PackerType/WinZipSFX.cs +++ b/BurnOutSharp/PackerType/WinZipSFX.cs @@ -19,26 +19,12 @@ namespace BurnOutSharp.PackerType // WinZip Self-Extractor byte[] check = new byte[] { 0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70, 0x20, 0x53, 0x65, 0x6C, 0x66, 0x2D, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6F, 0x72 }; if (fileContent.Contains(check, out int position)) - { - // " - byte[] check = new byte[] { 0x3C, 0x2F, 0x61, 0x73, 0x73, 0x65, 0x6D, 0x62, 0x6C, 0x79, 0x3E }; - if (fileContent.Contains(check, out int position, start: xmlStartPosition)) - { - int offset = position + 11 - xmlStartPosition; - string xmlString = Encoding.ASCII.GetString(fileContent, xmlStartPosition, offset); - - try - { - // Load the XML string as a document - var xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(xmlString); - - // Get the version attribute, if possible - string xmlVersion = xmlDoc["assembly"]["assemblyIdentity"].GetAttributeNode("version").InnerXml; - - // Some version strings don't exactly match the public version number - switch (xmlVersion) - { - case "3.0.7158.0": - return "3.0.7158"; - case "3.1.7556.0": - return "3.1.7556"; - case "3.1.8421.0": - return "4.0.8421"; - case "3.1.8672.0": - return "4.0.8672"; - case "4.0.1221.0": - return "4.0.12218"; - default: - return $"(Unknown Version - {xmlVersion})"; - } - } - catch { } - } - + // Check the manifest version first + string version = Utilities.GetManifestVersion(fileContent); + if (!string.IsNullOrEmpty(version)) + return GetV3PlusVersion(version); + + // Assume an earlier version return GetV2Version(fileContent); } @@ -160,7 +116,7 @@ namespace BurnOutSharp.PackerType 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, }; if (fileContent.Contains(check, out _)) - return "Version 2.0 (MS-DOS/16-bit)"; + return "2.0 (MS-DOS/16-bit)"; check = new byte[] { @@ -174,7 +130,7 @@ namespace BurnOutSharp.PackerType 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, }; if (fileContent.Contains(check, out _)) - return "Version 2.0 (16-bit)"; + return "2.0 (16-bit)"; check = new byte[] { @@ -216,7 +172,7 @@ namespace BurnOutSharp.PackerType 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, }; if (fileContent.Contains(check, out _)) - return "Version 2.1 RC2 (MS-DOS/16-bit)"; + return "2.1 RC2 (MS-DOS/16-bit)"; check = new byte[] { @@ -230,7 +186,7 @@ namespace BurnOutSharp.PackerType 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, }; if (fileContent.Contains(check, out _)) - return "Version 2.1 RC2 (16-bit)"; + return "2.1 RC2 (16-bit)"; check = new byte[] { @@ -272,7 +228,7 @@ namespace BurnOutSharp.PackerType 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, }; if (fileContent.Contains(check, out _)) - return "Version 2.1 (MS-DOS/16-bit)"; + return "2.1 (MS-DOS/16-bit)"; check = new byte[] { @@ -286,7 +242,7 @@ namespace BurnOutSharp.PackerType 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, }; if (fileContent.Contains(check, out _)) - return "Version 2.1 (16-bit)"; + return "2.1 (16-bit)"; check = new byte[] { @@ -334,7 +290,7 @@ namespace BurnOutSharp.PackerType 0x53, 0x46, 0x58, }; if (fileContent.Contains(check, out _)) - return "Version 2.0 (32-bit)"; + return "2.0 (32-bit)"; // .............]�92....�P..............�P..�P..�P..VW95SRE.SFX check = new byte[] @@ -364,7 +320,7 @@ namespace BurnOutSharp.PackerType 0x53, 0x46, 0x58, }; if (fileContent.Contains(check, out _)) - return "Version 2.1 RC2 (32-bit)"; + return "2.1 RC2 (32-bit)"; // .............���3....�P..............�P..�P..�P..VW95SRE.SFX check = new byte[] @@ -394,7 +350,7 @@ namespace BurnOutSharp.PackerType 0x53, 0x46, 0x58, }; if (fileContent.Contains(check, out _)) - return "Version 2.1 (32-bit)"; + return "2.1 (32-bit)"; // .............{��3....�P..............�P..�P..�P..VW95SRE.SFX check = new byte[] @@ -427,7 +383,7 @@ namespace BurnOutSharp.PackerType 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, }; if (fileContent.Contains(check, out _)) - return "Version 2.2.4003"; + return "2.2.4003"; // PE..L.....[:........�........V...*.......?.......p....@. check = new byte[] @@ -447,5 +403,25 @@ namespace BurnOutSharp.PackerType return "Unknown Version 2.X"; } + + private static string GetV3PlusVersion(string version) + { + // Some version strings don't exactly match the public version number + switch (version) + { + case "3.0.7158.0": + return "3.0.7158"; + case "3.1.7556.0": + return "3.1.7556"; + case "3.1.8421.0": + return "4.0.8421"; + case "3.1.8672.0": + return "4.0.8672"; + case "4.0.1221.0": + return "4.0.12218"; + default: + return $"(Unknown Version - {version})"; + } + } } } diff --git a/BurnOutSharp/Utilities.cs b/BurnOutSharp/Utilities.cs index a66f4e08..21ff54d2 100644 --- a/BurnOutSharp/Utilities.cs +++ b/BurnOutSharp/Utilities.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Text; +using System.Xml; namespace BurnOutSharp { @@ -232,5 +234,55 @@ namespace BurnOutSharp else return fvinfo.ProductVersion.Replace(", ", "."); } + + /// + /// Get the assembly version as determined by an embedded assembly manifest + /// + /// TODO: How do we find the manifest specifically better? + public static string GetManifestVersion(byte[] fileContent) + { + // + byte[] manifestEnd = new byte[] { 0x3C, 0x2F, 0x61, 0x73, 0x73, 0x65, 0x6D, 0x62, 0x6C, 0x79, 0x3E }; + if (!fileContent.Contains(manifestEnd, out int manifestEndPosition, start: manifestStartPosition)) + return null; + + // Read in the manifest to a string + int manifestLength = manifestEndPosition + "".Length - manifestStartPosition; + string manifestString = Encoding.ASCII.GetString(fileContent, manifestStartPosition, manifestLength); + + // Try to read the XML in from the string + try + { + // Load the XML string as a document + var manifestDoc = new XmlDocument(); + manifestDoc.LoadXml(manifestString); + + // If the XML has no children, it's invalid + if (!manifestDoc.HasChildNodes) + return null; + + // Try to read the assembly node + var assemblyNode = manifestDoc["assembly"]; + if (assemblyNode == null) + return null; + + // Try to read the assemblyIdentity + var assemblyIdentityNode = assemblyNode["assemblyIdentity"]; + if (assemblyIdentityNode == null) + return null; + + // Return the version attribute, if possible + return assemblyIdentityNode.GetAttribute("version"); + } + catch + { + return null; + } + } } }