From 57dc6c5d40d98fef848e453b2632719f0c7b6a34 Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Tue, 13 Feb 2024 23:04:45 +0100 Subject: [PATCH 01/13] Updated patcher to .NET 8.0 --- patcher/.gitignore | 1 + .../.idea.HitmanPatcher/.idea/.gitignore | 10 +- .../.idea/copyright/AGPL_3_0.xml | 2 +- .../.idea.HitmanPatcher/.idea/encodings.xml | 4 + patcher/App.config | 24 -- patcher/CliLocale.Designer.cs | 81 +++++-- patcher/HitmanPatcher.csproj | 219 ++++-------------- patcher/HitmanPatcher.sln | 18 +- patcher/HitmanVersion.cs | 16 +- patcher/MainForm.Designer.cs | 2 +- patcher/MainForm.cs | 1 + patcher/Program.cs | 3 +- patcher/Properties/AssemblyInfo.cs | 39 ---- patcher/Properties/Resources.Designer.cs | 37 +-- patcher/Properties/Resources.resx | 85 +++++-- patcher/Properties/Settings.Designer.cs | 26 --- patcher/Properties/Settings.settings | 7 - 17 files changed, 221 insertions(+), 354 deletions(-) create mode 100644 patcher/.idea/.idea.HitmanPatcher/.idea/encodings.xml delete mode 100644 patcher/App.config delete mode 100644 patcher/Properties/AssemblyInfo.cs delete mode 100644 patcher/Properties/Settings.Designer.cs delete mode 100644 patcher/Properties/Settings.settings diff --git a/patcher/.gitignore b/patcher/.gitignore index 1747fa209..d74468c11 100644 --- a/patcher/.gitignore +++ b/patcher/.gitignore @@ -4,3 +4,4 @@ obj/* /HitmanPatcher.sln.DotSettings.user /.idea/.idea.HitmanPatcher/.idea/riderMarkupCache.xml *.suo +*.user \ No newline at end of file diff --git a/patcher/.idea/.idea.HitmanPatcher/.idea/.gitignore b/patcher/.idea/.idea.HitmanPatcher/.idea/.gitignore index 81d8650d4..b0bc3ebd5 100644 --- a/patcher/.idea/.idea.HitmanPatcher/.idea/.gitignore +++ b/patcher/.idea/.idea.HitmanPatcher/.idea/.gitignore @@ -1,9 +1,13 @@ -# Default ignored files +# Default ignored files /shelf/ /workspace.xml # Rider ignored files +/projectSettingsUpdater.xml /modules.xml /contentModel.xml -/projectSettingsUpdater.xml /.idea.HitmanPatcher.iml -discord.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/patcher/.idea/.idea.HitmanPatcher/.idea/copyright/AGPL_3_0.xml b/patcher/.idea/.idea.HitmanPatcher/.idea/copyright/AGPL_3_0.xml index 0e3ba8f2e..716f85dad 100644 --- a/patcher/.idea/.idea.HitmanPatcher/.idea/copyright/AGPL_3_0.xml +++ b/patcher/.idea/.idea.HitmanPatcher/.idea/copyright/AGPL_3_0.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/patcher/.idea/.idea.HitmanPatcher/.idea/encodings.xml b/patcher/.idea/.idea.HitmanPatcher/.idea/encodings.xml new file mode 100644 index 000000000..df87cf951 --- /dev/null +++ b/patcher/.idea/.idea.HitmanPatcher/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/patcher/App.config b/patcher/App.config deleted file mode 100644 index fcf2f62a0..000000000 --- a/patcher/App.config +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/patcher/CliLocale.Designer.cs b/patcher/CliLocale.Designer.cs index 679a1f453..fe09bc289 100644 --- a/patcher/CliLocale.Designer.cs +++ b/patcher/CliLocale.Designer.cs @@ -1,6 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -11,32 +12,46 @@ namespace HitmanPatcher { using System; - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class CliLocale { - private static System.Resources.ResourceManager resourceMan; + private static global::System.Resources.ResourceManager resourceMan; - private static System.Globalization.CultureInfo resourceCulture; + private static global::System.Globalization.CultureInfo resourceCulture; - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal CliLocale() { } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - internal static System.Resources.ResourceManager ResourceManager { + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { get { - if (object.Equals(null, resourceMan)) { - System.Resources.ResourceManager temp = new System.Resources.ResourceManager("HitmanPatcher.CliLocale", typeof(CliLocale).Assembly); + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HitmanPatcher.CliLocale", typeof(CliLocale).Assembly); resourceMan = temp; } return resourceMan; } } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - internal static System.Globalization.CultureInfo Culture { + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -45,39 +60,57 @@ internal static System.Globalization.CultureInfo Culture { } } - internal static string HeadlessDescription { + /// + /// Looks up a localized string similar to The domain for the game to connect to.. + /// + internal static string DomainDescription { get { - return ResourceManager.GetString("HeadlessDescription", resourceCulture); + return ResourceManager.GetString("DomainDescription", resourceCulture); } } - internal static string DomainDescription { + /// + /// Looks up a localized string similar to ====== Peacock Patcher - Headless mode ======. + /// + internal static string HeadlessBanner { get { - return ResourceManager.GetString("DomainDescription", resourceCulture); + return ResourceManager.GetString("HeadlessBanner", resourceCulture); } } - internal static string UseHttpDescription { + /// + /// Looks up a localized string similar to If the patcher should be run without the GUI.. + /// + internal static string HeadlessDescription { get { - return ResourceManager.GetString("UseHttpDescription", resourceCulture); + return ResourceManager.GetString("HeadlessDescription", resourceCulture); } } - internal static string OptionalDynResDescription { + /// + /// Looks up a localized string similar to Peacock Patcher CLI - Copyright (c) 2020-2024 grappigegovert & The Peacock Project. + /// + internal static string HelpHeader { get { - return ResourceManager.GetString("OptionalDynResDescription", resourceCulture); + return ResourceManager.GetString("HelpHeader", resourceCulture); } } - internal static string HeadlessBanner { + /// + /// Looks up a localized string similar to If the game should not force the user offline if the dynamic resources are missing or invalid.. + /// + internal static string OptionalDynResDescription { get { - return ResourceManager.GetString("HeadlessBanner", resourceCulture); + return ResourceManager.GetString("OptionalDynResDescription", resourceCulture); } } - internal static string HelpHeader { + /// + /// Looks up a localized string similar to If the game should connect using "http://" instead of the default, "https://".. + /// + internal static string UseHttpDescription { get { - return ResourceManager.GetString("HelpHeader", resourceCulture); + return ResourceManager.GetString("UseHttpDescription", resourceCulture); } } } diff --git a/patcher/HitmanPatcher.csproj b/patcher/HitmanPatcher.csproj index c2914cd5e..e40f07a38 100644 --- a/patcher/HitmanPatcher.csproj +++ b/patcher/HitmanPatcher.csproj @@ -1,177 +1,44 @@ - - - - - - - - Debug - x64 - {0487D44B-B3E1-4A6E-91E0-47016C391A20} - WinExe - Properties - HitmanPatcher - PeacockPatcher - v4.6 - 512 - - True - False - False - False - False - None.None.None.Increment - None.None.None.Increment - 8 - - - - true - bin\x64\Debug\ - DEBUG;TRACE;PLATFORM_STEAM;PLATFORM_EPIC;PLATFORM_GOG;PLATFORM_SCARLETT - full - x64 - prompt - MinimumRecommendedRules.ruleset - true - - - - bin\x64\Release\ - TRACE;PLATFORM_STEAM;PLATFORM_EPIC - true - pdbonly - x64 - prompt - MinimumRecommendedRules.ruleset - true - - - - patcher.ico - - - - - - - - - - - - - - - - - - - True - True - CliLocale.resx - - - Form - - - MainForm.cs - - - - - Form - - - OptionsForm.cs - - - - - - - - - - - - - - - - - - - - - - Form - - - TrayOptionsForm.cs - - - ResXFileCodeGenerator - CliLocale.Designer.cs - - - MainForm.cs - Designer - - - OptionsForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - TrayOptionsForm.Designer.cs - - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - + + + WinExe + net8.0-windows + enable + disable + Peacock Patcher + Peacock's HITMAN™ World of Assassination trilogy game patcher. + The Peacock Project + Peacock Patcher + Copyright © 2020-2024 grappigegovert & The Peacock Project + true + true + DpiUnawareGdiScaled + patcher.ico + 8.0.0.0 + 8.0.0.0 + + + + + + + + + True + True + CliLocale.resx + + + True + True + Resources.resx + + + CliLocale.Designer.cs + ResXFileCodeGenerator + + + ResXFileCodeGenerator + Resources.Designer.cs + + diff --git a/patcher/HitmanPatcher.sln b/patcher/HitmanPatcher.sln index 1d06a1846..00681e0b2 100644 --- a/patcher/HitmanPatcher.sln +++ b/patcher/HitmanPatcher.sln @@ -1,20 +1,20 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34316.72 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitmanPatcher", "HitmanPatcher.csproj", "{0487D44B-B3E1-4A6E-91E0-47016C391A20}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HitmanPatcher", "HitmanPatcher.csproj", "{0487D44B-B3E1-4A6E-91E0-47016C391A20}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0487D44B-B3E1-4A6E-91E0-47016C391A20}.Debug|x64.ActiveCfg = Debug|x64 - {0487D44B-B3E1-4A6E-91E0-47016C391A20}.Debug|x64.Build.0 = Debug|x64 - {0487D44B-B3E1-4A6E-91E0-47016C391A20}.Release|x64.ActiveCfg = Release|x64 - {0487D44B-B3E1-4A6E-91E0-47016C391A20}.Release|x64.Build.0 = Release|x64 + {0487D44B-B3E1-4A6E-91E0-47016C391A20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0487D44B-B3E1-4A6E-91E0-47016C391A20}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0487D44B-B3E1-4A6E-91E0-47016C391A20}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0487D44B-B3E1-4A6E-91E0-47016C391A20}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/patcher/HitmanVersion.cs b/patcher/HitmanVersion.cs index 24ac7dc77..72c451dd4 100644 --- a/patcher/HitmanVersion.cs +++ b/patcher/HitmanVersion.cs @@ -1,11 +1,19 @@ -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Remoting.Metadata.W3cXsd2001; using System.Text; using HitmanPatcher.PatchDefinitions; namespace HitmanPatcher { + public static class SoapHexBinary + { + public static byte[] Parse(string value) + { + return Enumerable.Range(0, value.Length) + .Where(x => x % 2 == 0) + .Select(x => Convert.ToByte(value.Substring(x, 2), 16)) + .ToArray(); + } + } + public class Patch { public static readonly byte[] http = Encoding.ASCII.GetBytes("http://{0}\0").ToArray(); @@ -26,7 +34,7 @@ public Patch(int offset, byte[] original, byte[] patch, MemProtection defaultPro } public Patch(int offset, string original, string patch, MemProtection defaultProtection, string customPatch = "") - : this(offset, SoapHexBinary.Parse(original).Value, SoapHexBinary.Parse(patch).Value, defaultProtection, customPatch) + : this(offset, SoapHexBinary.Parse(original), SoapHexBinary.Parse(patch), defaultProtection, customPatch) { } diff --git a/patcher/MainForm.Designer.cs b/patcher/MainForm.Designer.cs index 5778da907..cbc6bae4d 100644 --- a/patcher/MainForm.Designer.cs +++ b/patcher/MainForm.Designer.cs @@ -1,4 +1,4 @@ -namespace HitmanPatcher +namespace HitmanPatcher { partial class MainForm { diff --git a/patcher/MainForm.cs b/patcher/MainForm.cs index 5a30dfe0e..b229e05fb 100644 --- a/patcher/MainForm.cs +++ b/patcher/MainForm.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.IO; using System.Text; +using Timer = System.Windows.Forms.Timer; namespace HitmanPatcher { diff --git a/patcher/Program.cs b/patcher/Program.cs index 2dadfe587..5fa1928e2 100644 --- a/patcher/Program.cs +++ b/patcher/Program.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Security.Principal; using System.Windows.Forms; @@ -39,6 +39,7 @@ private static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); + Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.Run(MainForm.GetInstance()); } diff --git a/patcher/Properties/AssemblyInfo.cs b/patcher/Properties/AssemblyInfo.cs deleted file mode 100644 index 40916fa24..000000000 --- a/patcher/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Peacock Patcher")] -[assembly: AssemblyDescription("Peacock's HITMAN™ World of Assassination trilogy game patcher.")] -#if DEBUG - [assembly: AssemblyConfiguration("Debug")] -#else - [assembly: AssemblyConfiguration("Release")] -#endif -[assembly: AssemblyCompany("The Peacock Project")] -[assembly: AssemblyProduct("Peacock Patcher")] -[assembly: AssemblyCopyright("Copyright © 2020-2024 grappigegovert & The Peacock Project")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("4f027fef-87be-47f7-a0c6-f3978dc707e3")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("8.0.0.0")] -[assembly: AssemblyFileVersion("8.0.0.0")] diff --git a/patcher/Properties/Resources.Designer.cs b/patcher/Properties/Resources.Designer.cs index 9aeb8e631..d71cafe80 100644 --- a/patcher/Properties/Resources.Designer.cs +++ b/patcher/Properties/Resources.Designer.cs @@ -1,22 +1,25 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ -namespace HitmanPatcher.Properties { +namespace HitmanPatcher.Properties { + using System; + + /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -30,7 +33,7 @@ internal Resources() { } /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -44,8 +47,8 @@ internal Resources() { } /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -58,7 +61,7 @@ internal Resources() { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Novikov_error { get { @@ -68,7 +71,7 @@ internal static System.Drawing.Bitmap Novikov_error { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Novikov_standard { get { @@ -78,7 +81,7 @@ internal static System.Drawing.Bitmap Novikov_standard { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Novikov_success { get { diff --git a/patcher/Properties/Resources.resx b/patcher/Properties/Resources.resx index 8de4204db..05f8454bd 100644 --- a/patcher/Properties/Resources.resx +++ b/patcher/Properties/Resources.resx @@ -1,23 +1,64 @@  - - + @@ -77,13 +118,13 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Novikov_standard.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Novikov_error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Novikov_standard.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Novikov_success.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - + \ No newline at end of file diff --git a/patcher/Properties/Settings.Designer.cs b/patcher/Properties/Settings.Designer.cs deleted file mode 100644 index eeee566bd..000000000 --- a/patcher/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace HitmanPatcher.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/patcher/Properties/Settings.settings b/patcher/Properties/Settings.settings deleted file mode 100644 index 39645652a..000000000 --- a/patcher/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - From e9c64188b19826366e16991410c421757ca4adf3 Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Tue, 13 Feb 2024 23:49:14 +0100 Subject: [PATCH 02/13] Split the codebase into two executables: UI and CLI --- patcher/.gitignore | 6 +- patcher/{ => HitmanPatcher.CLI}/Cli.cs | 19 +----- .../CliLocale.Designer.cs | 0 .../{ => HitmanPatcher.CLI}/CliLocale.resx | 0 .../HitmanPatcher.CLI.csproj} | 23 +++---- patcher/HitmanPatcher.CLI/Program.cs | 54 +++++++++++++++++ patcher/{ => HitmanPatcher.CLI}/patcher.ico | Bin .../{ => HitmanPatcher.Core}/AOBScanner.cs | 8 +-- patcher/HitmanPatcher.Core/Compositions.cs | 22 +++++++ .../HitmanPatcher.Core.csproj | 8 +++ .../{ => HitmanPatcher.Core}/HitmanVersion.cs | 0 .../{ => HitmanPatcher.Core}/MemoryPatcher.cs | 18 ++++-- .../PatchDefinitions/v1_12.cs | 0 .../PatchDefinitions/v1_15.cs | 0 .../PatchDefinitions/v1_16.cs | 0 .../PatchDefinitions/v2_13.cs | 0 .../PatchDefinitions/v2_71.cs | 0 .../PatchDefinitions/v2_72.cs | 0 .../PatchDefinitions/v3_10.cs | 0 .../PatchDefinitions/v3_100.cs | 0 .../PatchDefinitions/v3_11.cs | 0 .../PatchDefinitions/v3_110.cs | 0 .../PatchDefinitions/v3_120.cs | 0 .../PatchDefinitions/v3_20.cs | 0 .../PatchDefinitions/v3_30.cs | 0 .../PatchDefinitions/v3_40.cs | 0 .../PatchDefinitions/v3_50.cs | 0 .../PatchDefinitions/v3_70.cs | 0 .../PatchDefinitions/vScpc.cs | 0 patcher/{ => HitmanPatcher.Core}/Pinvoke.cs | 0 patcher/{ => HitmanPatcher.Core}/Settings.cs | 0 .../HitmanPatcher.UI/HitmanPatcher.UI.csproj | 55 +++++++++++++++++ .../MainForm.Designer.cs | 0 patcher/{ => HitmanPatcher.UI}/MainForm.cs | 0 patcher/{ => HitmanPatcher.UI}/MainForm.resx | 0 .../{ => HitmanPatcher.UI}/Novikov_error.png | Bin .../Novikov_standard.png | Bin .../Novikov_success.png | Bin .../OptionsForm.Designer.cs | 0 patcher/{ => HitmanPatcher.UI}/OptionsForm.cs | 0 .../{ => HitmanPatcher.UI}/OptionsForm.resx | 0 patcher/HitmanPatcher.UI/Program.cs | 24 ++++++++ .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../TrayOptionsForm.Designer.cs | 0 .../{ => HitmanPatcher.UI}/TrayOptionsForm.cs | 0 .../TrayOptionsForm.resx | 0 patcher/HitmanPatcher.UI/patcher.ico | Bin 0 -> 4286 bytes patcher/HitmanPatcher.sln | 25 ++++++-- patcher/Program.cs | 56 ------------------ 50 files changed, 211 insertions(+), 107 deletions(-) rename patcher/{ => HitmanPatcher.CLI}/Cli.cs (80%) rename patcher/{ => HitmanPatcher.CLI}/CliLocale.Designer.cs (100%) rename patcher/{ => HitmanPatcher.CLI}/CliLocale.resx (100%) rename patcher/{HitmanPatcher.csproj => HitmanPatcher.CLI/HitmanPatcher.CLI.csproj} (65%) create mode 100644 patcher/HitmanPatcher.CLI/Program.cs rename patcher/{ => HitmanPatcher.CLI}/patcher.ico (100%) rename patcher/{ => HitmanPatcher.Core}/AOBScanner.cs (98%) create mode 100644 patcher/HitmanPatcher.Core/Compositions.cs create mode 100644 patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj rename patcher/{ => HitmanPatcher.Core}/HitmanVersion.cs (100%) rename patcher/{ => HitmanPatcher.Core}/MemoryPatcher.cs (96%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v1_12.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v1_15.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v1_16.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v2_13.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v2_71.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v2_72.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_10.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_100.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_11.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_110.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_120.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_20.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_30.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_40.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_50.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/v3_70.cs (100%) rename patcher/{ => HitmanPatcher.Core}/PatchDefinitions/vScpc.cs (100%) rename patcher/{ => HitmanPatcher.Core}/Pinvoke.cs (100%) rename patcher/{ => HitmanPatcher.Core}/Settings.cs (100%) create mode 100644 patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj rename patcher/{ => HitmanPatcher.UI}/MainForm.Designer.cs (100%) rename patcher/{ => HitmanPatcher.UI}/MainForm.cs (100%) rename patcher/{ => HitmanPatcher.UI}/MainForm.resx (100%) rename patcher/{ => HitmanPatcher.UI}/Novikov_error.png (100%) rename patcher/{ => HitmanPatcher.UI}/Novikov_standard.png (100%) rename patcher/{ => HitmanPatcher.UI}/Novikov_success.png (100%) rename patcher/{ => HitmanPatcher.UI}/OptionsForm.Designer.cs (100%) rename patcher/{ => HitmanPatcher.UI}/OptionsForm.cs (100%) rename patcher/{ => HitmanPatcher.UI}/OptionsForm.resx (100%) create mode 100644 patcher/HitmanPatcher.UI/Program.cs rename patcher/{ => HitmanPatcher.UI}/Properties/Resources.Designer.cs (100%) rename patcher/{ => HitmanPatcher.UI}/Properties/Resources.resx (100%) rename patcher/{ => HitmanPatcher.UI}/TrayOptionsForm.Designer.cs (100%) rename patcher/{ => HitmanPatcher.UI}/TrayOptionsForm.cs (100%) rename patcher/{ => HitmanPatcher.UI}/TrayOptionsForm.resx (100%) create mode 100644 patcher/HitmanPatcher.UI/patcher.ico delete mode 100644 patcher/Program.cs diff --git a/patcher/.gitignore b/patcher/.gitignore index d74468c11..b876dba69 100644 --- a/patcher/.gitignore +++ b/patcher/.gitignore @@ -1,6 +1,6 @@ -.vs/* -bin/* -obj/* +.vs +bin +obj /HitmanPatcher.sln.DotSettings.user /.idea/.idea.HitmanPatcher/.idea/riderMarkupCache.xml *.suo diff --git a/patcher/Cli.cs b/patcher/HitmanPatcher.CLI/Cli.cs similarity index 80% rename from patcher/Cli.cs rename to patcher/HitmanPatcher.CLI/Cli.cs index 413614f27..96ac6d9d8 100644 --- a/patcher/Cli.cs +++ b/patcher/HitmanPatcher.CLI/Cli.cs @@ -30,24 +30,15 @@ internal static void EnsureConsole(string[] args) internal class CliOptions { - internal bool Headless { get; set; } - internal string Domain { get; set; } - internal bool UseHttp { get; set; } + internal bool? UseHttp { get; set; } - internal bool OptionalDynRes { get; set; } + internal bool? OptionalDynRes { get; set; } - [SuppressMessage("ReSharper", "LocalizableElement")] internal static CliOptions FromArguments(string[] args) { - var options = new CliOptions - { - Domain = "127.0.0.1", - Headless = false, - OptionalDynRes = true, - UseHttp = true - }; + var options = new CliOptions(); var i = 0; @@ -63,9 +54,6 @@ internal static CliOptions FromArguments(string[] args) { switch (arg) { - case "--headless": - options.Headless = true; - break; case "--optional-dynamic-resources": options.OptionalDynRes = true; break; @@ -80,7 +68,6 @@ internal static CliOptions FromArguments(string[] args) Console.WriteLine(CliLocale.HelpHeader); Console.WriteLine(""); Console.WriteLine("Options:"); - Console.WriteLine($" --headless : {CliLocale.HeadlessDescription}"); Console.WriteLine($" --optional-dynamic-resources : {CliLocale.OptionalDynResDescription}"); Console.WriteLine($" --domain : {CliLocale.DomainDescription}"); Console.WriteLine($" --use-http : {CliLocale.UseHttpDescription}"); diff --git a/patcher/CliLocale.Designer.cs b/patcher/HitmanPatcher.CLI/CliLocale.Designer.cs similarity index 100% rename from patcher/CliLocale.Designer.cs rename to patcher/HitmanPatcher.CLI/CliLocale.Designer.cs diff --git a/patcher/CliLocale.resx b/patcher/HitmanPatcher.CLI/CliLocale.resx similarity index 100% rename from patcher/CliLocale.resx rename to patcher/HitmanPatcher.CLI/CliLocale.resx diff --git a/patcher/HitmanPatcher.csproj b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj similarity index 65% rename from patcher/HitmanPatcher.csproj rename to patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj index e40f07a38..899f4b8c3 100644 --- a/patcher/HitmanPatcher.csproj +++ b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj @@ -1,15 +1,17 @@ - WinExe - net8.0-windows + Exe + net8.0 enable disable + + HitmanPatcher + Peacock Patcher Peacock's HITMAN™ World of Assassination trilogy game patcher. The Peacock Project Peacock Patcher Copyright © 2020-2024 grappigegovert & The Peacock Project - true true DpiUnawareGdiScaled patcher.ico @@ -18,27 +20,18 @@ - + + CliLocale.resx True True - CliLocale.resx - - - True - True - Resources.resx CliLocale.Designer.cs ResXFileCodeGenerator - - ResXFileCodeGenerator - Resources.Designer.cs - - + \ No newline at end of file diff --git a/patcher/HitmanPatcher.CLI/Program.cs b/patcher/HitmanPatcher.CLI/Program.cs new file mode 100644 index 000000000..f4228e25c --- /dev/null +++ b/patcher/HitmanPatcher.CLI/Program.cs @@ -0,0 +1,54 @@ +namespace HitmanPatcher +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + private static void Main(string[] args) + { + Compositions.Initialize(); + Compositions.Logger = new Cli.ConsoleLogger(); + +#if !DEBUG + Cli.EnsureConsole(args); +#endif + + Cli.CliOptions o = Cli.CliOptions.FromArguments(args); + + // ReSharper disable once LocalizableElement + Console.WriteLine(CliLocale.HeadlessBanner); + + var settings = Settings.GetFromFile(); + settings.SaveToFile(); + + Console.WriteLine("Settings:"); + Console.WriteLine($"- CustomConfigDomain = {settings.patchOptions.CustomConfigDomain}"); + Console.WriteLine($"- UseHttp = {settings.patchOptions.UseHttp}"); + Console.WriteLine($"- DisableForceDynamicResources = {settings.patchOptions.DisableForceOfflineOnFailedDynamicResources}"); + Console.WriteLine(); + + bool result = false; + + while(!result) + { + result = MemoryPatcher.PatchAllProcesses(Compositions.Logger, settings.patchOptions with + { + CustomConfigDomain = o.Domain ?? settings.patchOptions.CustomConfigDomain, + DisableForceOfflineOnFailedDynamicResources = o.OptionalDynRes ?? settings.patchOptions.DisableForceOfflineOnFailedDynamicResources, + UseHttp = o.UseHttp ?? settings.patchOptions.UseHttp + }); + + if (result) + { + continue; + } + + Console.WriteLine("Waiting..."); + + Thread.Sleep(1000); + } + } + } +} diff --git a/patcher/patcher.ico b/patcher/HitmanPatcher.CLI/patcher.ico similarity index 100% rename from patcher/patcher.ico rename to patcher/HitmanPatcher.CLI/patcher.ico diff --git a/patcher/AOBScanner.cs b/patcher/HitmanPatcher.Core/AOBScanner.cs similarity index 98% rename from patcher/AOBScanner.cs rename to patcher/HitmanPatcher.Core/AOBScanner.cs index 89b9ee49c..1c2f166b3 100644 --- a/patcher/AOBScanner.cs +++ b/patcher/HitmanPatcher.Core/AOBScanner.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; namespace HitmanPatcher { @@ -77,7 +73,7 @@ public static bool TryGetHitmanVersionByScanning(Process process, Task.WaitAll(alltasks); bench.Stop(); - Console.WriteLine(bench.Elapsed.ToString()); + Compositions.Logger.log(bench.Elapsed.ToString()); // error out if any task does not have exactly 1 result if (alltasks.Any(task => task.Result.Count() != 1)) @@ -113,7 +109,7 @@ public static bool TryGetHitmanVersionByScanning(Process process, #if DEBUG private static void Note(string name, Patch patch) { - MainForm.GetInstance().log($"{name}: {patch.offset:X} {BitConverter.ToString(patch.original).Replace("-", string.Empty)} {BitConverter.ToString(patch.patch).Replace("-", string.Empty)}"); + Compositions.Logger.log($"{name}: {patch.offset:X} {BitConverter.ToString(patch.original).Replace("-", string.Empty)} {BitConverter.ToString(patch.patch).Replace("-", string.Empty)}"); } #endif diff --git a/patcher/HitmanPatcher.Core/Compositions.cs b/patcher/HitmanPatcher.Core/Compositions.cs new file mode 100644 index 000000000..fc9578729 --- /dev/null +++ b/patcher/HitmanPatcher.Core/Compositions.cs @@ -0,0 +1,22 @@ +using System.Security.Principal; + +namespace HitmanPatcher +{ + public static class Compositions + { + public static bool HasAdmin; + public static ILoggingProvider Logger; + + public static void Initialize() + { + HasAdmin = CheckForAdmin(); + } + + private static bool CheckForAdmin() + { + WindowsIdentity identity = WindowsIdentity.GetCurrent(); + WindowsPrincipal principal = new WindowsPrincipal(identity); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } + } +} diff --git a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj new file mode 100644 index 000000000..c8e85511c --- /dev/null +++ b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj @@ -0,0 +1,8 @@ + + + net8.0 + enable + disable + HitmanPatcher + + diff --git a/patcher/HitmanVersion.cs b/patcher/HitmanPatcher.Core/HitmanVersion.cs similarity index 100% rename from patcher/HitmanVersion.cs rename to patcher/HitmanPatcher.Core/HitmanVersion.cs diff --git a/patcher/MemoryPatcher.cs b/patcher/HitmanPatcher.Core/MemoryPatcher.cs similarity index 96% rename from patcher/MemoryPatcher.cs rename to patcher/HitmanPatcher.Core/MemoryPatcher.cs index 668556b30..ffb66fa38 100644 --- a/patcher/MemoryPatcher.cs +++ b/patcher/HitmanPatcher.Core/MemoryPatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; @@ -52,8 +52,10 @@ private static List GetProcessesByName(params string[] names) return result; } - public static void PatchAllProcesses(ILoggingProvider logger, Options patchOptions) - { + public static bool PatchAllProcesses(ILoggingProvider logger, Options patchOptions) + { + bool patched = false; + IEnumerable hitmans = GetProcessesByName("HITMAN", "HITMAN2", "HITMAN3"); foreach (Process process in hitmans) { @@ -69,7 +71,7 @@ public static void PatchAllProcesses(ILoggingProvider logger, Options patchOptio } catch (Win32Exception ex) { - if (ex.NativeErrorCode == 5 && !Program.HasAdmin) + if (ex.NativeErrorCode == 5 && !Compositions.HasAdmin) { logger.log(String.Format("Access denied, try running the patcher as admin.")); process.Dispose(); @@ -95,7 +97,9 @@ public static void PatchAllProcesses(ILoggingProvider logger, Options patchOptio { logger.log(String.Format("Injected server: {0}", patchOptions.CustomConfigDomain)); } - } + + patched = true; + } else { // else: process not yet ready for patching, try again next timer tick @@ -114,7 +118,9 @@ public static void PatchAllProcesses(ILoggingProvider logger, Options patchOptio } process.Dispose(); } - } + + return patched; + } public static bool Patch(Process process, Options patchOptions) { diff --git a/patcher/PatchDefinitions/v1_12.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v1_12.cs similarity index 100% rename from patcher/PatchDefinitions/v1_12.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v1_12.cs diff --git a/patcher/PatchDefinitions/v1_15.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v1_15.cs similarity index 100% rename from patcher/PatchDefinitions/v1_15.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v1_15.cs diff --git a/patcher/PatchDefinitions/v1_16.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v1_16.cs similarity index 100% rename from patcher/PatchDefinitions/v1_16.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v1_16.cs diff --git a/patcher/PatchDefinitions/v2_13.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v2_13.cs similarity index 100% rename from patcher/PatchDefinitions/v2_13.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v2_13.cs diff --git a/patcher/PatchDefinitions/v2_71.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v2_71.cs similarity index 100% rename from patcher/PatchDefinitions/v2_71.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v2_71.cs diff --git a/patcher/PatchDefinitions/v2_72.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v2_72.cs similarity index 100% rename from patcher/PatchDefinitions/v2_72.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v2_72.cs diff --git a/patcher/PatchDefinitions/v3_10.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_10.cs similarity index 100% rename from patcher/PatchDefinitions/v3_10.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_10.cs diff --git a/patcher/PatchDefinitions/v3_100.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_100.cs similarity index 100% rename from patcher/PatchDefinitions/v3_100.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_100.cs diff --git a/patcher/PatchDefinitions/v3_11.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_11.cs similarity index 100% rename from patcher/PatchDefinitions/v3_11.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_11.cs diff --git a/patcher/PatchDefinitions/v3_110.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_110.cs similarity index 100% rename from patcher/PatchDefinitions/v3_110.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_110.cs diff --git a/patcher/PatchDefinitions/v3_120.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_120.cs similarity index 100% rename from patcher/PatchDefinitions/v3_120.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_120.cs diff --git a/patcher/PatchDefinitions/v3_20.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_20.cs similarity index 100% rename from patcher/PatchDefinitions/v3_20.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_20.cs diff --git a/patcher/PatchDefinitions/v3_30.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_30.cs similarity index 100% rename from patcher/PatchDefinitions/v3_30.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_30.cs diff --git a/patcher/PatchDefinitions/v3_40.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_40.cs similarity index 100% rename from patcher/PatchDefinitions/v3_40.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_40.cs diff --git a/patcher/PatchDefinitions/v3_50.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_50.cs similarity index 100% rename from patcher/PatchDefinitions/v3_50.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_50.cs diff --git a/patcher/PatchDefinitions/v3_70.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/v3_70.cs similarity index 100% rename from patcher/PatchDefinitions/v3_70.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/v3_70.cs diff --git a/patcher/PatchDefinitions/vScpc.cs b/patcher/HitmanPatcher.Core/PatchDefinitions/vScpc.cs similarity index 100% rename from patcher/PatchDefinitions/vScpc.cs rename to patcher/HitmanPatcher.Core/PatchDefinitions/vScpc.cs diff --git a/patcher/Pinvoke.cs b/patcher/HitmanPatcher.Core/Pinvoke.cs similarity index 100% rename from patcher/Pinvoke.cs rename to patcher/HitmanPatcher.Core/Pinvoke.cs diff --git a/patcher/Settings.cs b/patcher/HitmanPatcher.Core/Settings.cs similarity index 100% rename from patcher/Settings.cs rename to patcher/HitmanPatcher.Core/Settings.cs diff --git a/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj new file mode 100644 index 000000000..d40359cb3 --- /dev/null +++ b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj @@ -0,0 +1,55 @@ + + + WinExe + net8.0-windows + enable + disable + + HitmanPatcher + + Peacock Patcher + Peacock's HITMAN™ World of Assassination trilogy game patcher. + The Peacock Project + Peacock Patcher + Copyright © 2020-2024 grappigegovert & The Peacock Project + true + true + DpiUnawareGdiScaled + patcher.ico + 8.0.0.0 + 8.0.0.0 + + + + + + + + + + + + + Form + + + Form + + + True + True + Resources.resx + + + Form + + + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + diff --git a/patcher/MainForm.Designer.cs b/patcher/HitmanPatcher.UI/MainForm.Designer.cs similarity index 100% rename from patcher/MainForm.Designer.cs rename to patcher/HitmanPatcher.UI/MainForm.Designer.cs diff --git a/patcher/MainForm.cs b/patcher/HitmanPatcher.UI/MainForm.cs similarity index 100% rename from patcher/MainForm.cs rename to patcher/HitmanPatcher.UI/MainForm.cs diff --git a/patcher/MainForm.resx b/patcher/HitmanPatcher.UI/MainForm.resx similarity index 100% rename from patcher/MainForm.resx rename to patcher/HitmanPatcher.UI/MainForm.resx diff --git a/patcher/Novikov_error.png b/patcher/HitmanPatcher.UI/Novikov_error.png similarity index 100% rename from patcher/Novikov_error.png rename to patcher/HitmanPatcher.UI/Novikov_error.png diff --git a/patcher/Novikov_standard.png b/patcher/HitmanPatcher.UI/Novikov_standard.png similarity index 100% rename from patcher/Novikov_standard.png rename to patcher/HitmanPatcher.UI/Novikov_standard.png diff --git a/patcher/Novikov_success.png b/patcher/HitmanPatcher.UI/Novikov_success.png similarity index 100% rename from patcher/Novikov_success.png rename to patcher/HitmanPatcher.UI/Novikov_success.png diff --git a/patcher/OptionsForm.Designer.cs b/patcher/HitmanPatcher.UI/OptionsForm.Designer.cs similarity index 100% rename from patcher/OptionsForm.Designer.cs rename to patcher/HitmanPatcher.UI/OptionsForm.Designer.cs diff --git a/patcher/OptionsForm.cs b/patcher/HitmanPatcher.UI/OptionsForm.cs similarity index 100% rename from patcher/OptionsForm.cs rename to patcher/HitmanPatcher.UI/OptionsForm.cs diff --git a/patcher/OptionsForm.resx b/patcher/HitmanPatcher.UI/OptionsForm.resx similarity index 100% rename from patcher/OptionsForm.resx rename to patcher/HitmanPatcher.UI/OptionsForm.resx diff --git a/patcher/HitmanPatcher.UI/Program.cs b/patcher/HitmanPatcher.UI/Program.cs new file mode 100644 index 000000000..20879440b --- /dev/null +++ b/patcher/HitmanPatcher.UI/Program.cs @@ -0,0 +1,24 @@ +namespace HitmanPatcher +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + private static void Main(string[] args) + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.SetHighDpiMode(HighDpiMode.SystemAware); + + Compositions.Initialize(); + + var mainForm = MainForm.GetInstance(); + + Compositions.Logger = mainForm; + + Application.Run(mainForm); + } + } +} diff --git a/patcher/Properties/Resources.Designer.cs b/patcher/HitmanPatcher.UI/Properties/Resources.Designer.cs similarity index 100% rename from patcher/Properties/Resources.Designer.cs rename to patcher/HitmanPatcher.UI/Properties/Resources.Designer.cs diff --git a/patcher/Properties/Resources.resx b/patcher/HitmanPatcher.UI/Properties/Resources.resx similarity index 100% rename from patcher/Properties/Resources.resx rename to patcher/HitmanPatcher.UI/Properties/Resources.resx diff --git a/patcher/TrayOptionsForm.Designer.cs b/patcher/HitmanPatcher.UI/TrayOptionsForm.Designer.cs similarity index 100% rename from patcher/TrayOptionsForm.Designer.cs rename to patcher/HitmanPatcher.UI/TrayOptionsForm.Designer.cs diff --git a/patcher/TrayOptionsForm.cs b/patcher/HitmanPatcher.UI/TrayOptionsForm.cs similarity index 100% rename from patcher/TrayOptionsForm.cs rename to patcher/HitmanPatcher.UI/TrayOptionsForm.cs diff --git a/patcher/TrayOptionsForm.resx b/patcher/HitmanPatcher.UI/TrayOptionsForm.resx similarity index 100% rename from patcher/TrayOptionsForm.resx rename to patcher/HitmanPatcher.UI/TrayOptionsForm.resx diff --git a/patcher/HitmanPatcher.UI/patcher.ico b/patcher/HitmanPatcher.UI/patcher.ico new file mode 100644 index 0000000000000000000000000000000000000000..82463fcea416563228817868e36e6719ba8efb5e GIT binary patch literal 4286 zcma)9du)@}6~C+kG@(Jr!%6HocKnLp_UE@9zZ1U_JC5@r2~J1|&a*($P)OT^q%E{v zplgA(YCB4c*t$nsF;!G!nx?LQFo{)_CfZHfq)F8_6=~I`c7JSWo%rqCj|P#925xln zefNH!zu!6MckVgoGPa5SluE|`vmcc)CSi=}Noa{hN%;Ex4y8)X)LI>r*2!6Ibv2XK z*4~n83DXgUK3#(b5FF^Og=~vkz9% zMOjVw<>ky~GO}7pIctuDnWUzc?JO&2_rh1}j7;^F{ha%U9$vxh%nDpWEBu~3Y(fSG zO9X123l@7s#I_1iQ5UN%ghqo4Hg_C?KS{pW$=rgS?H$Om>RKtQApCOTV57nD8;FBi zSsjx~rQaxYmC&6Ufl+0KRwY2K7SPaO5wUHKn27K6ByQ`$beX7WAvgNerj3Fk(u_rmUIfz{ItjxSdzS&dZ2D#|PGiQj0niuUv09GX9Y ze106>Kps`q3RFuJkjV_>e*s=^3Oa*N-`vJ0+bb(8 zH!`2;%@(Gl93ZW$V-r&gIJxpFx;n>TFomE{SfHra!{biC?@z($Y!>5=$Dzxcgxi;b zg|G!zGk8q6d>x#VFAg3#`aAA_j(tD)3blsGn^FX1pqh4V^ZB->)b`u;{1KIE7xd)A;6ZZq>pT}i@^lR@dp-yVW zaB&GvcQ>jjpG&H$?*_k(7I8Px>$Es?<~($!DC|}nv})Du_mat^crOToc;)fH{loW$ z%S#-EBk;u%kW?w)cV*B$u!NfG+V%LEJ8?mS&%gZgOYyp8%ND%;=KFB?v!J~zuC2a* z{rYtj3I*J_aRU~MQ&6o&tvoE%}}XS&}fW^Co-@&eUQ}|(V%e>he45pHRz08 zr1?iAeQXMX9@B~V=B+O=!qZ>4er8g0at(FT>ljCisQ26Ie&wr$%se*M~^ zX*4mJLb)lMEn;Hg5JpC3k<0DD(&J~aXLt&S4=qz}3sVlXLvIelO}Qb}xgYWDK7?8Z z5s3FgP5hhfZfFTx)o6mwY(+(l45_Z3yV<`+7oPw5-h1cr6`VVN5i2XNkYAs{snf5c zSbPwfOg}Q&-N<*1AxK#MNH3z9eTcP|5KiqyD85_V0~Wyp!5x4zNcqtlh9{grS8(D=8#wvgt9bI*X&gE7G^X}1Af4Go zeNP%T+S3kihbXc12n1gN4o`-1g&92qeZ)lqdch5|!w+w$1%+Kjq+45`T?4po!gFs8 z^?b{Z&wqURy=!>w{98DB^d$QF#?a9|fT5u&s!4m`^|y)m++L@bIA|h&5Vl(FBrekE z>gz>sZ!e5aFN}mApuHGt?FRYwo9iIgOnLt+t(7s2wqeVMfBYQ#M)$*PwIWx@lAj~u zcWHls{6u@I2|8nlYH*VJvY43noW3T6VsW&0bf7igj^=cR`k^5Fu{8QeCOH4!S_8Ol zqM+PQeGgNs)okw3xnE?nSp=g^=Su^%GNnSE<`Bqnp0_b!!bB$%^Qj%oXo)&2=wzBw9(-B z+kf9*+Sevu#v+ zVpRYA2qhAv1NkId;J#<~!sor>D*oKz@t>VO^(1Cy$1yiIj?!2W57GVj^e_sY9cb?= zAV^$$BGm7?=`7&&!RZep)1E_uaJdeVL<`OHn0a{aU%d9+3!mq{ReXMZ>7^CS96E>t z2TSNH_G0&*0hA_3F}SB+oTKZE6OFJb2J zET(3rQQSL-Ba8DG-Zz8?_fMj8R}bbF4r6erh|mf`|eeIe*Rg# zryhs=aPhNWeRu^6PanhiAHRlEFF%J9r=P{b@h5Qn#8bHN=J)Zz$G^dwKm8%3WP@BT zzukL__H!NX-hbWpKhOOfliR&|_U7N>Yy2#%H)vUVAs>4GgZF;>r%(Uzm;c)%7suz|)ljYhMX|CZMe?n62C@%)>s{$G!ePpH{hj*uv*>Dfy10B(x1iLQ*x5=n$a u@n4c<#`pntRkq%sds^Shh29b6j`5Q; - /// The main entry point for the application. - /// - [STAThread] - private static void Main(string[] args) - { - HasAdmin = CheckForAdmin(); -#if !DEBUG - Cli.EnsureConsole(args); -#endif - - Cli.CliOptions o = Cli.CliOptions.FromArguments(args); - - if (o.Headless) - { - // ReSharper disable once LocalizableElement - Console.WriteLine(CliLocale.HeadlessBanner); - MemoryPatcher.PatchAllProcesses(new Cli.ConsoleLogger(), new MemoryPatcher.Options - { - AlwaysSendAuthHeader = true, - CustomConfigDomain = o.Domain, - DisableCertPinning = true, - DisableForceOfflineOnFailedDynamicResources = o.OptionalDynRes, - SetCustomConfigDomain = true, - UseHttp = o.UseHttp - }); - } - else - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.SetHighDpiMode(HighDpiMode.SystemAware); - - Application.Run(MainForm.GetInstance()); - } - } - - static bool CheckForAdmin() - { - WindowsIdentity identity = WindowsIdentity.GetCurrent(); - WindowsPrincipal principal = new WindowsPrincipal(identity); - return principal.IsInRole(WindowsBuiltInRole.Administrator); - } - - } -} From a784bc985a6f3fb7daed9f0418aee98f98cb2362 Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Wed, 14 Feb 2024 00:52:30 +0100 Subject: [PATCH 03/13] Updated patcher workflow --- .github/workflows/patcher.yml | 36 +++++++++++++++---- .../HitmanPatcher.CLI.csproj | 1 + patcher/HitmanPatcher.Core/Compositions.cs | 6 ++++ .../HitmanPatcher.Core.csproj | 2 ++ .../HitmanPatcher.UI/HitmanPatcher.UI.csproj | 2 ++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/.github/workflows/patcher.yml b/.github/workflows/patcher.yml index 89fcb2f07..ad79c802e 100644 --- a/.github/workflows/patcher.yml +++ b/.github/workflows/patcher.yml @@ -8,23 +8,45 @@ on: branches: [ "v*" ] paths: [ "patcher/**/*" ] +env: + DOTNET_VERSION: 8.x + jobs: build: name: Build Patcher - runs-on: windows-latest + runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v2 + - name: Setup .NET Core + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} - name: Build Patcher - run: msbuild.exe patcher\HitmanPatcher.sln -t:Build -p:Configuration=Release -p:Platform=x64 -m + run: | + export DOTNET_NOLOGO=true + export DOTNET_CLI_TELEMETRY_OPTOUT=true + dotnet publish patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True --nologo -o patcher/Publish/Windows-x64 + dotnet publish patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none --nologo -o patcher/Publish/Linux-x64 + dotnet publish patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True --nologo -o patcher/Publish/Windows-x64 + + - name: Upload patcher-windows-cli + uses: actions/upload-artifact@v4 + with: + name: patcher-windows-cli + path: patcher/Publish/Windows-x64/PeacockPatcher.CLI.exe + + - name: Upload patcher-windows-ui + uses: actions/upload-artifact@v4 + with: + name: patcher-windows-ui + path: patcher/Publish/Windows-x64/PeacockPatcher.UI.exe - - name: Upload Patcher Artifacts + - name: Upload patcher-linux-cli uses: actions/upload-artifact@v4 with: - name: patcher-windows - path: patcher/bin/x64/Release/PeacockPatcher.exe + name: patcher-linux-cli + path: patcher/Publish/Linux-x64/PeacockPatcher.CLI.exe diff --git a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj index 899f4b8c3..99b7b718c 100644 --- a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj +++ b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj @@ -6,6 +6,7 @@ disable HitmanPatcher + PeacockPatcher.CLI Peacock Patcher Peacock's HITMAN™ World of Assassination trilogy game patcher. diff --git a/patcher/HitmanPatcher.Core/Compositions.cs b/patcher/HitmanPatcher.Core/Compositions.cs index fc9578729..fdb038f58 100644 --- a/patcher/HitmanPatcher.Core/Compositions.cs +++ b/patcher/HitmanPatcher.Core/Compositions.cs @@ -1,4 +1,6 @@ +#if WINDOWS using System.Security.Principal; +#endif namespace HitmanPatcher { @@ -14,9 +16,13 @@ public static void Initialize() private static bool CheckForAdmin() { +#if WINDOWS WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); return principal.IsInRole(WindowsBuiltInRole.Administrator); +#else + return false; +#endif } } } diff --git a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj index c8e85511c..12cd31443 100644 --- a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj +++ b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj @@ -3,6 +3,8 @@ net8.0 enable disable + HitmanPatcher + PeacockPatcher.Core diff --git a/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj index d40359cb3..2eb34b1d8 100644 --- a/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj +++ b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj @@ -6,6 +6,8 @@ disable HitmanPatcher + true + PeacockPatcher.UI Peacock Patcher Peacock's HITMAN™ World of Assassination trilogy game patcher. From f9769208a76f3b29876cff09431b0abc7acf854e Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Wed, 14 Feb 2024 01:45:03 +0100 Subject: [PATCH 04/13] Added support for unix file paths Updated workflow to also build smaller portable executables --- .github/workflows/patcher.yml | 43 ++++++++++++++----- patcher/.gitignore | 1 + .../HitmanPatcher.CLI.csproj | 4 +- patcher/HitmanPatcher.CLI/Program.cs | 1 + patcher/HitmanPatcher.Core/Compositions.cs | 8 ++-- .../HitmanPatcher.Core.csproj | 3 ++ patcher/HitmanPatcher.Core/Settings.cs | 34 +++++++-------- .../HitmanPatcher.UI/HitmanPatcher.UI.csproj | 2 + patcher/build.bat | 14 ++++++ 9 files changed, 77 insertions(+), 33 deletions(-) create mode 100644 patcher/build.bat diff --git a/.github/workflows/patcher.yml b/.github/workflows/patcher.yml index ad79c802e..0ca44033c 100644 --- a/.github/workflows/patcher.yml +++ b/.github/workflows/patcher.yml @@ -29,24 +29,47 @@ jobs: run: | export DOTNET_NOLOGO=true export DOTNET_CLI_TELEMETRY_OPTOUT=true - dotnet publish patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True --nologo -o patcher/Publish/Windows-x64 - dotnet publish patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none --nologo -o patcher/Publish/Linux-x64 - dotnet publish patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True --nologo -o patcher/Publish/Windows-x64 + cd patcher + dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable + dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 + dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-Portable + dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-x64 + dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable + dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 - - name: Upload patcher-windows-cli + - name: Upload patcher-cli-windows-portable uses: actions/upload-artifact@v4 with: - name: patcher-windows-cli + name: patcher-cli-windows-portable + path: patcher/Publish/Windows-Portable/PeacockPatcher.CLI.exe + + - name: Upload patcher-cli-windows + uses: actions/upload-artifact@v4 + with: + name: patcher-cli-windows path: patcher/Publish/Windows-x64/PeacockPatcher.CLI.exe - - name: Upload patcher-windows-ui + - name: Upload patcher-cli-linux-portable uses: actions/upload-artifact@v4 with: - name: patcher-windows-ui - path: patcher/Publish/Windows-x64/PeacockPatcher.UI.exe + name: patcher-cli-linux-portable + path: patcher/Publish/Linux-Portable/PeacockPatcher.CLI.exe - - name: Upload patcher-linux-cli + - name: Upload patcher-cli-linux uses: actions/upload-artifact@v4 with: - name: patcher-linux-cli + name: patcher-cli-linux path: patcher/Publish/Linux-x64/PeacockPatcher.CLI.exe + + - name: Upload patcher-ui-windows-portable + uses: actions/upload-artifact@v4 + with: + name: patcher-ui-windows-portable + path: patcher/Publish/Windows-Portable/PeacockPatcher.UI.exe + + - name: Upload patcher-ui-windows + uses: actions/upload-artifact@v4 + with: + name: patcher-ui-windows + path: patcher/Publish/Windows-x64/PeacockPatcher.UI.exe + diff --git a/patcher/.gitignore b/patcher/.gitignore index b876dba69..3c8224636 100644 --- a/patcher/.gitignore +++ b/patcher/.gitignore @@ -1,6 +1,7 @@ .vs bin obj +/Publish /HitmanPatcher.sln.DotSettings.user /.idea/.idea.HitmanPatcher/.idea/riderMarkupCache.xml *.suo diff --git a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj index 99b7b718c..f910a37a8 100644 --- a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj +++ b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj @@ -7,7 +7,7 @@ HitmanPatcher PeacockPatcher.CLI - + Peacock Patcher Peacock's HITMAN™ World of Assassination trilogy game patcher. The Peacock Project @@ -18,6 +18,8 @@ patcher.ico 8.0.0.0 8.0.0.0 + + $(DefineConstants);LINUX diff --git a/patcher/HitmanPatcher.CLI/Program.cs b/patcher/HitmanPatcher.CLI/Program.cs index f4228e25c..f25d6bac8 100644 --- a/patcher/HitmanPatcher.CLI/Program.cs +++ b/patcher/HitmanPatcher.CLI/Program.cs @@ -24,6 +24,7 @@ private static void Main(string[] args) settings.SaveToFile(); Console.WriteLine("Settings:"); + Console.WriteLine($"- File = {Path.GetFullPath(Settings.GetSavePath())}"); Console.WriteLine($"- CustomConfigDomain = {settings.patchOptions.CustomConfigDomain}"); Console.WriteLine($"- UseHttp = {settings.patchOptions.UseHttp}"); Console.WriteLine($"- DisableForceDynamicResources = {settings.patchOptions.DisableForceOfflineOnFailedDynamicResources}"); diff --git a/patcher/HitmanPatcher.Core/Compositions.cs b/patcher/HitmanPatcher.Core/Compositions.cs index fdb038f58..184e2d47c 100644 --- a/patcher/HitmanPatcher.Core/Compositions.cs +++ b/patcher/HitmanPatcher.Core/Compositions.cs @@ -1,4 +1,4 @@ -#if WINDOWS +#if !LINUX using System.Security.Principal; #endif @@ -16,12 +16,12 @@ public static void Initialize() private static bool CheckForAdmin() { -#if WINDOWS +#if LINUX + return false; +#else WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); return principal.IsInRole(WindowsBuiltInRole.Administrator); -#else - return false; #endif } } diff --git a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj index 12cd31443..1e02e6042 100644 --- a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj +++ b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj @@ -6,5 +6,8 @@ HitmanPatcher PeacockPatcher.Core + + $(DefineConstants);LINUX + CA1416 diff --git a/patcher/HitmanPatcher.Core/Settings.cs b/patcher/HitmanPatcher.Core/Settings.cs index eb7cabece..1153029bd 100644 --- a/patcher/HitmanPatcher.Core/Settings.cs +++ b/patcher/HitmanPatcher.Core/Settings.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.IO; - namespace HitmanPatcher { public class Settings @@ -30,20 +26,21 @@ public Settings() trayDomains = new List(); } - private static string GetSavePath() + public static string GetSavePath() { - if (!Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\PeacockProject")) +#if LINUX + return "peacock_patcher.conf"; +#else + string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + string folder = Path.Combine(appData, "PeacockProject"); + + if (!Directory.Exists(folder)) { - Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\PeacockProject"); + Directory.CreateDirectory(folder); } - string appData = Environment.GetFolderPath(Environment - .SpecialFolder - .ApplicationData); - - string folder = $@"{appData}\PeacockProject\"; - string config1 = folder + "peacock_patcher.conf"; - string config2 = folder + "peacock_patcher2.conf"; + string config1 = Path.Combine(folder, "peacock_patcher.conf"); + string config2 = Path.Combine(folder, "peacock_patcher2.conf"); if (File.Exists(config1)) { @@ -51,6 +48,7 @@ private static string GetSavePath() } return config2; +#endif } public void SaveToFile() @@ -59,7 +57,7 @@ public void SaveToFile() lines.Add(string.Format("CustomConfigDomain={0}", patchOptions.CustomConfigDomain)); lines.Add(string.Format("UseHttp={0}", patchOptions.UseHttp)); lines.Add(string.Format("DisableForceDynamicResources={0}", patchOptions.DisableForceOfflineOnFailedDynamicResources)); - lines.Add(string.Format("DarkModeEnabled={0}", darkModeEnabled)); + lines.Add(string.Format("DarkModeEnabled={0}", darkModeEnabled)); lines.Add(string.Format("startInTray={0}", startInTray)); lines.Add(string.Format("minToTray={0}", minimizeToTray)); @@ -100,9 +98,9 @@ public static Settings GetFromFile() case "DisableForceDynamicResources": result.patchOptions.DisableForceOfflineOnFailedDynamicResources = bool.Parse(linecontents[1]); break; - case "DarkModeEnabled": - result.darkModeEnabled = bool.Parse(linecontents[1]); - break; + case "DarkModeEnabled": + result.darkModeEnabled = bool.Parse(linecontents[1]); + break; case "startInTray": result.startInTray = bool.Parse(linecontents[1]); break; diff --git a/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj index 2eb34b1d8..c1a42826f 100644 --- a/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj +++ b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj @@ -20,6 +20,8 @@ patcher.ico 8.0.0.0 8.0.0.0 + + $(DefineConstants);LINUX diff --git a/patcher/build.bat b/patcher/build.bat new file mode 100644 index 000000000..bf16ad0ec --- /dev/null +++ b/patcher/build.bat @@ -0,0 +1,14 @@ +@echo off +rem Windows - CLI +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 + +rem Linux - CLI +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-Portable +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-x64 + +rem Windows - UI +dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable +dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 + +pause \ No newline at end of file From 83b09f8beb038d5f3101b33b01479d1f5b971d3a Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Wed, 14 Feb 2024 02:07:50 +0100 Subject: [PATCH 05/13] Updated to actions/setup-dotnet@v4 Fixed wrong filenames for Linux artifacts --- .github/workflows/patcher.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/patcher.yml b/.github/workflows/patcher.yml index 0ca44033c..ea965db4e 100644 --- a/.github/workflows/patcher.yml +++ b/.github/workflows/patcher.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v4 - name: Setup .NET Core - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ env.DOTNET_VERSION }} @@ -53,13 +53,13 @@ jobs: uses: actions/upload-artifact@v4 with: name: patcher-cli-linux-portable - path: patcher/Publish/Linux-Portable/PeacockPatcher.CLI.exe + path: patcher/Publish/Linux-Portable/PeacockPatcher.CLI - name: Upload patcher-cli-linux uses: actions/upload-artifact@v4 with: name: patcher-cli-linux - path: patcher/Publish/Linux-x64/PeacockPatcher.CLI.exe + path: patcher/Publish/Linux-x64/PeacockPatcher.CLI - name: Upload patcher-ui-windows-portable uses: actions/upload-artifact@v4 From a27f52156a63247f505807dfe99d0ec59babd3ac Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Sat, 17 Feb 2024 02:45:34 +0100 Subject: [PATCH 06/13] Added support for both .NET 8 and .NET 4.6.1 --- patcher/.gitignore | 1 + patcher/HitmanPatcher.CLI/Cli.cs | 13 +-- .../HitmanPatcher.CLI.csproj | 8 +- patcher/HitmanPatcher.CLI/Program.cs | 1 - patcher/HitmanPatcher.Core/Compositions.cs | 23 +---- .../HitmanPatcher.Core.csproj | 20 +++- patcher/HitmanPatcher.Core/Pinvoke.Windows.cs | 93 +++++++++++++++++++ patcher/HitmanPatcher.Core/Pinvoke.cs | 80 +--------------- patcher/HitmanPatcher.UI/App.config | 6 ++ .../HitmanPatcher.UI/HitmanPatcher.UI.csproj | 12 +-- patcher/HitmanPatcher.UI/Program.cs | 3 - patcher/HitmanPatcher.sln | 18 +++- patcher/HitmanPatcher.sln.DotSettings | 3 +- 13 files changed, 152 insertions(+), 129 deletions(-) create mode 100644 patcher/HitmanPatcher.Core/Pinvoke.Windows.cs create mode 100644 patcher/HitmanPatcher.UI/App.config diff --git a/patcher/.gitignore b/patcher/.gitignore index 3c8224636..3d855743a 100644 --- a/patcher/.gitignore +++ b/patcher/.gitignore @@ -2,6 +2,7 @@ bin obj /Publish +/Res /HitmanPatcher.sln.DotSettings.user /.idea/.idea.HitmanPatcher/.idea/riderMarkupCache.xml *.suo diff --git a/patcher/HitmanPatcher.CLI/Cli.cs b/patcher/HitmanPatcher.CLI/Cli.cs index 96ac6d9d8..f0ef001e2 100644 --- a/patcher/HitmanPatcher.CLI/Cli.cs +++ b/patcher/HitmanPatcher.CLI/Cli.cs @@ -1,10 +1,3 @@ -using System; -using System.Diagnostics.CodeAnalysis; -#if !DEBUG -using System.Linq; -using System.Runtime.InteropServices; -#endif - namespace HitmanPatcher { internal static class Cli @@ -13,17 +6,13 @@ internal static class Cli // in any mode outside debug (which is probably what it's being run in while in IDE), // we attach the console to the parent process - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool AttachConsole(int dwProcessId); - private const int ATTACH_PARENT_PROCESS = -1; internal static void EnsureConsole(string[] args) { if (args.Any(arg => arg.Contains("-"))) { - AttachConsole(ATTACH_PARENT_PROCESS); + Pinvoke.AttachConsole(ATTACH_PARENT_PROCESS); } } #endif diff --git a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj index f910a37a8..bca0f9767 100644 --- a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj +++ b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj @@ -7,7 +7,9 @@ HitmanPatcher PeacockPatcher.CLI - + + Debug;Release;Debug - Linux;Release - Linux + Peacock Patcher Peacock's HITMAN™ World of Assassination trilogy game patcher. The Peacock Project @@ -18,8 +20,10 @@ patcher.ico 8.0.0.0 8.0.0.0 + - $(DefineConstants);LINUX + + $(DefineConstants);LINUX diff --git a/patcher/HitmanPatcher.CLI/Program.cs b/patcher/HitmanPatcher.CLI/Program.cs index f25d6bac8..b8c6a641c 100644 --- a/patcher/HitmanPatcher.CLI/Program.cs +++ b/patcher/HitmanPatcher.CLI/Program.cs @@ -8,7 +8,6 @@ internal static class Program [STAThread] private static void Main(string[] args) { - Compositions.Initialize(); Compositions.Logger = new Cli.ConsoleLogger(); #if !DEBUG diff --git a/patcher/HitmanPatcher.Core/Compositions.cs b/patcher/HitmanPatcher.Core/Compositions.cs index 184e2d47c..6faafdc70 100644 --- a/patcher/HitmanPatcher.Core/Compositions.cs +++ b/patcher/HitmanPatcher.Core/Compositions.cs @@ -1,28 +1,9 @@ -#if !LINUX -using System.Security.Principal; -#endif - namespace HitmanPatcher { public static class Compositions { - public static bool HasAdmin; - public static ILoggingProvider Logger; + public static bool HasAdmin => Pinvoke.CheckForAdmin(); - public static void Initialize() - { - HasAdmin = CheckForAdmin(); - } - - private static bool CheckForAdmin() - { -#if LINUX - return false; -#else - WindowsIdentity identity = WindowsIdentity.GetCurrent(); - WindowsPrincipal principal = new WindowsPrincipal(identity); - return principal.IsInRole(WindowsBuiltInRole.Administrator); -#endif - } + public static ILoggingProvider Logger; } } diff --git a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj index 1e02e6042..204d074af 100644 --- a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj +++ b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj @@ -1,13 +1,27 @@ - net8.0 + netstandard2.0 enable disable HitmanPatcher PeacockPatcher.Core - $(DefineConstants);LINUX - CA1416 + Debug;Release;Debug - Linux;Release - Linux + + latest + + + + CA1416 + + + $(DefineConstants);LINUX + true + + + + + diff --git a/patcher/HitmanPatcher.Core/Pinvoke.Windows.cs b/patcher/HitmanPatcher.Core/Pinvoke.Windows.cs new file mode 100644 index 000000000..d9dfc1c62 --- /dev/null +++ b/patcher/HitmanPatcher.Core/Pinvoke.Windows.cs @@ -0,0 +1,93 @@ +#if !LINUX +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Security.Principal; + +namespace HitmanPatcher +{ + public static partial class Pinvoke + { + //Source: https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess + private enum PROCESSINFOCLASS + { + ProcessBasicInformation = 0, + ProcessDebugPort = 7, + ProcessWow64Information = 26, + ProcessImageFileName = 27, + ProcessBreakOnTermination = 29, + ProcessSubsystemInformation = 75 + } + + //Source: https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess + [StructLayout(LayoutKind.Sequential)] + private struct PROCESS_BASIC_INFORMATION + { + public IntPtr Reserved1; + public IntPtr PebBaseAddress; + public IntPtr Reserved2_0; + public IntPtr Reserved2_1; + public IntPtr UniqueProcessId; + public IntPtr Reserved3; + } + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AttachConsole(int dwProcessId); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenProcess(ProcessAccess dwDesiredAccess, bool bInheritHandle, int dwProcessId); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool CloseHandle(IntPtr hObject); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool WriteProcessMemory([In] IntPtr hProcess, [In] IntPtr address, [In, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, [In] UIntPtr size, [Out] out UIntPtr byteswritten); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool ReadProcessMemory([In] IntPtr hProcess, [In] IntPtr address, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] buffer, [In] UIntPtr size, [Out] out UIntPtr numberOfBytesRead); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool VirtualProtectEx([In] IntPtr hProcess, [In] IntPtr lpAddress, [In] UIntPtr dwSize, [In] MemProtection flNewProtect, [Out] out MemProtection lpflOldProtect); + + [DllImport("ntdll.dll")] + private static extern int NtQueryInformationProcess(IntPtr hProcess, PROCESSINFOCLASS processInformationClass, out PROCESS_BASIC_INFORMATION processInformation, uint processInformationLength, out uint returnLength); + + public static int GetProcessParentPid(Process process) + { + IntPtr hProcess = OpenProcess( + ProcessAccess.PROCESS_VM_READ + | ProcessAccess.PROCESS_QUERY_INFORMATION, + false, process.Id); + + if (hProcess == IntPtr.Zero) + { + throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to get a process handle."); + } + + PROCESS_BASIC_INFORMATION PEB = new PROCESS_BASIC_INFORMATION(); + + int result = NtQueryInformationProcess(hProcess, + PROCESSINFOCLASS.ProcessBasicInformation, out PEB, + (uint)Marshal.SizeOf(PEB), out _); + + CloseHandle(hProcess); + if (result != 0) + { + throw new Win32Exception(result, "(NTSTATUS)"); // not a w32 status code, but an NTSTATUS + } + + return PEB.Reserved3.ToInt32(); // undocumented, but should hold the parent PID + } + + public static bool CheckForAdmin() + { + using var identity = WindowsIdentity.GetCurrent(); + + var principal = new WindowsPrincipal(identity); + + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } + } +} +#endif \ No newline at end of file diff --git a/patcher/HitmanPatcher.Core/Pinvoke.cs b/patcher/HitmanPatcher.Core/Pinvoke.cs index 1daecabbc..74c8d70d7 100644 --- a/patcher/HitmanPatcher.Core/Pinvoke.cs +++ b/patcher/HitmanPatcher.Core/Pinvoke.cs @@ -1,11 +1,6 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Runtime.InteropServices; - namespace HitmanPatcher { - // from https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants + //Source: https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants [Flags] public enum MemProtection : uint { @@ -22,8 +17,7 @@ public enum MemProtection : uint PAGE_WRITECOMBINE = 0x00000400 } - // from https://docs.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights - // I've only listed the ones that I use + //Source: https://docs.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights [Flags] public enum ProcessAccess : uint { @@ -33,74 +27,8 @@ public enum ProcessAccess : uint PROCESS_VM_OPERATION = 0x0008 // Required to perform an operation on the address space of a process using VirtualProtectEx } - // from https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess - public enum PROCESSINFOCLASS + public static partial class Pinvoke { - ProcessBasicInformation = 0, - ProcessDebugPort = 7, - ProcessWow64Information = 26, - ProcessImageFileName = 27, - ProcessBreakOnTermination = 29, - ProcessSubsystemInformation = 75 - } - - // from https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess - [StructLayout(LayoutKind.Sequential)] - public struct PROCESS_BASIC_INFORMATION - { - public IntPtr Reserved1; - public IntPtr PebBaseAddress; - public IntPtr Reserved2_0; - public IntPtr Reserved2_1; - public IntPtr UniqueProcessId; - public IntPtr Reserved3; - } - - public static class Pinvoke - { - [DllImport("kernel32", SetLastError = true)] - public static extern IntPtr OpenProcess(ProcessAccess dwDesiredAccess, bool bInheritHandle, int dwProcessId); - - [DllImport("kernel32", SetLastError = true)] - public static extern bool CloseHandle(IntPtr hObject); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool WriteProcessMemory([In] IntPtr hProcess, [In] IntPtr address, [In, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, [In] UIntPtr size, [Out] out UIntPtr byteswritten); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool ReadProcessMemory([In] IntPtr hProcess, [In] IntPtr address, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] buffer, [In] UIntPtr size, [Out] out UIntPtr numberOfBytesRead); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool VirtualProtectEx([In] IntPtr hProcess, [In] IntPtr lpAddress, [In] UIntPtr dwSize, [In] MemProtection flNewProtect, [Out] out MemProtection lpflOldProtect); - - [DllImport("ntdll.dll")] - public static extern int NtQueryInformationProcess(IntPtr hProcess, PROCESSINFOCLASS processInformationClass, out PROCESS_BASIC_INFORMATION processInformation, uint processInformationLength, out uint returnLength); - - public static int GetProcessParentPid(Process process) - { - IntPtr hProcess = OpenProcess( - ProcessAccess.PROCESS_VM_READ - | ProcessAccess.PROCESS_QUERY_INFORMATION, - false, process.Id); - - if (hProcess == IntPtr.Zero) - { - throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to get a process handle."); - } - - PROCESS_BASIC_INFORMATION PEB = new PROCESS_BASIC_INFORMATION(); - - int result = NtQueryInformationProcess(hProcess, - PROCESSINFOCLASS.ProcessBasicInformation, out PEB, - (uint) Marshal.SizeOf(PEB), out _); - - CloseHandle(hProcess); - if (result != 0) - { - throw new Win32Exception(result, "(NTSTATUS)"); // not a w32 status code, but an NTSTATUS - } - - return PEB.Reserved3.ToInt32(); // undocumented, but should hold the parent PID - } + //Do nothing } } diff --git a/patcher/HitmanPatcher.UI/App.config b/patcher/HitmanPatcher.UI/App.config new file mode 100644 index 000000000..b22f7572e --- /dev/null +++ b/patcher/HitmanPatcher.UI/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj index c1a42826f..bb0ee0b88 100644 --- a/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj +++ b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj @@ -1,14 +1,15 @@ WinExe - net8.0-windows + net461;net8.0-windows enable disable HitmanPatcher - true PeacockPatcher.UI + Debug;Release + Peacock Patcher Peacock's HITMAN™ World of Assassination trilogy game patcher. The Peacock Project @@ -21,13 +22,10 @@ 8.0.0.0 8.0.0.0 - $(DefineConstants);LINUX + latest + True - - - - diff --git a/patcher/HitmanPatcher.UI/Program.cs b/patcher/HitmanPatcher.UI/Program.cs index 20879440b..343c3bef3 100644 --- a/patcher/HitmanPatcher.UI/Program.cs +++ b/patcher/HitmanPatcher.UI/Program.cs @@ -10,9 +10,6 @@ private static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); - Application.SetHighDpiMode(HighDpiMode.SystemAware); - - Compositions.Initialize(); var mainForm = MainForm.GetInstance(); diff --git a/patcher/HitmanPatcher.sln b/patcher/HitmanPatcher.sln index f21da2075..08c4dbd59 100644 --- a/patcher/HitmanPatcher.sln +++ b/patcher/HitmanPatcher.sln @@ -3,28 +3,40 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.8.34316.72 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitmanPatcher.Core", "HitmanPatcher.Core\HitmanPatcher.Core.csproj", "{70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HitmanPatcher.Core", "HitmanPatcher.Core\HitmanPatcher.Core.csproj", "{70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitmanPatcher.CLI", "HitmanPatcher.CLI\HitmanPatcher.CLI.csproj", "{799814F1-919B-4BCA-9348-4F7F5F429CB9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HitmanPatcher.CLI", "HitmanPatcher.CLI\HitmanPatcher.CLI.csproj", "{799814F1-919B-4BCA-9348-4F7F5F429CB9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitmanPatcher.UI", "HitmanPatcher.UI\HitmanPatcher.UI.csproj", "{50B900C8-B244-4AAA-9130-5C0A6093B22D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HitmanPatcher.UI", "HitmanPatcher.UI\HitmanPatcher.UI.csproj", "{50B900C8-B244-4AAA-9130-5C0A6093B22D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug - Linux|Any CPU = Debug - Linux|Any CPU Debug|Any CPU = Debug|Any CPU + Release - Linux|Any CPU = Release - Linux|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}.Debug - Linux|Any CPU.ActiveCfg = Debug - Linux|Any CPU + {70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}.Debug - Linux|Any CPU.Build.0 = Debug - Linux|Any CPU {70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}.Release - Linux|Any CPU.ActiveCfg = Release - Linux|Any CPU + {70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}.Release - Linux|Any CPU.Build.0 = Release - Linux|Any CPU {70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}.Release|Any CPU.ActiveCfg = Release|Any CPU {70EA1386-6A9D-47C2-ADE8-2F32CDD9E946}.Release|Any CPU.Build.0 = Release|Any CPU + {799814F1-919B-4BCA-9348-4F7F5F429CB9}.Debug - Linux|Any CPU.ActiveCfg = Debug - Linux|Any CPU + {799814F1-919B-4BCA-9348-4F7F5F429CB9}.Debug - Linux|Any CPU.Build.0 = Debug - Linux|Any CPU {799814F1-919B-4BCA-9348-4F7F5F429CB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {799814F1-919B-4BCA-9348-4F7F5F429CB9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {799814F1-919B-4BCA-9348-4F7F5F429CB9}.Release - Linux|Any CPU.ActiveCfg = Release - Linux|Any CPU + {799814F1-919B-4BCA-9348-4F7F5F429CB9}.Release - Linux|Any CPU.Build.0 = Release - Linux|Any CPU {799814F1-919B-4BCA-9348-4F7F5F429CB9}.Release|Any CPU.ActiveCfg = Release|Any CPU {799814F1-919B-4BCA-9348-4F7F5F429CB9}.Release|Any CPU.Build.0 = Release|Any CPU + {50B900C8-B244-4AAA-9130-5C0A6093B22D}.Debug - Linux|Any CPU.ActiveCfg = Debug|Any CPU {50B900C8-B244-4AAA-9130-5C0A6093B22D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {50B900C8-B244-4AAA-9130-5C0A6093B22D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50B900C8-B244-4AAA-9130-5C0A6093B22D}.Release - Linux|Any CPU.ActiveCfg = Release|Any CPU {50B900C8-B244-4AAA-9130-5C0A6093B22D}.Release|Any CPU.ActiveCfg = Release|Any CPU {50B900C8-B244-4AAA-9130-5C0A6093B22D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection diff --git a/patcher/HitmanPatcher.sln.DotSettings b/patcher/HitmanPatcher.sln.DotSettings index 80734dfb0..3d4aa7d86 100644 --- a/patcher/HitmanPatcher.sln.DotSettings +++ b/patcher/HitmanPatcher.sln.DotSettings @@ -11,4 +11,5 @@ DO_NOT_SHOW True True - True \ No newline at end of file + True + True \ No newline at end of file From 4c625a941c16d8aae1d6b2cec6ccafde57d69d59 Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Sat, 17 Feb 2024 04:16:15 +0100 Subject: [PATCH 07/13] Added Pinvoke abstractions for Linux --- .../HitmanPatcher.CLI.csproj | 7 +- patcher/HitmanPatcher.Core/AOBScanner.cs | 6 +- patcher/HitmanPatcher.Core/Compositions.cs | 5 +- .../HitmanPatcher.Core.csproj | 14 +- patcher/HitmanPatcher.Core/MemoryPatcher.cs | 50 ++-- patcher/HitmanPatcher.Core/Pinvoke.Linux.cs | 255 ++++++++++++++++++ patcher/HitmanPatcher.Core/Pinvoke.Windows.cs | 22 +- patcher/HitmanPatcher.Core/Pinvoke.cs | 11 +- patcher/HitmanPatcher.sln.DotSettings | 3 +- 9 files changed, 328 insertions(+), 45 deletions(-) create mode 100644 patcher/HitmanPatcher.Core/Pinvoke.Linux.cs diff --git a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj index bca0f9767..1c82fe312 100644 --- a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj +++ b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj @@ -22,8 +22,13 @@ 8.0.0.0 - + + $(DefineConstants);LINUX;DEBUG + + + $(DefineConstants);LINUX + True diff --git a/patcher/HitmanPatcher.Core/AOBScanner.cs b/patcher/HitmanPatcher.Core/AOBScanner.cs index 1c2f166b3..97b5ed160 100644 --- a/patcher/HitmanPatcher.Core/AOBScanner.cs +++ b/patcher/HitmanPatcher.Core/AOBScanner.cs @@ -4,13 +4,13 @@ namespace HitmanPatcher { internal static class AOBScanner { - public static bool TryGetHitmanVersionByScanning(Process process, + public static bool TryGetHitmanVersionByScanning(ProcessMetadata processMetadata, IntPtr hProcess, out HitmanVersion result) { Stopwatch bench = Stopwatch.StartNew(); - IntPtr baseAddress = process.MainModule.BaseAddress; - byte[] exeData = new byte[process.MainModule.ModuleMemorySize]; + IntPtr baseAddress = processMetadata.BaseAddress; + byte[] exeData = new byte[processMetadata.ModuleMemorySize]; Pinvoke.ReadProcessMemory(hProcess, baseAddress, exeData, (UIntPtr) exeData.Length, out _); // fuck it, just read the whole thing diff --git a/patcher/HitmanPatcher.Core/Compositions.cs b/patcher/HitmanPatcher.Core/Compositions.cs index 6faafdc70..e6e1fc715 100644 --- a/patcher/HitmanPatcher.Core/Compositions.cs +++ b/patcher/HitmanPatcher.Core/Compositions.cs @@ -2,8 +2,9 @@ namespace HitmanPatcher { public static class Compositions { - public static bool HasAdmin => Pinvoke.CheckForAdmin(); + //NOTE: This will only have to be determined once + public static bool HasAdmin { get; } = Pinvoke.CheckForAdmin(); - public static ILoggingProvider Logger; + public static ILoggingProvider Logger { get; set; } } } diff --git a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj index 204d074af..bfd9ce917 100644 --- a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj +++ b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj @@ -1,6 +1,6 @@ - netstandard2.0 + netstandard2.0;net8.0 enable disable @@ -12,16 +12,22 @@ latest - + CA1416 - + + $(DefineConstants);LINUX;DEBUG + true + + + $(DefineConstants);LINUX true + True - + diff --git a/patcher/HitmanPatcher.Core/MemoryPatcher.cs b/patcher/HitmanPatcher.Core/MemoryPatcher.cs index ffb66fa38..f34e8840c 100644 --- a/patcher/HitmanPatcher.Core/MemoryPatcher.cs +++ b/patcher/HitmanPatcher.Core/MemoryPatcher.cs @@ -35,7 +35,7 @@ private static List GetProcessesByName(params string[] names) { try { - if (names.Contains(p.ProcessName, StringComparer.OrdinalIgnoreCase)) + if (names.Contains(Path.GetFileNameWithoutExtension(p.ProcessName), StringComparer.OrdinalIgnoreCase)) { result.Add(p); } @@ -124,35 +124,31 @@ public static bool PatchAllProcesses(ILoggingProvider logger, Options patchOptio public static bool Patch(Process process, Options patchOptions) { - IntPtr hProcess = Pinvoke.OpenProcess( + var processMetadata = Pinvoke.GetProcessMetadata(process); + + if (processMetadata.BaseAddress == IntPtr.Zero || processMetadata.ModuleMemorySize == 0) + { + return false; // process has no main module (not initialized yet?), try again next timer tick. + } + + IntPtr hProcess = Pinvoke.OpenProcess( ProcessAccess.PROCESS_VM_READ | ProcessAccess.PROCESS_VM_WRITE | ProcessAccess.PROCESS_VM_OPERATION, - false, process.Id); + false, processMetadata.PID); if (hProcess == IntPtr.Zero) { - throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to get a process handle."); + throw new Win32Exception(Pinvoke.LastError, "Failed to get a process handle."); } try { - IntPtr b = IntPtr.Zero; - try - { - ProcessModule mainModule = process.MainModule; - b = mainModule.BaseAddress; - } - catch (NullReferenceException) - { - return false; // process has no main module (not initialized yet?), try again next timer tick. - } - - uint timestamp = getTimestamp(hProcess, b); + uint timestamp = getTimestamp(hProcess, processMetadata.BaseAddress); HitmanVersion v = HitmanVersion.GetVersion(timestamp); if (v == HitmanVersion.NotFound) { - if (AOBScanner.TryGetHitmanVersionByScanning(process, hProcess, out v)) + if (AOBScanner.TryGetHitmanVersionByScanning(processMetadata, hProcess, out v)) { // add it to the db so subsequent patches don't need searching again HitmanVersion.AddVersion(timestamp.ToString("X8"), timestamp, v); @@ -167,7 +163,7 @@ public static bool Patch(Process process, Options patchOptions) byte[] newurl = Encoding.ASCII.GetBytes(patchOptions.CustomConfigDomain).Concat(new byte[] { 0x00 }).ToArray(); List patches = new List(); - if (!IsReadyForPatching(hProcess, b, v)) + if (!IsReadyForPatching(hProcess, processMetadata.BaseAddress, v)) { // Online_ConfigDomain variable is not initialized yet, try again in 1 second. Pinvoke.CloseHandle(hProcess); @@ -218,24 +214,24 @@ public static bool Patch(Process process, Options patchOptions) throw new Exception("This shouldn't be able to happen."); } - if (!Pinvoke.VirtualProtectEx(hProcess, b + patch.offset, (UIntPtr)dataToWrite.Length, + if (!Pinvoke.VirtualProtectEx(hProcess, processMetadata.BaseAddress + patch.offset, (UIntPtr)dataToWrite.Length, newmemprotection, out oldprotectflags)) { - throw new Win32Exception(Marshal.GetLastWin32Error(), string.Format("error at {0} for offset {1:X}", "vpe1", patch.offset)); + throw new Win32Exception(Pinvoke.LastError, string.Format("error at {0} for offset {1:X}", "vpe1", patch.offset)); } - if (!Pinvoke.WriteProcessMemory(hProcess, b + patch.offset, dataToWrite, (UIntPtr)dataToWrite.Length, out byteswritten)) + if (!Pinvoke.WriteProcessMemory(hProcess, processMetadata.BaseAddress + patch.offset, dataToWrite, (UIntPtr)dataToWrite.Length, out byteswritten)) { - throw new Win32Exception(Marshal.GetLastWin32Error(), string.Format("error at {0} for offset {1:X}" + throw new Win32Exception(Pinvoke.LastError, string.Format("error at {0} for offset {1:X}" + "\nBytes written: {2}", "wpm", patch.offset, byteswritten)); } MemProtection protectionToRestore = oldprotectflags; - if (!Pinvoke.VirtualProtectEx(hProcess, b + patch.offset, (UIntPtr)dataToWrite.Length, + if (!Pinvoke.VirtualProtectEx(hProcess, processMetadata.BaseAddress + patch.offset, (UIntPtr)dataToWrite.Length, protectionToRestore, out oldprotectflags)) { - throw new Win32Exception(Marshal.GetLastWin32Error(), string.Format("error at {0} for offset {1:X}", "vpe2", patch.offset)); + throw new Win32Exception(Pinvoke.LastError, string.Format("error at {0} for offset {1:X}", "vpe2", patch.offset)); } } } @@ -259,15 +255,15 @@ private static bool IsReadyForPatching(IntPtr hProcess, IntPtr baseAddress, Hitm MemProtection oldprotectflags; if (!Pinvoke.VirtualProtectEx(hProcess, baseAddress + p.offset, (UIntPtr)1, newmemprotection, out oldprotectflags)) { - throw new Win32Exception(Marshal.GetLastWin32Error(), string.Format("error at vpe1Check for offset {0:X}", p.offset)); + throw new Win32Exception(Pinvoke.LastError, string.Format("error at vpe1Check for offset {0:X}", p.offset)); } if (!Pinvoke.ReadProcessMemory(hProcess, baseAddress + p.offset, buffer, (UIntPtr)1, out bytesread)) { - throw new Win32Exception(Marshal.GetLastWin32Error(), string.Format("error at rpmCheck for offset {0:X}", p.offset)); + throw new Win32Exception(Pinvoke.LastError, string.Format("error at rpmCheck for offset {0:X}", p.offset)); } if (!Pinvoke.VirtualProtectEx(hProcess, baseAddress + p.offset, (UIntPtr)1, oldprotectflags, out oldprotectflags)) { - throw new Win32Exception(Marshal.GetLastWin32Error(), string.Format("error at vpe2Check for offset {0:X}", p.offset)); + throw new Win32Exception(Pinvoke.LastError, string.Format("error at vpe2Check for offset {0:X}", p.offset)); } ready &= buffer[0] != 0; } diff --git a/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs b/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs new file mode 100644 index 000000000..2a47dd263 --- /dev/null +++ b/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs @@ -0,0 +1,255 @@ +#if LINUX +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace HitmanPatcher; + +public static partial class Pinvoke +{ + [StructLayout(LayoutKind.Sequential)] + private unsafe struct iovec + { + public void* iov_base; + public int iov_len; + } + + private enum PtraceRequest + { + //PTRACE_PEEKDATA = 2, + PTRACE_POKEDATA = 5, + PTRACE_ATTACH = 16, + PTRACE_DETACH = 17 + } + + [DllImport("libc", SetLastError = true)] + private static extern unsafe long ptrace(PtraceRequest request, int pid, void* address, void* data); + + [DllImport("libc", SetLastError = true)] + private static extern unsafe int process_vm_readv(int pid, iovec* local_iov, ulong liovcnt, iovec* remote_iov, ulong riovcnt, ulong flags); + + public static ProcessMetadata GetProcessMetadata(Process process) + { + var lines = File.ReadAllLines($"/proc/{process.Id}/maps"); + + var findProcess = Path.GetFileNameWithoutExtension(process.ProcessName).ToLower(); + + var foundLines = lines.Where(x => x.ToLower().Contains(findProcess)).ToList(); + + long baseAddressStart = long.MaxValue; + long baseAddressEnd = 0; + + foreach (var line in foundLines) + { + var splittedLine = line.Split(' '); + var addressStartEnd = splittedLine[0].Split('-'); + + Compositions.Logger.log(addressStartEnd[0]); + Compositions.Logger.log(addressStartEnd[1]); + + baseAddressStart = Math.Min(baseAddressStart, Convert.ToInt64(addressStartEnd[0], 16)); + baseAddressEnd = Math.Max(baseAddressEnd, Convert.ToInt64(addressStartEnd[1], 16)); + } + + IntPtr baseAddress = new IntPtr(baseAddressStart); + var moduleMemorySize = baseAddressEnd - baseAddressStart; + + return new ProcessMetadata + { + PID = process.Id, + BaseAddress = baseAddress, + ModuleMemorySize = moduleMemorySize + }; + } + + /** + * Attach to the given process using ptrace, return the PID as the handle. + */ + public static unsafe IntPtr OpenProcess(ProcessAccess dwDesiredAccess, bool bInheritHandle, int dwProcessId) + { + Compositions.Logger.log("Open: " + dwProcessId); + + var result = ptrace(PtraceRequest.PTRACE_ATTACH, dwProcessId, null, null); + + if (result == -1) + { + Compositions.Logger.log($"- Attach error: {LastError}"); + + return IntPtr.Zero; + } + + Compositions.Logger.log("- Attach: " + result); + + return new IntPtr(dwProcessId); + } + + /** + * Retrieve the PID from the handle, and detach from the process using ptrace. + */ + public static unsafe void CloseHandle(IntPtr hProcess) + { + var pid = hProcess.ToInt32(); + + Compositions.Logger.log($"Close: {pid}"); + + var result = ptrace(PtraceRequest.PTRACE_DETACH, pid, null, null); + + if (result == -1) + { + Compositions.Logger.log($"- Detach error: {LastError}"); + } + else + { + Compositions.Logger.log($"- Detach: {result}"); + } + } + + /** + * Since process_vm_writev is too respectful of permissions, we have to use ptrace to write to memory. + * + * ptrace writes data in blocks of 8 bytes (long), so if a given buffer is non-divisible by 8, we have to pad it with data read from memory to prevent corruption. + */ + public static unsafe bool WriteProcessMemory(IntPtr hProcess, IntPtr address, byte[] buffer, UIntPtr size, out UIntPtr numberOfBytesWritten) + { + var pid = hProcess.ToInt32(); + var sizeAsUInt = (int)size.ToUInt32(); + + Compositions.Logger.log($"Write: {pid} {sizeAsUInt}"); + + var desiredBufferSize = (int)Math.Ceiling(sizeAsUInt / 8.0) * 8; + + byte[] paddedBuffer; + + if (sizeAsUInt < desiredBufferSize) + { + Compositions.Logger.log($"- Padding buffer to {desiredBufferSize}"); + + paddedBuffer = new byte[desiredBufferSize]; + ReadProcessMemory(hProcess, address, paddedBuffer, new UIntPtr((uint)desiredBufferSize), out _); + + for (var i = 0; i < sizeAsUInt; i++) + { + paddedBuffer[i] = buffer[i]; + } + } + else + { + paddedBuffer = buffer; + } + + Compositions.Logger.log($"- Padded: {BitConverter.ToString(paddedBuffer)}"); + + var debugBuffer = new byte[paddedBuffer.Length]; + ReadProcessMemory(hProcess, address, debugBuffer, new UIntPtr((uint)debugBuffer.Length), out _); + Compositions.Logger.log($"- Debug before: {BitConverter.ToString(debugBuffer)}"); + + for (int i = 0; i < desiredBufferSize; i += 8) + { + var value = BitConverter.ToInt64(paddedBuffer, i); + + var result = ptrace(PtraceRequest.PTRACE_POKEDATA, pid, (address + i).ToPointer(), (void*)value); + + if (result == -1) + { + Compositions.Logger.log($"- Poke error: {LastError}"); + + numberOfBytesWritten = UIntPtr.Zero; + + return false; + } + + Compositions.Logger.log($"- Poke: {result}"); + } + + debugBuffer = new byte[paddedBuffer.Length]; + ReadProcessMemory(hProcess, address, debugBuffer, new UIntPtr((uint)debugBuffer.Length), out _); + Compositions.Logger.log("- Debug after: " + BitConverter.ToString(debugBuffer)); + + numberOfBytesWritten = size; + + return true; + } + + /** + * Memory can always be read regardless of permissions, so we can use process_vm_readv. + * + * To prevent stack overflows, memory is read in chunks of 1MB. + */ + public static unsafe bool ReadProcessMemory(IntPtr hProcess, IntPtr address, byte[] buffer, UIntPtr size, out UIntPtr numberOfBytesRead) + { + var pid = hProcess.ToInt32(); + var sizeAsUInt = (int)size.ToUInt32(); + + Compositions.Logger.log($"Read: {pid} {sizeAsUInt}"); + + var chunkSize = Math.Min(sizeAsUInt, 1_000_000); + + var ptr = stackalloc byte[chunkSize]; + + for (var i = 0; i < sizeAsUInt; i += chunkSize) + { + if (sizeAsUInt - i < chunkSize) + { + chunkSize = sizeAsUInt - i; + } + + Compositions.Logger.log($"- Chunk: {i}/{sizeAsUInt} => {chunkSize}"); + + var localIo = new iovec + { + iov_base = ptr, + iov_len = chunkSize + }; + + var remoteIo = new iovec + { + iov_base = (address + i).ToPointer(), + iov_len = chunkSize + }; + + var res = process_vm_readv(pid, &localIo, 1, &remoteIo, 1, 0); + + if (res == -1) + { + numberOfBytesRead = UIntPtr.Zero; + + return false; + } + + Marshal.Copy((IntPtr)ptr, buffer, i, chunkSize); + } + + numberOfBytesRead = new UIntPtr((uint)sizeAsUInt); + + return true; + } + + /** + * Technically ptrace attach/detach would be the closest equivalent, but from a performance perspective, we only do that once. + */ + public static bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, MemProtection flNewProtect, out MemProtection lpflOldProtect) + { + lpflOldProtect = 0; + + return true; + } + + public static void AttachConsole(int attachParentProcess) + { + //Do nothing + } + + public static bool CheckForAdmin() + { + //TODO: Check if SUDO_USER is set + + return false; + } + + public static int GetProcessParentPid(Process process) + { + //TODO: Retrieve "PPid" from "/proc/pid/status" + + return process.Id; + } +} +#endif \ No newline at end of file diff --git a/patcher/HitmanPatcher.Core/Pinvoke.Windows.cs b/patcher/HitmanPatcher.Core/Pinvoke.Windows.cs index d9dfc1c62..497668349 100644 --- a/patcher/HitmanPatcher.Core/Pinvoke.Windows.cs +++ b/patcher/HitmanPatcher.Core/Pinvoke.Windows.cs @@ -53,6 +53,15 @@ private struct PROCESS_BASIC_INFORMATION [DllImport("ntdll.dll")] private static extern int NtQueryInformationProcess(IntPtr hProcess, PROCESSINFOCLASS processInformationClass, out PROCESS_BASIC_INFORMATION processInformation, uint processInformationLength, out uint returnLength); + public static bool CheckForAdmin() + { + using var identity = WindowsIdentity.GetCurrent(); + + var principal = new WindowsPrincipal(identity); + + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } + public static int GetProcessParentPid(Process process) { IntPtr hProcess = OpenProcess( @@ -80,13 +89,14 @@ public static int GetProcessParentPid(Process process) return PEB.Reserved3.ToInt32(); // undocumented, but should hold the parent PID } - public static bool CheckForAdmin() + public static ProcessMetadata GetProcessMetadata(Process process) { - using var identity = WindowsIdentity.GetCurrent(); - - var principal = new WindowsPrincipal(identity); - - return principal.IsInRole(WindowsBuiltInRole.Administrator); + return new ProcessMetadata + { + PID = process.Id, + BaseAddress = process.MainModule?.BaseAddress ?? IntPtr.Zero, + ModuleMemorySize = process.MainModule?.ModuleMemorySize ?? 0 + }; } } } diff --git a/patcher/HitmanPatcher.Core/Pinvoke.cs b/patcher/HitmanPatcher.Core/Pinvoke.cs index 74c8d70d7..7001b2051 100644 --- a/patcher/HitmanPatcher.Core/Pinvoke.cs +++ b/patcher/HitmanPatcher.Core/Pinvoke.cs @@ -1,5 +1,14 @@ +using System.Runtime.InteropServices; + namespace HitmanPatcher { + public class ProcessMetadata + { + public int PID { get; set; } + public IntPtr BaseAddress { get; set; } + public long ModuleMemorySize { get; set; } + } + //Source: https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants [Flags] public enum MemProtection : uint @@ -29,6 +38,6 @@ public enum ProcessAccess : uint public static partial class Pinvoke { - //Do nothing + public static int LastError => Marshal.GetLastWin32Error(); } } diff --git a/patcher/HitmanPatcher.sln.DotSettings b/patcher/HitmanPatcher.sln.DotSettings index 3d4aa7d86..9c64d6593 100644 --- a/patcher/HitmanPatcher.sln.DotSettings +++ b/patcher/HitmanPatcher.sln.DotSettings @@ -12,4 +12,5 @@ True True True - True \ No newline at end of file + True + True \ No newline at end of file From 03d415f163deb5230c431f00fbf85500eb3a039a Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Sat, 17 Feb 2024 05:02:15 +0100 Subject: [PATCH 08/13] Hotfixes after testrun on Steam Deck --- patcher/HitmanPatcher.Core/Pinvoke.Linux.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs b/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs index 2a47dd263..87d4167f5 100644 --- a/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs +++ b/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs @@ -7,7 +7,9 @@ namespace HitmanPatcher; public static partial class Pinvoke { [StructLayout(LayoutKind.Sequential)] +#pragma warning disable CS8981 private unsafe struct iovec +#pragma warning restore CS8981 { public void* iov_base; public int iov_len; @@ -31,7 +33,7 @@ public static ProcessMetadata GetProcessMetadata(Process process) { var lines = File.ReadAllLines($"/proc/{process.Id}/maps"); - var findProcess = Path.GetFileNameWithoutExtension(process.ProcessName).ToLower(); + var findProcess = process.ProcessName.ToLower(); var foundLines = lines.Where(x => x.ToLower().Contains(findProcess)).ToList(); @@ -249,7 +251,7 @@ public static int GetProcessParentPid(Process process) { //TODO: Retrieve "PPid" from "/proc/pid/status" - return process.Id; + return -1; } } #endif \ No newline at end of file From 1d6dbe0a0671c0774bb72d1add218f7f19540b91 Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Sun, 18 Feb 2024 14:09:52 +0100 Subject: [PATCH 09/13] Added cross-compilation for .NET Framework 4.6 and .NET 8 Replaced embedded resources with custom implementation for proper cross-compilation support --- .github/workflows/patcher.yml | 45 +++--- .../HitmanPatcher.CLI.csproj | 10 ++ patcher/HitmanPatcher.CLI/ILRepack.targets | 16 +++ .../HitmanPatcher.Core.csproj | 7 +- patcher/HitmanPatcher.UI/App.config | 2 +- .../HitmanPatcher.UI/HitmanPatcher.UI.csproj | 38 +++-- patcher/HitmanPatcher.UI/ILRepack.targets | 16 +++ patcher/HitmanPatcher.UI/MainForm.Designer.cs | 8 +- patcher/HitmanPatcher.UI/MainForm.cs | 6 +- patcher/HitmanPatcher.UI/Program.cs | 4 + .../Properties/Resources.Designer.cs | 93 ------------- .../Properties/Resources.resx | 130 ------------------ patcher/HitmanPatcher.UI/Resources.cs | 31 +++++ patcher/build.bat | 16 ++- 14 files changed, 143 insertions(+), 279 deletions(-) create mode 100644 patcher/HitmanPatcher.CLI/ILRepack.targets create mode 100644 patcher/HitmanPatcher.UI/ILRepack.targets delete mode 100644 patcher/HitmanPatcher.UI/Properties/Resources.Designer.cs delete mode 100644 patcher/HitmanPatcher.UI/Properties/Resources.resx create mode 100644 patcher/HitmanPatcher.UI/Resources.cs diff --git a/.github/workflows/patcher.yml b/.github/workflows/patcher.yml index ea965db4e..a7c690d6a 100644 --- a/.github/workflows/patcher.yml +++ b/.github/workflows/patcher.yml @@ -30,18 +30,20 @@ jobs: export DOTNET_NOLOGO=true export DOTNET_CLI_TELEMETRY_OPTOUT=true cd patcher - dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable - dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 - dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-Portable - dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-x64 - dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable - dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 + dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable + dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -f net8.0 -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 + dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-Portable + dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -f net8.0 -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-x64 + dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -f net8.0-windows -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable + dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -f net8.0-windows -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 + dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Legacy -p:IsLegacy=True + dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Legacy -p:IsLegacy=True - - name: Upload patcher-cli-windows-portable + - name: Upload patcher-windows-portable uses: actions/upload-artifact@v4 with: - name: patcher-cli-windows-portable - path: patcher/Publish/Windows-Portable/PeacockPatcher.CLI.exe + name: patcher-windows-portable + path: patcher/Publish/Windows-Portable - name: Upload patcher-cli-windows uses: actions/upload-artifact@v4 @@ -49,27 +51,26 @@ jobs: name: patcher-cli-windows path: patcher/Publish/Windows-x64/PeacockPatcher.CLI.exe - - name: Upload patcher-cli-linux-portable + - name: Upload patcher-ui-windows uses: actions/upload-artifact@v4 with: - name: patcher-cli-linux-portable - path: patcher/Publish/Linux-Portable/PeacockPatcher.CLI + name: patcher-ui-windows + path: patcher/Publish/Windows-x64/PeacockPatcher.UI.exe - - name: Upload patcher-cli-linux + - name: Upload patcher-linux-portable uses: actions/upload-artifact@v4 with: - name: patcher-cli-linux - path: patcher/Publish/Linux-x64/PeacockPatcher.CLI + name: patcher-linux-portable + path: patcher/Publish/Linux-Portable - - name: Upload patcher-ui-windows-portable + - name: Upload patcher-linux uses: actions/upload-artifact@v4 with: - name: patcher-ui-windows-portable - path: patcher/Publish/Windows-Portable/PeacockPatcher.UI.exe + name: patcher-linux + path: patcher/Publish/Linux-x64 - - name: Upload patcher-ui-windows + - name: Upload patcher-windows-legacy uses: actions/upload-artifact@v4 with: - name: patcher-ui-windows - path: patcher/Publish/Windows-x64/PeacockPatcher.UI.exe - + name: patcher-windows-legacy + path: patcher/Publish/Windows-Legacy/ILRepack diff --git a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj index 1c82fe312..84a0ec1ef 100644 --- a/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj +++ b/patcher/HitmanPatcher.CLI/HitmanPatcher.CLI.csproj @@ -2,6 +2,7 @@ Exe net8.0 + net46 enable disable @@ -20,6 +21,8 @@ patcher.ico 8.0.0.0 8.0.0.0 + + latest @@ -31,6 +34,13 @@ True + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/patcher/HitmanPatcher.CLI/ILRepack.targets b/patcher/HitmanPatcher.CLI/ILRepack.targets new file mode 100644 index 000000000..5ffd50f69 --- /dev/null +++ b/patcher/HitmanPatcher.CLI/ILRepack.targets @@ -0,0 +1,16 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj index bfd9ce917..414ddfb3b 100644 --- a/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj +++ b/patcher/HitmanPatcher.Core/HitmanPatcher.Core.csproj @@ -1,6 +1,7 @@ - netstandard2.0;net8.0 + net8.0 + net46 enable disable @@ -26,8 +27,4 @@ true True - - - - diff --git a/patcher/HitmanPatcher.UI/App.config b/patcher/HitmanPatcher.UI/App.config index b22f7572e..6abd8f17b 100644 --- a/patcher/HitmanPatcher.UI/App.config +++ b/patcher/HitmanPatcher.UI/App.config @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj index bb0ee0b88..627e872f4 100644 --- a/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj +++ b/patcher/HitmanPatcher.UI/HitmanPatcher.UI.csproj @@ -1,7 +1,8 @@ WinExe - net461;net8.0-windows + net8.0-windows + net46 enable disable @@ -22,36 +23,43 @@ 8.0.0.0 8.0.0.0 + true + $(DefineConstants);LEGACY latest - True + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + Form Form - - True - True - Resources.resx - Form - - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - diff --git a/patcher/HitmanPatcher.UI/ILRepack.targets b/patcher/HitmanPatcher.UI/ILRepack.targets new file mode 100644 index 000000000..19e81fcc2 --- /dev/null +++ b/patcher/HitmanPatcher.UI/ILRepack.targets @@ -0,0 +1,16 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/patcher/HitmanPatcher.UI/MainForm.Designer.cs b/patcher/HitmanPatcher.UI/MainForm.Designer.cs index cbc6bae4d..026a930e4 100644 --- a/patcher/HitmanPatcher.UI/MainForm.Designer.cs +++ b/patcher/HitmanPatcher.UI/MainForm.Designer.cs @@ -209,8 +209,8 @@ private void InitializeComponent() this.novikovPictureBox.AccessibleDescription = "Icon showing the patcher status."; this.novikovPictureBox.AccessibleName = "Status icon"; this.novikovPictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.novikovPictureBox.Image = global::HitmanPatcher.Properties.Resources.Novikov_standard; - this.novikovPictureBox.InitialImage = ((System.Drawing.Image)(resources.GetObject("novikovPictureBox.InitialImage"))); + this.novikovPictureBox.Image = Resources.Novikov_standard; + this.novikovPictureBox.InitialImage = Resources.Novikov_standard; this.novikovPictureBox.Location = new System.Drawing.Point(313, 44); this.novikovPictureBox.Margin = new System.Windows.Forms.Padding(4); this.novikovPictureBox.Name = "novikovPictureBox"; @@ -222,7 +222,7 @@ private void InitializeComponent() // trayIcon // this.trayIcon.ContextMenuStrip = this.trayMenu; - this.trayIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("trayIcon.Icon"))); + this.trayIcon.Icon = Resources.Icon; this.trayIcon.Text = "Peacock Patcher"; this.trayIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.menuItemOpen_Click); // @@ -284,7 +284,7 @@ private void InitializeComponent() this.Controls.Add(this.logLabel); this.Controls.Add(this.logListView); this.Controls.Add(this.serverAddressLabel); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Icon = Resources.Icon; this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.MaximizeBox = false; this.MinimumSize = new System.Drawing.Size(423, 238); diff --git a/patcher/HitmanPatcher.UI/MainForm.cs b/patcher/HitmanPatcher.UI/MainForm.cs index b229e05fb..a16b8549e 100644 --- a/patcher/HitmanPatcher.UI/MainForm.cs +++ b/patcher/HitmanPatcher.UI/MainForm.cs @@ -207,15 +207,15 @@ private void SetStatusImage(int status) { if (status == 0) { - novikovPictureBox.Image = Properties.Resources.Novikov_standard; + novikovPictureBox.Image = Resources.Novikov_standard; } else if (status > 0) { - novikovPictureBox.Image = Properties.Resources.Novikov_success; + novikovPictureBox.Image = Resources.Novikov_success; } else { - novikovPictureBox.Image = Properties.Resources.Novikov_error; + novikovPictureBox.Image = Resources.Novikov_error; } } diff --git a/patcher/HitmanPatcher.UI/Program.cs b/patcher/HitmanPatcher.UI/Program.cs index 343c3bef3..98b04f32f 100644 --- a/patcher/HitmanPatcher.UI/Program.cs +++ b/patcher/HitmanPatcher.UI/Program.cs @@ -11,6 +11,10 @@ private static void Main(string[] args) Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); +#if !LEGACY + Application.SetHighDpiMode(HighDpiMode.SystemAware); +#endif + var mainForm = MainForm.GetInstance(); Compositions.Logger = mainForm; diff --git a/patcher/HitmanPatcher.UI/Properties/Resources.Designer.cs b/patcher/HitmanPatcher.UI/Properties/Resources.Designer.cs deleted file mode 100644 index d71cafe80..000000000 --- a/patcher/HitmanPatcher.UI/Properties/Resources.Designer.cs +++ /dev/null @@ -1,93 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace HitmanPatcher.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HitmanPatcher.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Novikov_error { - get { - object obj = ResourceManager.GetObject("Novikov_error", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Novikov_standard { - get { - object obj = ResourceManager.GetObject("Novikov_standard", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Novikov_success { - get { - object obj = ResourceManager.GetObject("Novikov_success", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} diff --git a/patcher/HitmanPatcher.UI/Properties/Resources.resx b/patcher/HitmanPatcher.UI/Properties/Resources.resx deleted file mode 100644 index 05f8454bd..000000000 --- a/patcher/HitmanPatcher.UI/Properties/Resources.resx +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\Novikov_error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Novikov_standard.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Novikov_success.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - \ No newline at end of file diff --git a/patcher/HitmanPatcher.UI/Resources.cs b/patcher/HitmanPatcher.UI/Resources.cs new file mode 100644 index 000000000..4d7bb9f53 --- /dev/null +++ b/patcher/HitmanPatcher.UI/Resources.cs @@ -0,0 +1,31 @@ +using System.Reflection; + +namespace HitmanPatcher +{ + public static class Resources + { + public static Icon Icon { get; } + public static Bitmap Novikov_standard { get; } + public static Bitmap Novikov_success { get; } + public static Bitmap Novikov_error { get; } + + static Resources() + { + Icon = new Icon(ReadResource("patcher.ico")); + Novikov_standard = new Bitmap(ReadResource("Novikov_standard.png")); + Novikov_success = new Bitmap(ReadResource("Novikov_success.png")); + Novikov_error = new Bitmap(ReadResource("Novikov_error.png")); + } + + private static Stream ReadResource(string name) + { + var assembly = Assembly.GetExecutingAssembly(); + + string resourcePath = assembly + .GetManifestResourceNames() + .Single(str => str.EndsWith(name)); + + return assembly.GetManifestResourceStream(resourcePath); + } + } +} diff --git a/patcher/build.bat b/patcher/build.bat index bf16ad0ec..cfa8b7e52 100644 --- a/patcher/build.bat +++ b/patcher/build.bat @@ -1,14 +1,18 @@ @echo off rem Windows - CLI -dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable -dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -f net8.0 -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 rem Linux - CLI -dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-Portable -dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c Release -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-x64 +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux -c "Release - Linux" -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-Portable +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -f net8.0 -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-x64 rem Windows - UI -dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable -dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 +dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -f net8.0-windows -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable +dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -f net8.0-windows -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 + +rem Windows (.NET Framework) +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Legacy -p:IsLegacy=True +dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Legacy -p:IsLegacy=True pause \ No newline at end of file From 006c1cd0e9bb48b690b10e43a1059d5b68fcb3b3 Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Sun, 18 Feb 2024 15:25:49 +0100 Subject: [PATCH 10/13] Attempt at fixing CodeQL --- .github/workflows/codeql.yml | 27 ++++++++++++++++++++++++++- .github/workflows/patcher.yml | 4 ++-- patcher/build.bat | 6 +++--- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 380f0fc59..570803db1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -6,6 +6,9 @@ on: pull_request: branches: [ "v6", v* ] +env: + DOTNET_VERSION: 8.x + jobs: analyze: name: Analyze @@ -29,9 +32,31 @@ jobs: with: languages: ${{ matrix.language }} - - name: Autobuild + - if: matrix.language != 'csharp' + name: Autobuild uses: github/codeql-action/autobuild@v3 + - if: matrix.language == 'csharp' + name: Setup .NET Core + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - if: matrix.language == 'csharp' + name: Build Patcher + run: | + export DOTNET_NOLOGO=true + export DOTNET_CLI_TELEMETRY_OPTOUT=true + cd patcher + export DOTNET_NOLOGO=true + export DOTNET_CLI_TELEMETRY_OPTOUT=true + cd patcher + dotnet build HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p:EnableWindowsTargeting=True + dotnet build HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p:EnableWindowsTargeting=True + dotnet build HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -p:IsLinux=true + dotnet build HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p:EnableWindowsTargeting=True -p:IsLegacy=True + dotnet build HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p:EnableWindowsTargeting=True -p:IsLegacy=True + - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: diff --git a/.github/workflows/patcher.yml b/.github/workflows/patcher.yml index a7c690d6a..3806b5ace 100644 --- a/.github/workflows/patcher.yml +++ b/.github/workflows/patcher.yml @@ -34,8 +34,8 @@ jobs: dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -f net8.0 -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-Portable dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -f net8.0 -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-x64 - dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -f net8.0-windows -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable - dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -f net8.0-windows -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 + dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable + dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Legacy -p:IsLegacy=True dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Legacy -p:IsLegacy=True diff --git a/patcher/build.bat b/patcher/build.bat index cfa8b7e52..9b85e21b7 100644 --- a/patcher/build.bat +++ b/patcher/build.bat @@ -4,12 +4,12 @@ dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p:PublishS dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r win-x64 -c Release -f net8.0 -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 rem Linux - CLI -dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux -c "Release - Linux" -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-Portable +dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-Portable dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -f net8.0 -p:PublishTrimmed=True -p:PublishSingleFile=True --self-contained -p DebugType=none -p:IsLinux=true -o Publish/Linux-x64 rem Windows - UI -dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -f net8.0-windows -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable -dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -f net8.0-windows -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 +dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p:PublishSingleFile=True --no-self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Portable +dotnet publish HitmanPatcher.UI/HitmanPatcher.UI.csproj -r win-x64 -c Release -p:PublishSingleFile=True --self-contained -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-x64 rem Windows (.NET Framework) dotnet publish HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p DebugType=none -p:EnableWindowsTargeting=True -o Publish/Windows-Legacy -p:IsLegacy=True From 17da4145fe79f933eb92461088a5d4d8fcd72e39 Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Sun, 18 Feb 2024 15:46:48 +0100 Subject: [PATCH 11/13] Fixed copy/paste error in codeql.yml --- .github/workflows/codeql.yml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 570803db1..014edd09c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -47,15 +47,12 @@ jobs: run: | export DOTNET_NOLOGO=true export DOTNET_CLI_TELEMETRY_OPTOUT=true - cd patcher - export DOTNET_NOLOGO=true - export DOTNET_CLI_TELEMETRY_OPTOUT=true - cd patcher - dotnet build HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p:EnableWindowsTargeting=True - dotnet build HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p:EnableWindowsTargeting=True - dotnet build HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -p:IsLinux=true - dotnet build HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p:EnableWindowsTargeting=True -p:IsLegacy=True - dotnet build HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p:EnableWindowsTargeting=True -p:IsLegacy=True + cd $GITHUB_WORKSPACE/patcher + dotnet build HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p:EnableWindowsTargeting=True + dotnet build HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p:EnableWindowsTargeting=True + dotnet build HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -r linux-x64 -c "Release - Linux" -p:IsLinux=true + dotnet build HitmanPatcher.CLI/HitmanPatcher.CLI.csproj -c Release -p:EnableWindowsTargeting=True -p:IsLegacy=True + dotnet build HitmanPatcher.UI/HitmanPatcher.UI.csproj -c Release -p:EnableWindowsTargeting=True -p:IsLegacy=True - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 From a48831cae1adfe62adda0679d0912bed6d5cecdc Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Sat, 29 Jun 2024 18:51:20 +0200 Subject: [PATCH 12/13] Added option for CLI to keep scanning for processes Fixed issue where legacy GUI also has a console --- patcher/HitmanPatcher.CLI/Cli.cs | 6 + .../HitmanPatcher.CLI/CliLocale.Designer.cs | 12 +- patcher/HitmanPatcher.CLI/CliLocale.resx | 187 +++++++++++++----- patcher/HitmanPatcher.CLI/Program.cs | 20 +- patcher/HitmanPatcher.UI/ILRepack.targets | 2 +- 5 files changed, 157 insertions(+), 70 deletions(-) diff --git a/patcher/HitmanPatcher.CLI/Cli.cs b/patcher/HitmanPatcher.CLI/Cli.cs index f0ef001e2..68490420a 100644 --- a/patcher/HitmanPatcher.CLI/Cli.cs +++ b/patcher/HitmanPatcher.CLI/Cli.cs @@ -25,6 +25,8 @@ internal class CliOptions internal bool? OptionalDynRes { get; set; } + internal bool? KeepScanning { get; set; } + internal static CliOptions FromArguments(string[] args) { var options = new CliOptions(); @@ -53,6 +55,9 @@ internal static CliOptions FromArguments(string[] args) case "--use-http": options.UseHttp = true; break; + case "--keep-scanning": + options.KeepScanning = true; + break; case "--help": Console.WriteLine(CliLocale.HelpHeader); Console.WriteLine(""); @@ -60,6 +65,7 @@ internal static CliOptions FromArguments(string[] args) Console.WriteLine($" --optional-dynamic-resources : {CliLocale.OptionalDynResDescription}"); Console.WriteLine($" --domain : {CliLocale.DomainDescription}"); Console.WriteLine($" --use-http : {CliLocale.UseHttpDescription}"); + Console.WriteLine($" --keep-scanning : {CliLocale.KeepScanning}"); Environment.Exit(0); break; } diff --git a/patcher/HitmanPatcher.CLI/CliLocale.Designer.cs b/patcher/HitmanPatcher.CLI/CliLocale.Designer.cs index fe09bc289..c8893e013 100644 --- a/patcher/HitmanPatcher.CLI/CliLocale.Designer.cs +++ b/patcher/HitmanPatcher.CLI/CliLocale.Designer.cs @@ -79,20 +79,20 @@ internal static string HeadlessBanner { } /// - /// Looks up a localized string similar to If the patcher should be run without the GUI.. + /// Looks up a localized string similar to Peacock Patcher CLI - Copyright (c) 2020-2024 grappigegovert & The Peacock Project. /// - internal static string HeadlessDescription { + internal static string HelpHeader { get { - return ResourceManager.GetString("HeadlessDescription", resourceCulture); + return ResourceManager.GetString("HelpHeader", resourceCulture); } } /// - /// Looks up a localized string similar to Peacock Patcher CLI - Copyright (c) 2020-2024 grappigegovert & The Peacock Project. + /// Looks up a localized string similar to If the patcher should keep scanning for processes after patching.. /// - internal static string HelpHeader { + internal static string KeepScanning { get { - return ResourceManager.GetString("HelpHeader", resourceCulture); + return ResourceManager.GetString("KeepScanning", resourceCulture); } } diff --git a/patcher/HitmanPatcher.CLI/CliLocale.resx b/patcher/HitmanPatcher.CLI/CliLocale.resx index b251cf8ee..11c75da8e 100644 --- a/patcher/HitmanPatcher.CLI/CliLocale.resx +++ b/patcher/HitmanPatcher.CLI/CliLocale.resx @@ -1,57 +1,138 @@ - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - If the patcher should be run without the GUI. - - - The domain for the game to connect to. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + If the patcher should keep scanning for processes after patching. + + + The domain for the game to connect to. + + + If the game should connect using "http://" instead of the default, "https://". + + + If the game should not force the user offline if the dynamic resources are missing or invalid. + + + ====== Peacock Patcher - Headless mode ====== + + + Peacock Patcher CLI - Copyright (c) 2020-2024 grappigegovert & The Peacock Project + + \ No newline at end of file diff --git a/patcher/HitmanPatcher.CLI/Program.cs b/patcher/HitmanPatcher.CLI/Program.cs index b8c6a641c..11c8055f9 100644 --- a/patcher/HitmanPatcher.CLI/Program.cs +++ b/patcher/HitmanPatcher.CLI/Program.cs @@ -29,20 +29,20 @@ private static void Main(string[] args) Console.WriteLine($"- DisableForceDynamicResources = {settings.patchOptions.DisableForceOfflineOnFailedDynamicResources}"); Console.WriteLine(); - bool result = false; + // Set the active values + settings.patchOptions.CustomConfigDomain = o.Domain ?? settings.patchOptions.CustomConfigDomain; + settings.patchOptions.DisableForceOfflineOnFailedDynamicResources = o.OptionalDynRes ?? settings.patchOptions.DisableForceOfflineOnFailedDynamicResources; + settings.patchOptions.UseHttp = o.UseHttp ?? settings.patchOptions.UseHttp; - while(!result) + var keepScanning = o.KeepScanning ?? false; + + while (true) { - result = MemoryPatcher.PatchAllProcesses(Compositions.Logger, settings.patchOptions with - { - CustomConfigDomain = o.Domain ?? settings.patchOptions.CustomConfigDomain, - DisableForceOfflineOnFailedDynamicResources = o.OptionalDynRes ?? settings.patchOptions.DisableForceOfflineOnFailedDynamicResources, - UseHttp = o.UseHttp ?? settings.patchOptions.UseHttp - }); + var result = MemoryPatcher.PatchAllProcesses(Compositions.Logger, settings.patchOptions); - if (result) + if (result && !keepScanning) { - continue; + break; } Console.WriteLine("Waiting..."); diff --git a/patcher/HitmanPatcher.UI/ILRepack.targets b/patcher/HitmanPatcher.UI/ILRepack.targets index 19e81fcc2..48ca8dd77 100644 --- a/patcher/HitmanPatcher.UI/ILRepack.targets +++ b/patcher/HitmanPatcher.UI/ILRepack.targets @@ -10,7 +10,7 @@ \ No newline at end of file From 739f8fd46e501b6dbce016455583dc08daf7b2fe Mon Sep 17 00:00:00 2001 From: Lennard Fonteijn Date: Sun, 30 Jun 2024 22:02:12 +0200 Subject: [PATCH 13/13] Fixed patching not working for the Steam version on Linux --- patcher/HitmanPatcher.Core/Pinvoke.Linux.cs | 73 ++++++++++++++------- patcher/HitmanPatcher.sln.DotSettings | 1 + 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs b/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs index 87d4167f5..09b769187 100644 --- a/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs +++ b/patcher/HitmanPatcher.Core/Pinvoke.Linux.cs @@ -1,6 +1,7 @@ #if LINUX using System.Diagnostics; using System.Runtime.InteropServices; +using System.Text.RegularExpressions; namespace HitmanPatcher; @@ -29,37 +30,22 @@ private enum PtraceRequest [DllImport("libc", SetLastError = true)] private static extern unsafe int process_vm_readv(int pid, iovec* local_iov, ulong liovcnt, iovec* remote_iov, ulong riovcnt, ulong flags); + private static readonly Regex _modulePathRegex = new Regex("\\/.*?$", RegexOptions.Compiled); + public static ProcessMetadata GetProcessMetadata(Process process) { var lines = File.ReadAllLines($"/proc/{process.Id}/maps"); var findProcess = process.ProcessName.ToLower(); - - var foundLines = lines.Where(x => x.ToLower().Contains(findProcess)).ToList(); - - long baseAddressStart = long.MaxValue; - long baseAddressEnd = 0; - - foreach (var line in foundLines) - { - var splittedLine = line.Split(' '); - var addressStartEnd = splittedLine[0].Split('-'); - - Compositions.Logger.log(addressStartEnd[0]); - Compositions.Logger.log(addressStartEnd[1]); - - baseAddressStart = Math.Min(baseAddressStart, Convert.ToInt64(addressStartEnd[0], 16)); - baseAddressEnd = Math.Max(baseAddressEnd, Convert.ToInt64(addressStartEnd[1], 16)); - } - - IntPtr baseAddress = new IntPtr(baseAddressStart); - var moduleMemorySize = baseAddressEnd - baseAddressStart; + var foundModule = lines.First(x => x.Contains(findProcess, StringComparison.CurrentCultureIgnoreCase)); + var foundModulePath = _modulePathRegex.Match(foundModule).Value; + var (baseAddress, imageSize) = GetImageSizeFromPE(foundModulePath); return new ProcessMetadata { PID = process.Id, - BaseAddress = baseAddress, - ModuleMemorySize = moduleMemorySize + BaseAddress = new IntPtr((long) baseAddress), + ModuleMemorySize = imageSize }; } @@ -253,5 +239,48 @@ public static int GetProcessParentPid(Process process) return -1; } + + private static (ulong, uint) GetImageSizeFromPE(string modulePath) + { + using var module = File.OpenRead(modulePath); + using var reader = new BinaryReader(module); + + //Validate DOS Header (MZ) + var dosHeader = reader.ReadUInt16(); + + if(dosHeader != 0x5A4D) { + return (0, 0); + } + + //Skip to PE offset + reader.BaseStream.Seek(0x3A, SeekOrigin.Current); + var peOffset = reader.ReadInt32(); + + //Validate PE Header (PE\0\0) + reader.BaseStream.Seek(peOffset, SeekOrigin.Begin); + var peHeader = reader.ReadUInt32(); + + if(peHeader != 0x00004550) { + return (0, 0); + } + + //Validate PE Type (PE32+) + reader.BaseStream.Seek(20, SeekOrigin.Current); + var peType = reader.ReadUInt16(); + + if(peType != 0x020B) { + return (0, 0); + } + + //Skip to base address + reader.BaseStream.Seek(22, SeekOrigin.Current); + var baseAddress = reader.ReadUInt64(); + + //Skip to image size + reader.BaseStream.Seek(24, SeekOrigin.Current); + var imageSize = reader.ReadUInt32(); + + return (baseAddress, imageSize); + } } #endif \ No newline at end of file diff --git a/patcher/HitmanPatcher.sln.DotSettings b/patcher/HitmanPatcher.sln.DotSettings index 9c64d6593..0d108e53e 100644 --- a/patcher/HitmanPatcher.sln.DotSettings +++ b/patcher/HitmanPatcher.sln.DotSettings @@ -9,6 +9,7 @@ DO_NOT_SHOW DO_NOT_SHOW DO_NOT_SHOW + PE True True True