public void Unpatch(HarmonyPatchType type, string harmonyID) { lock (locker) { foreach (var original in originals) { var patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Prefix) { PatchFunctions.RemovePrefix(patchInfo, harmonyID); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Postfix) { PatchFunctions.RemovePostfix(patchInfo, harmonyID); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Transpiler) { PatchFunctions.RemoveTranspiler(patchInfo, harmonyID); } PatchHandler.Get(original).Apply(); } } }
/// <summary>Gets current version information</summary> /// <param name="currentVersion">[out] The current Harmony version</param> /// <returns>A dictionary containing assembly versions keyed by Harmony version</returns> /// public Dictionary <string, Version> VersionInfo(out Version currentVersion) { currentVersion = typeof(HarmonyInstance).Assembly.GetName().Version; var assemblies = new Dictionary <string, Assembly>(); GetPatchedMethods().Do(method => { var info = HarmonySharedState.GetPatchInfo(method); info.prefixes.Do(fix => assemblies[fix.owner] = fix.patch.DeclaringType.Assembly); info.postfixes.Do(fix => assemblies[fix.owner] = fix.patch.DeclaringType.Assembly); info.transpilers.Do(fix => assemblies[fix.owner] = fix.patch.DeclaringType.Assembly); }); var result = new Dictionary <string, Version>(); assemblies.Do(info => { var assemblyName = info.Value.GetReferencedAssemblies().FirstOrDefault(a => a.FullName.StartsWith("0Harmony, Version")); if (assemblyName != null) { result[info.Key] = assemblyName.Version; } }); return(result); }
public void Patch() { var obj = locker; lock (obj) { foreach (var methodBase in originals) { if (methodBase == null) { throw new NullReferenceException("original"); } if (RunMethod <HarmonyPrepare, bool>(true, methodBase)) { var patchInfo = HarmonySharedState.GetPatchInfo(methodBase) ?? new PatchInfo(); PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix); PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix); PatchFunctions.AddTranspiler(patchInfo, instance.Id, transpiler); PatchFunctions.UpdateWrapper(methodBase, patchInfo, instance.Id); HarmonySharedState.UpdatePatchInfo(methodBase, patchInfo); RunMethod <HarmonyCleanup>(methodBase); } } } }
/// <summary> /// 执行Patch /// </summary> /// <returns></returns> public PatchInfoData Patch(PatchFlags flags) { PatchInfo patchInfo = null; lock (locker) { #if RECORD_PATCH_STATE patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } #endif patchInfo = new PatchInfo(); PatchFunctions.AddPrefix(patchInfo, instance.id, prefix); PatchFunctions.AddPostfix(patchInfo, instance.id, postfix); PatchFunctions.AddTranspiler(patchInfo, instance.id, transpiler); PatchFunctions.UpdateWrapper(original, patchInfo, flags); #if RECORD_PATCH_STATE HarmonySharedState.UpdatePatchInfo(original, patchInfo); #endif } return(patchInfo.patchdata); }
public List <DynamicMethod> Patch() { lock (locker) { var dynamicMethods = new List <DynamicMethod>(); foreach (var original in originals) { if (original == null) { throw new NullReferenceException("original"); } var individualPrepareResult = RunMethod <HarmonyPrepare, bool>(true, original); if (individualPrepareResult) { var patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix); PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix); PatchFunctions.AddTranspiler(patchInfo, instance.Id, transpiler); dynamicMethods.Add(PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id)); HarmonySharedState.UpdatePatchInfo(original, patchInfo); RunMethod <HarmonyCleanup>(original); } } return(dynamicMethods); } }
public void Unpatch(HarmonyPatchType type, string harmonyID) { lock (locker) { foreach (var original in originals) { var patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Prefix) { PatchFunctions.RemovePrefix(patchInfo, harmonyID); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Postfix) { PatchFunctions.RemovePostfix(patchInfo, harmonyID); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Transpiler) { PatchFunctions.RemoveTranspiler(patchInfo, harmonyID); } PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id); HarmonySharedState.UpdatePatchInfo(original, patchInfo); } } }
public void Unpatch(HarmonyPatchType type, string harmonyID) { var obj = locker; lock (obj) { foreach (var methodBase in originals) { var patchInfo = HarmonySharedState.GetPatchInfo(methodBase) ?? new PatchInfo(); if (type == HarmonyPatchType.All || type == HarmonyPatchType.Prefix) { PatchFunctions.RemovePrefix(patchInfo, harmonyID); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Postfix) { PatchFunctions.RemovePostfix(patchInfo, harmonyID); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Transpiler) { PatchFunctions.RemoveTranspiler(patchInfo, harmonyID); } PatchFunctions.UpdateWrapper(methodBase, patchInfo, instance.Id); HarmonySharedState.UpdatePatchInfo(methodBase, patchInfo); } } }
private static IEnumerable <CodeInstruction> UnhollowerTranspiler(MethodBase method, IEnumerable <CodeInstruction> instructionsIn) { List <CodeInstruction> instructions = new List <CodeInstruction>(instructionsIn); PatchInfo patchInfo = HarmonySharedState.GetPatchInfo(method); IntPtr copiedMethodInfo = patchInfo.copiedMethodInfoPointer; bool found = false; int replaceIdx = 0; int replaceCount = 0; for (int i = instructions.Count - 2; i >= 0; --i) { if (instructions[i].opcode != OpCodes.Ldsfld) { continue; } found = true; CodeInstruction next = instructions[i + 1]; if (next.opcode == OpCodes.Call && ((MethodInfo)next.operand).Name == "il2cpp_object_get_virtual_method") { // Virtual method: Replace the sequence // - ldarg.0 // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::Il2CppObjectBaseToPtr(class [UnhollowerBaseLib] UnhollowerBaseLib.Il2CppObjectBase) // - ldsfld native int SomeClass::NativeMethodInfoPtr_Etc // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::il2cpp_object_get_virtual_method(native int, native int) replaceIdx = i - 2; replaceCount = 4; } else { // Everything else: Just replace the static load replaceIdx = i; replaceCount = 1; } break; } if (!found) { MelonLogger.Error("Harmony transpiler could not rewrite Unhollower method. Expect a stack overflow."); return(instructions); } CodeInstruction[] replacement = { new CodeInstruction(OpCodes.Ldc_I8, copiedMethodInfo.ToInt64()), new CodeInstruction(OpCodes.Conv_I) }; instructions.RemoveRange(replaceIdx, replaceCount); instructions.InsertRange(replaceIdx, replacement); return(instructions); }
public static Patches IsPatched(MethodBase method) { var patchInfo = HarmonySharedState.GetPatchInfo(method); if (patchInfo == null) { return(null); } return(new Patches(patchInfo.prefixes, patchInfo.postfixes, patchInfo.transpilers)); }
public Dictionary <string, Version> VersionInfo(out Version currentVersion) { currentVersion = Assembly.GetExecutingAssembly().GetName().Version; var assemblies = new Dictionary <string, Assembly>(); Action <Patch> a1 = null; Action <Patch> a2 = null; Action <Patch> a3 = null; GetPatchedMethods().Do(delegate(MethodBase method) { var patchInfo = HarmonySharedState.GetPatchInfo(method); IEnumerable <Patch> prefixes = patchInfo.prefixes; Action <Patch> action; if ((action = a1) == null) { action = (a1 = delegate(Patch fix) { assemblies[fix.owner] = fix.patch.DeclaringType.Assembly; }); } prefixes.Do(action); IEnumerable <Patch> postfixes = patchInfo.postfixes; Action <Patch> action2; if ((action2 = a2) == null) { action2 = (a2 = delegate(Patch fix) { assemblies[fix.owner] = fix.patch.DeclaringType.Assembly; }); } postfixes.Do(action2); IEnumerable <Patch> transpilers = patchInfo.transpilers; Action <Patch> action3; if ((action3 = a3) == null) { action3 = (a3 = delegate(Patch fix) { assemblies[fix.owner] = fix.patch.DeclaringType.Assembly; }); } transpilers.Do(action3); }); var result = new Dictionary <string, Version>(); assemblies.Do(delegate(KeyValuePair <string, Assembly> info) { var assemblyName = info.Value.GetReferencedAssemblies() .FirstOrDefault(a => a.FullName.StartsWith("0Harmony, Version")); if (assemblyName != null) { result[info.Key] = assemblyName.Version; } }); return(result); }
public void Unpatch(MethodInfo patch) { var obj = locker; lock (obj) { foreach (var methodBase in originals) { var patchInfo = HarmonySharedState.GetPatchInfo(methodBase) ?? new PatchInfo(); PatchFunctions.RemovePatch(patchInfo, patch); PatchFunctions.UpdateWrapper(methodBase, patchInfo, instance.Id); HarmonySharedState.UpdatePatchInfo(methodBase, patchInfo); } } }
public void Patch() { lock (locker) { var patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix); PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix); PatchFunctions.AddInfix(patchInfo, instance.Id, infix); PatchFunctions.UpdateWrapper(original, patchInfo); HarmonySharedState.UpdatePatchInfo(original, patchInfo); } }
public void Unpatch(MethodInfo patch) { lock (locker) { foreach (var original in originals) { var patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } PatchFunctions.RemovePatch(patchInfo, patch); PatchHandler.Get(original).Apply(); } } }
public void Patch() { lock (locker) { var patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix); PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix); PatchFunctions.AddTranspiler(patchInfo, instance.Id, transpiler); PatchHandler.Get(original).Apply(); } }
public List <DynamicMethod> Patch() { lock (locker) { var dynamicMethods = new List <DynamicMethod>(); foreach (var original in originals) { if (original == null) { throw new NullReferenceException("original"); } if ((original.DeclaringType.Assembly.GetCustomAttributes(typeof(HarmonyShield), false).Count() > 0) || (original.DeclaringType.GetCustomAttributes(typeof(HarmonyShield), false).Count() > 0) || (original.GetCustomAttributes(typeof(HarmonyShield), false).Count() > 0)) { continue; } if (MelonDebug.IsEnabled() && UnhollowerSupport.IsGeneratedAssemblyType(original.DeclaringType)) { WarnIfTargetMethodInlined(original); } var individualPrepareResult = RunMethod <HarmonyPrepare, bool>(true, original); if (individualPrepareResult) { var patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix); PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix); PatchFunctions.AddTranspiler(patchInfo, instance.Id, transpiler); dynamicMethods.Add(PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id)); HarmonySharedState.UpdatePatchInfo(original, patchInfo); RunMethod <HarmonyCleanup>(original); } } return(dynamicMethods); } }
public void Restore() { lock (locker) { var patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { return; } PatchFunctions.RemovePrefix(patchInfo, prefix); PatchFunctions.RemovePostfix(patchInfo, postfix); PatchFunctions.RemoveTranspiler(patchInfo, transpiler); PatchFunctions.UpdateWrapper(original, patchInfo); HarmonySharedState.UpdatePatchInfo(original, patchInfo); } }
public void Unpatch(MethodInfo patch) { lock (locker) { foreach (var original in originals) { var patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } PatchFunctions.RemovePatch(patchInfo, patch); PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id); HarmonySharedState.UpdatePatchInfo(original, patchInfo); } } }
public static Patches GetPatchInfo(MethodBase method) { var obj = locker; Patches result; lock (obj) { var patchInfo = HarmonySharedState.GetPatchInfo(method); if (patchInfo == null) { result = null; } else { result = new Patches(patchInfo.prefixes, patchInfo.postfixes, patchInfo.transpilers, patchInfo.finalizers); } } return(result); }
public void Apply() { PatchMethod[] ToPatchMethod(Patch[] patches) { return(patches.Select(p => new PatchMethod { after = p.after, before = p.before, method = p.patch, priority = p.priority, owner = p.owner, }).ToArray()); } var info = HarmonySharedState.GetPatchInfo(mb); var state = new PatchInfoWrapper { prefixes = ToPatchMethod(info.prefixes), postfixes = ToPatchMethod(info.postfixes), transpilers = ToPatchMethod(info.transpilers), finalizers = new PatchMethod[0] }; var add = new PatchInfoWrapper { finalizers = new PatchMethod[0] }; var remove = new PatchInfoWrapper { finalizers = new PatchMethod[0] }; Diff(previousState.prefixes, state.prefixes, out add.prefixes, out remove.prefixes); Diff(previousState.postfixes, state.postfixes, out add.postfixes, out remove.postfixes); Diff(previousState.transpilers, state.transpilers, out add.transpilers, out remove.transpilers); previousState = state; HarmonyInterop.ApplyPatch(mb, add, remove); }