From de51cee95468a6f86106852553cf7986f62d071d Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Fri, 26 Mar 2021 20:49:18 -0500 Subject: [PATCH] Enabled nullability checks in IPA.exe --- Common.props | 2 +- IPA/Arguments.cs | 428 +++++++++++++++++++------------------- IPA/PatchContext.cs | 119 +++++------ IPA/Patcher/BackupUnit.cs | 8 +- IPA/Program.cs | 80 ++++--- 5 files changed, 325 insertions(+), 312 deletions(-) diff --git a/Common.props b/Common.props index 9d367c05..95f8c80a 100644 --- a/Common.props +++ b/Common.props @@ -5,7 +5,7 @@ portable 9 - CA1031 + CA1031;CA1305 disable $(WarningsAsErrors);nullable AllEnabledByDefault diff --git a/IPA/Arguments.cs b/IPA/Arguments.cs index 30dc9b93..d9267038 100644 --- a/IPA/Arguments.cs +++ b/IPA/Arguments.cs @@ -1,215 +1,213 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -namespace IPA -{ - public class Arguments - { - public static readonly Arguments CmdLine = new Arguments(Environment.GetCommandLineArgs()); - - private readonly List positional = new List(); - private readonly Dictionary longFlags = new Dictionary(); - private readonly Dictionary flags = new Dictionary(); - private readonly List flagObjects = new List(); - - private string[] toParse; - - private Arguments(string[] args) - { - toParse = args.Skip(1).ToArray(); - } - - public Arguments Flags(params ArgumentFlag[] toAdd) - { - foreach (var f in toAdd) AddFlag(f); - return this; - } - - public void AddFlag(ArgumentFlag toAdd) - { - if (toParse == null) throw new InvalidOperationException(); - flagObjects.Add(toAdd); - } - - public void Process() - { - foreach (var arg in toParse) - { - if (arg.StartsWith("--")) - { // parse as a long flag - var name = arg.Substring(2); // cut off first two chars - string value = null; - - if (name.Contains('=')) - { - var spl = name.Split('='); - name = spl[0]; - value = string.Join("=", spl, 1, spl.Length - 1); - } - - longFlags.Add(name, value); - } - else if (arg.StartsWith("-")) - { // parse as flags - var argument = arg.Substring(1); // cut off first char - - var subBuildState = new StringBuilder(); - var parsingValue = false; - var escaped = false; - var mainChar = ' '; - foreach (var chr in argument) - { - if (!parsingValue) - { - if (chr == '=') - { - parsingValue = true; - } - else - { - mainChar = chr; - flags.Add(chr, null); - } - } - else - { - if (!escaped) - { - if (chr == ',') - { - parsingValue = false; - flags[mainChar] = subBuildState.ToString(); - subBuildState = new StringBuilder(); - continue; - } - else if (chr == '\\') - { - escaped = true; - continue; - } - } - - subBuildState.Append(chr); - } - } - - if (parsingValue) - { - parsingValue = false; - flags[mainChar] = subBuildState.ToString(); - subBuildState = new StringBuilder(); - } - } - else - { // parse as positional - positional.Add(arg); - } - } - - toParse = null; - - foreach (var flag in flagObjects) - { - foreach (var charFlag in flag.ShortFlags) - { - if (!(flag.exists_ = HasFlag(charFlag))) continue; - - flag.value_ = GetFlagValue(charFlag); - goto FoundValue; // continue to next flagObjects item - } - - foreach (var longFlag in flag.LongFlags) - { - if (!(flag.exists_ = HasLongFlag(longFlag))) continue; - - flag.value_ = GetLongFlagValue(longFlag); - goto FoundValue; // continue to next flagObjects item - } - - FoundValue:; - } - } - - public bool HasLongFlag(string flag) - { - return longFlags.ContainsKey(flag); - } - - public bool HasFlag(char flag) - { - return flags.ContainsKey(flag); - } - - public string GetLongFlagValue(string flag) - { - return longFlags[flag]; - } - - public string GetFlagValue(char flag) - { - return flags[flag]; - } - - public void PrintHelp() - { - const string indent = " "; - var filename = Path.GetFileName(Environment.GetCommandLineArgs()[0]); - const string format = @"usage: -{2}{0} [FLAGS] [ARGUMENTS] - -flags: -{1}"; - var flagsBuilder = new StringBuilder(); - foreach (var flag in flagObjects) - { - flagsBuilder.AppendFormat("{2}{0}{3}{1}", - string.Join(", ", flag.ShortFlags.Select(s => $"-{s}").Concat( flag.LongFlags.Select(s => $"--{s}")) ), - Environment.NewLine, indent, flag.ValueString != null ? "=" + flag.ValueString : ""); - flagsBuilder.AppendFormat("{2}{2}{0}{1}", flag.DocString, Environment.NewLine, indent); - } - - Console.Write(format, filename, flagsBuilder, indent); - } - - public IReadOnlyList PositionalArgs => positional; - } - - public class ArgumentFlag - { - internal readonly List ShortFlags = new List(); - internal readonly List LongFlags = new List(); - - internal string value_; - internal bool exists_; - - public ArgumentFlag(params string[] flags) - { - foreach (var part in flags) - AddPart(part); - } - - private void AddPart(string flagPart) - { - if (flagPart.StartsWith("--")) - LongFlags.Add(flagPart.Substring(2)); - else if (flagPart.StartsWith("-")) - ShortFlags.Add(flagPart[1]); - } - - public bool Exists => exists_; - public string Value => value_; - - public bool HasValue => Exists && Value != null; - - public string DocString { get; set; } = ""; - public string ValueString { get; set; } - - public static implicit operator bool(ArgumentFlag f) - { - return f.Exists; - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace IPA +{ + public class Arguments + { + public static readonly Arguments CmdLine = new(Environment.GetCommandLineArgs()); + + private readonly List positional = new(); + private readonly Dictionary longFlags = new(); + private readonly Dictionary flags = new(); + private readonly List flagObjects = new(); + + private string[]? toParse; + + private Arguments(string[] args) + { + toParse = args.Skip(1).ToArray(); + } + + public Arguments Flags(params ArgumentFlag[] toAdd) + { + foreach (var f in toAdd) AddFlag(f); + return this; + } + + public void AddFlag(ArgumentFlag toAdd) + { + if (toParse == null) throw new InvalidOperationException(); + flagObjects.Add(toAdd); + } + + public void Process() + { + if (toParse == null) throw new InvalidOperationException(); + + foreach (var arg in toParse) + { + if (arg.StartsWith("--")) + { // parse as a long flag + var name = arg.Substring(2); // cut off first two chars + string? value = null; + + if (name.Contains('=')) + { + var spl = name.Split('='); + name = spl[0]; + value = string.Join("=", spl, 1, spl.Length - 1); + } + + longFlags.Add(name, value); + } + else if (arg.StartsWith("-")) + { // parse as flags + var argument = arg.Substring(1); // cut off first char + + var subBuildState = new StringBuilder(); + var parsingValue = false; + var escaped = false; + var mainChar = ' '; + foreach (var chr in argument) + { + if (!parsingValue) + { + if (chr == '=') + { + parsingValue = true; + } + else + { + mainChar = chr; + flags.Add(chr, null); + } + } + else + { + if (!escaped) + { + if (chr == ',') + { + parsingValue = false; + flags[mainChar] = subBuildState.ToString(); + subBuildState = new StringBuilder(); + continue; + } + else if (chr == '\\') + { + escaped = true; + continue; + } + } + + _ = subBuildState.Append(chr); + } + } + + if (parsingValue) + { + flags[mainChar] = subBuildState.ToString(); + } + } + else + { // parse as positional + positional.Add(arg); + } + } + + toParse = null; + + foreach (var flag in flagObjects) + { + foreach (var charFlag in flag.ShortFlags) + { + if (!(flag.exists_ = HasFlag(charFlag))) continue; + + flag.value_ = GetFlagValue(charFlag); + goto FoundValue; // continue to next flagObjects item + } + + foreach (var longFlag in flag.LongFlags) + { + if (!(flag.exists_ = HasLongFlag(longFlag))) continue; + + flag.value_ = GetLongFlagValue(longFlag); + goto FoundValue; // continue to next flagObjects item + } + + FoundValue:; + } + } + + public bool HasLongFlag(string flag) + { + return longFlags.ContainsKey(flag); + } + + public bool HasFlag(char flag) + { + return flags.ContainsKey(flag); + } + + public string? GetLongFlagValue(string flag) + { + return longFlags[flag]; + } + + public string? GetFlagValue(char flag) + { + return flags[flag]; + } + + public void PrintHelp() + { + const string indent = " "; + var filename = Path.GetFileName(Environment.GetCommandLineArgs()[0]); + const string format = @"usage: +{2}{0} [FLAGS] [ARGUMENTS] + +flags: +{1}"; + var flagsBuilder = new StringBuilder(); + foreach (var flag in flagObjects) + { + _ = flagsBuilder + .AppendFormat("{2}{0}{3}{1}", + string.Join(", ", flag.ShortFlags.Select(s => $"-{s}").Concat( flag.LongFlags.Select(s => $"--{s}")) ), + Environment.NewLine, indent, flag.ValueString != null ? "=" + flag.ValueString : "") + .AppendFormat("{2}{2}{0}{1}", flag.DocString, Environment.NewLine, indent); + } + + Console.Write(format, filename, flagsBuilder, indent); + } + + public IReadOnlyList PositionalArgs => positional; + } + + public class ArgumentFlag + { + internal readonly List ShortFlags = new(); + internal readonly List LongFlags = new(); + + internal string? value_; + internal bool exists_; + + public ArgumentFlag(params string[] flags) + { + foreach (var part in flags) + AddPart(part); + } + + private void AddPart(string flagPart) + { + if (flagPart.StartsWith("--")) + LongFlags.Add(flagPart.Substring(2)); + else if (flagPart.StartsWith("-")) + ShortFlags.Add(flagPart[1]); + } + + public bool Exists => exists_; + public string? Value => value_; + + public bool HasValue => Exists && Value != null; + + public string DocString { get; set; } = ""; + public string? ValueString { get; set; } + + public static implicit operator bool(ArgumentFlag f) => f.Exists; + } +} diff --git a/IPA/PatchContext.cs b/IPA/PatchContext.cs index 2a829306..4e43c3eb 100644 --- a/IPA/PatchContext.cs +++ b/IPA/PatchContext.cs @@ -1,58 +1,61 @@ -using System; -using System.IO; -using System.Reflection; - -namespace IPA -{ - public class PatchContext - { - /// - /// Gets the filename of the executable. - /// - public string Executable { get; private set; } - - public string DataPathSrc { get; private set; } - public string LibsPathSrc { get; private set; } - public string PluginsFolder { get; private set; } - public string ProjectName { get; private set; } - public string DataPathDst { get; private set; } - public string LibsPathDst { get; private set; } - public string ManagedPath { get; private set; } - public string EngineFile { get; private set; } - public string AssemblyFile { get; private set; } - public string ProjectRoot { get; private set; } - public string IPARoot { get; private set; } - public string ShortcutPath { get; private set; } - public string IPA { get; private set; } - public string BackupPath { get; private set; } - - private PatchContext() { } - - public static PatchContext Create(string exe) - { - var context = new PatchContext - { - Executable = exe - }; - context.ProjectRoot = new FileInfo(context.Executable).Directory?.FullName; - context.IPARoot = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) ?? throw new InvalidOperationException(), "IPA"); - context.IPA = Assembly.GetExecutingAssembly().Location; - context.DataPathSrc = Path.Combine(context.IPARoot, "Data"); - context.LibsPathSrc = Path.Combine(context.IPARoot, "Libs"); - context.PluginsFolder = Path.Combine(context.ProjectRoot ?? throw new InvalidOperationException(), "Plugins"); - context.ProjectName = Path.GetFileNameWithoutExtension(context.Executable); - context.DataPathDst = Path.Combine(context.ProjectRoot, context.ProjectName + "_Data"); - context.LibsPathDst = Path.Combine(context.ProjectRoot, "Libs"); - context.ManagedPath = Path.Combine(context.DataPathDst, "Managed"); - context.EngineFile = Path.Combine(context.ManagedPath, "UnityEngine.CoreModule.dll"); - context.AssemblyFile = Path.Combine(context.ManagedPath, "Assembly-CSharp.dll"); - context.BackupPath = Path.Combine(context.IPARoot, "Backups", context.ProjectName); - string shortcutName = $"{context.ProjectName} (Patch & Launch)"; - context.ShortcutPath = Path.Combine(context.ProjectRoot, shortcutName) + ".lnk"; - - Directory.CreateDirectory(context.BackupPath); - - return context; - } - } -} +using System; +using System.IO; +using System.Reflection; + +namespace IPA +{ + public class PatchContext + { + /// + /// Gets the filename of the executable. + /// + public string Executable { get; private set; } + + public string DataPathSrc { get; private set; } + public string LibsPathSrc { get; private set; } + public string PluginsFolder { get; private set; } + public string ProjectName { get; private set; } + public string DataPathDst { get; private set; } + public string LibsPathDst { get; private set; } + public string ManagedPath { get; private set; } + public string EngineFile { get; private set; } + public string AssemblyFile { get; private set; } + public string ProjectRoot { get; private set; } + public string IPARoot { get; private set; } + public string ShortcutPath { get; private set; } + public string IPA { get; private set; } + public string BackupPath { get; private set; } + + // This is only created by us; and all are assigned +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + private PatchContext() { } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + + public static PatchContext Create(string exe) + { + var context = new PatchContext + { + Executable = exe + }; + context.ProjectRoot = new FileInfo(context.Executable).Directory?.FullName ?? throw new Exception(); + context.IPARoot = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location) ?? throw new InvalidOperationException(), "IPA"); + context.IPA = Assembly.GetExecutingAssembly().Location; + context.DataPathSrc = Path.Combine(context.IPARoot, "Data"); + context.LibsPathSrc = Path.Combine(context.IPARoot, "Libs"); + context.PluginsFolder = Path.Combine(context.ProjectRoot ?? throw new InvalidOperationException(), "Plugins"); + context.ProjectName = Path.GetFileNameWithoutExtension(context.Executable); + context.DataPathDst = Path.Combine(context.ProjectRoot, context.ProjectName + "_Data"); + context.LibsPathDst = Path.Combine(context.ProjectRoot, "Libs"); + context.ManagedPath = Path.Combine(context.DataPathDst, "Managed"); + context.EngineFile = Path.Combine(context.ManagedPath, "UnityEngine.CoreModule.dll"); + context.AssemblyFile = Path.Combine(context.ManagedPath, "Assembly-CSharp.dll"); + context.BackupPath = Path.Combine(context.IPARoot, "Backups", context.ProjectName); + string shortcutName = $"{context.ProjectName} (Patch & Launch)"; + context.ShortcutPath = Path.Combine(context.ProjectRoot, shortcutName) + ".lnk"; + + _ = Directory.CreateDirectory(context.BackupPath); + + return context; + } + } +} diff --git a/IPA/Patcher/BackupUnit.cs b/IPA/Patcher/BackupUnit.cs index 614e11ea..b2a70762 100644 --- a/IPA/Patcher/BackupUnit.cs +++ b/IPA/Patcher/BackupUnit.cs @@ -13,9 +13,9 @@ namespace IPA.Patcher private readonly DirectoryInfo _backupPath; private readonly PatchContext _context; - private readonly List _files = new List(); + private readonly List _files = new(); private readonly FileInfo _manifestFile; - private static string _ManifestFileName = "$manifest$.txt"; + private static readonly string _ManifestFileName = "$manifest$.txt"; public BackupUnit(PatchContext context) : this(context, DateTime.Now.ToString("yyyy-MM-dd_h-mm-ss")) { @@ -88,7 +88,7 @@ namespace IPA.Patcher backupPath.Directory?.Create(); if (file.Exists) { - file.CopyTo(backupPath.FullName); + _ = file.CopyTo(backupPath.FullName); } else { @@ -123,7 +123,7 @@ namespace IPA.Patcher { Console.WriteLine(" {0} => {1}", backupFile.FullName, target.FullName); target.Directory?.Create(); - backupFile.CopyTo(target.FullName, true); + _ = backupFile.CopyTo(target.FullName, true); } else { diff --git a/IPA/Program.cs b/IPA/Program.cs index d3df0f9b..7c052b16 100644 --- a/IPA/Program.cs +++ b/IPA/Program.cs @@ -12,10 +12,8 @@ using IPA.Patcher; namespace IPA { - [SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] public static class Program { - [SuppressMessage("ReSharper", "InconsistentNaming")] public enum Architecture { x86, @@ -25,17 +23,17 @@ namespace IPA public const string FileVersion = "4.1.6.0"; - public static Version Version => Assembly.GetEntryAssembly().GetName().Version; + public static Version Version => Assembly.GetEntryAssembly()!.GetName().Version!; - public static readonly ArgumentFlag ArgHelp = new ArgumentFlag("--help", "-h") { DocString = "prints this message" }; - public static readonly ArgumentFlag ArgVersion = new ArgumentFlag("--version", "-v") { DocString = "prints the version that will be installed and is currently installed" }; - public static readonly ArgumentFlag ArgWaitFor = new ArgumentFlag("--waitfor", "-w") { DocString = "waits for the specified PID to exit", ValueString = "PID" }; - public static readonly ArgumentFlag ArgForce = new ArgumentFlag("--force", "-f") { DocString = "forces the operation to go through" }; - public static readonly ArgumentFlag ArgRevert = new ArgumentFlag("--revert", "-r") { DocString = "reverts the IPA installation" }; - public static readonly ArgumentFlag ArgNoRevert = new ArgumentFlag("--no-revert", "-R") { DocString = "prevents a normal installation from first reverting" }; - public static readonly ArgumentFlag ArgNoWait = new ArgumentFlag("--nowait", "-n") { DocString = "doesn't wait for user input after the operation" }; - public static readonly ArgumentFlag ArgStart = new ArgumentFlag("--start", "-s") { DocString = "uses the specified arguments to start the game after the patch/unpatch", ValueString = "ARGUMENTS" }; - public static readonly ArgumentFlag ArgLaunch = new ArgumentFlag("--launch", "-l") { DocString = "uses positional parameters as arguments to start the game after patch/unpatch" }; + public static readonly ArgumentFlag ArgHelp = new("--help", "-h") { DocString = "prints this message" }; + public static readonly ArgumentFlag ArgVersion = new("--version", "-v") { DocString = "prints the version that will be installed and is currently installed" }; + public static readonly ArgumentFlag ArgWaitFor = new("--waitfor", "-w") { DocString = "waits for the specified PID to exit", ValueString = "PID" }; + public static readonly ArgumentFlag ArgForce = new("--force", "-f") { DocString = "forces the operation to go through" }; + public static readonly ArgumentFlag ArgRevert = new("--revert", "-r") { DocString = "reverts the IPA installation" }; + public static readonly ArgumentFlag ArgNoRevert = new("--no-revert", "-R") { DocString = "prevents a normal installation from first reverting" }; + public static readonly ArgumentFlag ArgNoWait = new("--nowait", "-n") { DocString = "doesn't wait for user input after the operation" }; + public static readonly ArgumentFlag ArgStart = new("--start", "-s") { DocString = "uses the specified arguments to start the game after the patch/unpatch", ValueString = "ARGUMENTS" }; + public static readonly ArgumentFlag ArgLaunch = new("--launch", "-l") { DocString = "uses positional parameters as arguments to start the game after patch/unpatch" }; [STAThread] public static void Main() @@ -57,7 +55,7 @@ namespace IPA { if (ArgWaitFor.HasValue && !ArgVersion) { // wait for process if necessary - var pid = int.Parse(ArgWaitFor.Value); + var pid = int.Parse(ArgWaitFor.Value!); try { // wait for beat saber to exit (ensures we can modify the file) @@ -73,12 +71,12 @@ namespace IPA } } - PatchContext context = null; + PatchContext? context = null; - Assembly AssemblyLibLoader(object source, ResolveEventArgs e) + Assembly? AssemblyLibLoader(object? source, ResolveEventArgs e) { // ReSharper disable AccessToModifiedClosure - if (context == null) return null; + if (context == null || e.Name == null) return null; var libsDir = context.LibsPathSrc; // ReSharper enable AccessToModifiedClosure @@ -96,14 +94,16 @@ namespace IPA var argExeName = Arguments.CmdLine.PositionalArgs.FirstOrDefault(s => s.EndsWith(".exe")); argExeName ??= new DirectoryInfo(Directory.GetCurrentDirectory()).GetFiles() - .FirstOrDefault(o => o.Extension == ".exe" && o.FullName != Assembly.GetEntryAssembly().Location) + .FirstOrDefault(o => o.Extension == ".exe" && o.FullName != Assembly.GetEntryAssembly()!.Location) ?.FullName; if (argExeName == null) { Fail("Could not locate game executable"); } else + { context = PatchContext.Create(argExeName); + } if (ArgVersion) { @@ -120,7 +120,9 @@ namespace IPA Validate(context); if (ArgRevert /*|| Keyboard.IsKeyDown(Keys.LMenu)*/) + { Revert(context); + } else { Install(context); @@ -147,7 +149,7 @@ namespace IPA Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine("[Press any key to continue]"); Console.ResetColor(); - Console.ReadKey(); + _ = Console.ReadKey(); } } @@ -161,7 +163,7 @@ namespace IPA } } - private static Version GetInstalledVersion(PatchContext context) + private static Version? GetInstalledVersion(PatchContext context) { // first, check currently installed version, if any if (File.Exists(Path.Combine(context.ProjectRoot, "winhttp.dll"))) @@ -199,7 +201,7 @@ namespace IPA Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("Restoring old version... "); if (BackupManager.HasBackup(context)) - BackupManager.Restore(context); + _ = BackupManager.Restore(context); } var nativePluginFolder = Path.Combine(context.DataPathDst, "Plugins"); @@ -231,7 +233,7 @@ namespace IPA { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine("Creating plugins folder... "); - Directory.CreateDirectory(context.PluginsFolder); + _ = Directory.CreateDirectory(context.PluginsFolder); Console.ResetColor(); } @@ -277,17 +279,17 @@ namespace IPA { if (ArgStart.HasValue) { - Process.Start(context.Executable, ArgStart.Value); + _ = Process.Start(context.Executable, ArgStart.Value); } else { var argList = Arguments.CmdLine.PositionalArgs.ToList(); - argList.Remove(context.Executable); + _ = argList.Remove(context.Executable); if (ArgLaunch) { - Process.Start(context.Executable, Args(argList.ToArray())); + _ = Process.Start(context.Executable, Args(argList.ToArray())); } } } @@ -309,7 +311,7 @@ namespace IPA } public static void CopyAll(DirectoryInfo source, DirectoryInfo target, bool aggressive, BackupUnit backup, - Func> interceptor = null, bool recurse = true) + Func>? interceptor = null, bool recurse = true) { if (interceptor == null) { @@ -331,7 +333,7 @@ namespace IPA ClearLine(); Console.WriteLine(@"Copying {0}", targetFile.FullName); backup.Add(targetFile); - fi.CopyTo(targetFile.FullName, true); + _ = fi.CopyTo(targetFile.FullName, true); } } @@ -351,13 +353,14 @@ namespace IPA WaitForEnd(); + // This is needed because in Framework, this is not marked DoesNotReturn +#pragma warning disable CS8763 // A method marked [DoesNotReturn] should not return. Environment.Exit(1); } +#pragma warning restore CS8763 // A method marked [DoesNotReturn] should not return. public static string Args(params string[] args) - { - return string.Join(" ", args.Select(EncodeParameterArgument).ToArray()); - } + => string.Join(" ", args.Select(EncodeParameterArgument).ToArray()); /// /// Encodes an argument for passing into a program @@ -381,19 +384,28 @@ namespace IPA var header = reader.ReadUInt16(); if (header == 0x5a4d) { - reader.BaseStream.Seek(60, SeekOrigin.Begin); // this location contains the offset for the PE header + _ = reader.BaseStream.Seek(60, SeekOrigin.Begin); // this location contains the offset for the PE header var peOffset = reader.ReadUInt32(); - reader.BaseStream.Seek(peOffset + 4, SeekOrigin.Begin); + _ = reader.BaseStream.Seek(peOffset + 4, SeekOrigin.Begin); var machine = reader.ReadUInt16(); if (machine == 0x8664) // IMAGE_FILE_MACHINE_AMD64 + { return Architecture.x64; - if (machine == 0x014c) // IMAGE_FILE_MACHINE_I386 + } + else if (machine == 0x014c) // IMAGE_FILE_MACHINE_I386 + { return Architecture.x86; - if (machine == 0x0200) // IMAGE_FILE_MACHINE_IA64 + } + else if (machine == 0x0200) // IMAGE_FILE_MACHINE_IA64 + { return Architecture.x64; - return Architecture.Unknown; + } + else + { + return Architecture.Unknown; + } } // Not a supported binary