public bool IsApplicable(Game game) { var patchInfo = Harmony.GetPatchInfo(TargetMethodInfo); if (AlreadyPatched(patchInfo)) { return(false); } var bytes = TargetMethodInfo.GetCilBytes(); if (bytes == null) { return(false); } var hash = bytes.GetSha256(); return(hash.SequenceEqual(new byte[] { 0x31, 0x81, 0x47, 0x2b, 0x6a, 0xde, 0xc8, 0x26, 0x37, 0x68, 0xb3, 0x81, 0x0a, 0x47, 0x57, 0x51, 0x37, 0x30, 0xa4, 0xa4, 0xb3, 0xde, 0xa7, 0x59, 0x1a, 0x75, 0x90, 0x8a, 0x18, 0xdf, 0xa7, 0x2b })); }
public bool IsApplicable(Game game) { var patchInfo = Harmony.GetPatchInfo(TargetMethodInfo); if (AlreadyPatchedByOthers(patchInfo)) { return(false); } var bytes = TargetMethodInfo.GetCilBytes(); if (bytes == null) { return(false); } var hash = bytes.GetSha256(); return(hash.SequenceEqual(new byte[] { 0x4C, 0x29, 0xDC, 0x2D, 0x78, 0x89, 0xA7, 0xA8, 0xC6, 0xDA, 0x84, 0xDB, 0x07, 0x2E, 0x7D, 0xB4, 0x99, 0xED, 0xB2, 0xB9, 0xC4, 0xBB, 0xAD, 0xE4, 0xC9, 0xD1, 0xC8, 0x0F, 0xD7, 0x8C, 0x25, 0x15 })); }
public bool IsApplicable(Game game) { var patchInfo = Harmony.GetPatchInfo(TargetMethodInfo); if (AlreadyPatchedByOthers(patchInfo)) { return(false); } var hash = TargetMethodInfo.MakeCilSignatureSha256(); return(hash.MatchesAnySha256(Hashes)); }
internal static MethodInfo ReversePatch(HarmonyMethod standin, MethodBase original, MethodInfo postTranspiler) { if (standin == null) { throw new ArgumentNullException(nameof(standin)); } if (standin.method == null) { throw new ArgumentNullException($"{nameof(standin)}.{nameof(standin.method)}"); } var debug = (standin.debug ?? false) || Harmony.DEBUG; var transpilers = new List <MethodInfo>(); if (standin.reversePatchType == HarmonyReversePatchType.Snapshot) { var info = Harmony.GetPatchInfo(original); transpilers.AddRange(GetSortedPatchMethods(original, info.Transpilers.ToArray(), debug)); } if (postTranspiler != null) { transpilers.Add(postTranspiler); } var empty = new List <MethodInfo>(); var patcher = new MethodPatcher(standin.method, original, empty, empty, transpilers, empty, debug); var replacement = patcher.CreateReplacement(out var finalInstructions); if (replacement == null) { throw new MissingMethodException($"Cannot create replacement for {standin.method.FullDescription()}"); } try { var errorString = Memory.DetourMethod(standin.method, replacement); if (errorString != null) { throw new FormatException($"Method {standin.method.FullDescription()} cannot be patched. Reason: {errorString}"); } } catch (Exception ex) { throw HarmonyException.Create(ex, finalInstructions); } PatchTools.RememberObject(standin.method, replacement); return(replacement); }
internal static MethodInfo ReversePatch(HarmonyMethod standin, MethodBase original, Harmony instance, MethodInfo postTranspiler) { if (standin == null) { throw new ArgumentNullException(nameof(standin)); } if (standin.method == null) { throw new ArgumentNullException($"{nameof(standin)}.{nameof(standin.method)}"); } var transpilers = new List <MethodInfo>(); if (standin.reversePatchType == HarmonyReversePatchType.Snapshot) { var info = Harmony.GetPatchInfo(original); transpilers.AddRange(GetSortedPatchMethods(original, info.Transpilers.ToArray())); } if (postTranspiler != null) { transpilers.Add(postTranspiler); } var empty = new List <MethodInfo>(); var replacement = MethodPatcher.CreatePatchedMethod(standin.method, original, instance.Id, empty, empty, transpilers, empty); if (replacement == null) { throw new MissingMethodException($"Cannot create dynamic replacement for {standin.method.FullDescription()}"); } var errorString = Memory.DetourMethod(standin.method, replacement); if (errorString != null) { throw new FormatException($"Method {standin.method.FullDescription()} cannot be patched. Reason: {errorString}"); } PatchTools.RememberObject(standin.method, replacement); return(replacement); }
internal static MethodInfo ReversePatch(HarmonyMethod standin, MethodBase original, MethodInfo postTranspiler, MethodInfo postManipulator) { if (standin is null) { throw new ArgumentNullException(nameof(standin)); } if (standin.method is null) { throw new ArgumentNullException($"{nameof(standin)}.{nameof(standin.method)}"); } var transpilers = new List <MethodInfo>(); var ilmanipulators = new List <MethodInfo>(); if (standin.reversePatchType == HarmonyReversePatchType.Snapshot) { var info = Harmony.GetPatchInfo(original); transpilers.AddRange(GetSortedPatchMethods(original, info.Transpilers.ToArray())); ilmanipulators.AddRange(GetSortedPatchMethods(original, info.ILManipulators.ToArray())); } if (postTranspiler is object) { transpilers.Add(postTranspiler); } if (postManipulator is object) { ilmanipulators.Add(postManipulator); } MethodBody patchBody = null; var hook = new ILHook(standin.method, ctx => { if (!(original is MethodInfo mi)) { return; } patchBody = ctx.Body; var patcher = mi.GetMethodPatcher(); var dmd = patcher.CopyOriginal(); if (dmd == null) { throw new NullReferenceException($"Cannot reverse patch {mi.FullDescription()}: method patcher ({patcher.GetType().FullDescription()}) can't copy original method body"); } var manipulator = new ILManipulator(dmd.Definition.Body); // Copy over variables from the original code ctx.Body.Variables.Clear(); foreach (var variableDefinition in manipulator.Body.Variables) { ctx.Body.Variables.Add(new VariableDefinition(ctx.Module.ImportReference(variableDefinition.VariableType))); } foreach (var methodInfo in transpilers) { manipulator.AddTranspiler(methodInfo); } manipulator.WriteTo(ctx.Body, standin.method); HarmonyManipulator.ApplyILManipulators(ctx, original, ilmanipulators, null); // Write a ret in case it got removed (wrt. HarmonyManipulator) ctx.IL.Emit(OpCodes.Ret); }, new ILHookConfig {
public static void GenerateReport() { var sb = new StringBuilder(); try { sb.AppendLine("Recorded Unhandled Exceptions:"); var i = 0; foreach (var exc in RecordedUnhandledExceptions) { var excStr = exc.ToString(); sb.Append(" ").Append(++i).Append(". ").AppendLine(excStr.Replace("\n", "\n ")); var iex = exc; var j = 0; while (iex.InnerException != null) { iex = iex.InnerException; sb.Append(" ").Append(i).Append(".").Append(++j).Append(". ").AppendLine(excStr.Replace("\n", "\n ")); } } if (i == 0) { sb.AppendLine(" None."); } } catch (Exception ex) { sb.Append(" *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message); } sb.AppendLine(); try { sb.AppendLine("Recorded First Chance Exceptions:"); var i = 0; foreach (var exc in RecordedFirstChanceExceptions) { var excStr = exc.ToString(); sb.Append(" ").Append(++i).Append(". ").AppendLine(excStr.Replace("\n", "\n ")); var iex = exc; var j = 0; while (iex.InnerException != null) { iex = iex.InnerException; sb.Append(" ").Append(i).Append(".").Append(++j).Append(". ").AppendLine(excStr.Replace("\n", "\n ")); } } if (RecordFirstChanceExceptions) { if (i == 0) { sb.AppendLine(" None recorded."); } } else { sb.AppendLine(" Recording disabled."); } } catch (Exception ex) { sb.Append(" *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message); } sb.AppendLine(); try { sb.AppendLine("Modules Information:"); var i = 0; foreach (var mi in ModuleInfo.GetModules()) { sb.Append(" ").Append(++i).Append(". ").Append(mi.Id).Append(" ").Append(mi.Version.ToString()); if (mi.IsSelected) { sb.Append(" *Selected*"); } sb.AppendLine(); sb.Append(" ").Append(mi.Name); if (!String.IsNullOrWhiteSpace(mi.Alias)) { sb.Append(" (").Append(mi.Alias).Append(")"); } if (mi.IsOfficial) { sb.Append(" *Official*"); } sb.AppendLine(); if (mi.DependedModuleIds.Count <= 0) { continue; } sb.Append(" ").AppendLine("Dependencies:"); var j = 0; foreach (var dep in mi.DependedModuleIds) { sb.Append(" ").Append(++j).Append(". ").AppendLine(dep); } } } catch (Exception ex) { sb.Append(" *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message); } sb.AppendLine(); try { sb.AppendLine("Harmony Patch Information:"); var i = 0; foreach (var patchedMethod in Harmony.GetAllPatchedMethods()) { var patchInfo = Harmony.GetPatchInfo(patchedMethod); sb.Append(" ").Append(++i).Append(". ").AppendLine(patchedMethod.FullDescription()); if (patchInfo.Prefixes.Count > 0) { var j = 0; sb.Append(" ").AppendLine("Prefixes:"); foreach (var patch in patchInfo.Prefixes) { sb.Append(" ").Append(++j).Append(". ").AppendLine(patch.PatchMethod.FullDescription()); sb.Append(" ").AppendLine($"Owner: {patch.owner}, Priority: {patch.priority}"); } } if (patchInfo.Postfixes.Count > 0) { var j = 0; sb.Append(" ").AppendLine("Postfixes:"); foreach (var patch in patchInfo.Postfixes) { sb.Append(" ").Append(++j).Append(". ").AppendLine(patch.PatchMethod.FullDescription()); sb.Append(" ").AppendLine($"Owner: {patch.owner}, Priority: {patch.priority}"); } } if (patchInfo.Finalizers.Count > 0) { var j = 0; sb.Append(" ").AppendLine("Finalizers:"); foreach (var patch in patchInfo.Finalizers) { sb.Append(" ").Append(++j).Append(". ").AppendLine(patch.PatchMethod.FullDescription()); sb.Append(" ").AppendLine($"Owner: {patch.owner}, Priority: {patch.priority}"); } } if (patchInfo.Transpilers.Count > 0) { var j = 0; sb.Append(" ").AppendLine("Transpilers:"); foreach (var patch in patchInfo.Transpilers) { sb.Append(" ").Append(++j).Append(". ").AppendLine(patch.PatchMethod.FullDescription()); sb.Append(" ").AppendLine($"Owner: {patch.owner}, Priority: {patch.priority}"); } } } } catch (Exception ex) { sb.Append(" *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message); } sb.AppendLine(); try { sb.AppendLine("Community Patch Information:"); var i = 0; foreach (var patch in CommunityPatchSubModule.Patches) { var type = patch.GetType(); sb.Append(" ").Append(++i).Append(". ").Append(type.Name); if (ActivePatches.ContainsKey(type)) { sb.Append(" *Active*"); } var applicability = patch.IsApplicable(Game.Current); if (applicability ?? false) { sb.Append(" *Applicable*"); } if (applicability == null) { sb.Append(" *Maybe Applicable*"); } if (patch.Applied) { sb.Append(" *Applied*"); } sb.AppendLine(); } } catch (Exception ex) { sb.Append(" *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message); } sb.AppendLine(); try { sb.AppendLine("Loaded SubModules:"); var i = 0; foreach (var sm in Module.CurrentModule.SubModules) { try { var type = sm.GetType(); var asm = type.Assembly; sb.Append(" ").Append(++i).Append(". ").AppendLine(type.AssemblyQualifiedName); foreach (var version in asm.GetCustomAttributes <AssemblyInformationalVersionAttribute>()) { sb.Append(" v").AppendLine(version.InformationalVersion); } } catch (Exception ex) { sb.Append(" *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message); } } } catch (Exception ex) { sb.Append(" *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message); } sb.AppendLine(); AppendSystemReport(sb); try { var reportStr = sb.ToString(); ShowMessage("Saving to \"My Documents\\Mount and Blade II Bannerlord\\diagnostic-report.txt\""); try { var docsMnb2 = new Uri(System.IO.Path.Combine(PathHelpers.GetConfigsDir(), "..")).LocalPath; var now = DateTime.UtcNow; Random.GetNonZeroBytes(RandomIntBuf); var randomInt = Unsafe.ReadUnaligned <uint>(ref RandomIntBuf[0]); File.WriteAllText(System.IO.Path.Combine(docsMnb2, $"diagnostic-report.{now.Year:0000}{now.Month:00}{now.Day:00}{now.Hour:00}{now.Minute:00}{now.Second:00}{now.Millisecond}.{randomInt:X8}.txt"), reportStr); } catch (Exception ex2) { ShowMessage($"Failed to save diagnostic report!\n{ex2.GetType().Name}: {ex2.Message}"); } try { Input.SetClipboardText(reportStr); ShowMessage("Diagnostics also copied to system clipboard."); } catch (Exception ex) { ShowMessage($"Writing to system clipboard failed!\n{ex.GetType().Name}: {ex.Message}"); } } catch (Exception ex) { ShowMessage($"Failed to generate string from diagnostic report string buffer!\n{ex.GetType().Name}: {ex.Message}"); } }