public void Unpatch() { try { if (prefix != null) { patchProcessor.Unpatch(prefix); } if (postfix != null) { patchProcessor.Unpatch(postfix); } if (finalizer != null) { patchProcessor.Unpatch(finalizer); } if (transpiler != null) { patchProcessor.Unpatch(transpiler); } Enabled = false; } catch (Exception ex) { ExplorerCore.LogWarning($"Exception unpatching method: {ex}"); } }
public void UnPatch() { foreach (var patch in patches) { processor.Unpatch(patch); } }
public void AttemptRemoveHarmonyModPatch(Harmony h) { /* Needs to run after Harmony is OnEnabled() */ testName = "TEST/" + "API/ACL3/" + typeof(HarmonyHelper).Assembly.GetName().Name + " " + typeof(HarmonyHelper).Assembly.GetName().Version; PatchProcessor processor = null; MethodInfo prohibitedPatch = null; try { var targetName = "SetEntry"; MethodInfo target = typeof(PackageEntry).GetMethod(targetName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (target == null) { throw new TestFailed($"Target fn ({targetName}) was not found."); } processor = h.CreateProcessor(target); if (processor == null) { UnityEngine.Debug.Log($"[{testName}] INFO - Processor=null. BAD"); throw new TestFailed($"Failed to create processor."); } var patches = Harmony.GetPatchInfo(target); if (patches == null) { throw new TestFailed($"Failed to get '{target}' patches."); } if (patches.Prefixes != null) { UnityEngine.Debug.Log($"[{testName}] INFO - found {patches.Prefixes.Count} prefix patches to {targetName}"); } if (patches.Postfixes != null) { UnityEngine.Debug.Log($"[{testName}] INFO - found {patches.Postfixes.Count} postfix patches to {targetName}"); } if (patches.Transpilers != null) { UnityEngine.Debug.Log($"[{testName}] INFO - found {patches.Transpilers.Count} transpiler patches to {targetName}"); } if (patches.Finalizers != null) { UnityEngine.Debug.Log($"[{testName}] INFO - found {patches.Finalizers.Count} finalizer patches to {targetName}"); } patches.Postfixes.Do((p) => UnityEngine.Debug.Log($"[{testName}] INFO - found patch to {targetName} = {p.PatchMethod.Name} by {p.owner}")); bool found = false; patches.Postfixes.DoIf((p) => p.owner.Contains("org.ohmi.harmony"), (p) => { found = true; processor.Unpatch(p.PatchMethod); }); if (!found) { throw new TestFailed($"Mod's patch to {targetName} not found."); } throw new TestFailed("Removing a Mod's patch did not throw HarmonyModACLException"); } catch (TestFailed ex) { UnityEngine.Debug.Log($"[{testName}] ERROR : {ex.Message}. BAD"); throw ex; } catch (Exception ex) { if (ex.GetType().Name != "HarmonyModACLException") { throw new TestFailed($"Unpatching the mod failed but not because of ACL: {ex.Message}", ex); } UnityEngine.Debug.Log($"[{testName}] INFO - Attempting to unpatch the mod was blocked ({ex.Message}). OK."); } }
public void AttemptProhibitedPatch(Harmony h) { testName = "TEST/" + "API/ACL2/" + typeof(HarmonyHelper).Assembly.GetName().Name + " " + typeof(HarmonyHelper).Assembly.GetName().Version; PatchProcessor processor = null; MethodInfo prohibitedPatch = null; try { var targetName = "CompareTo"; MethodInfo target = typeof(Patch).GetMethod(targetName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (target == null) { throw new TestFailed($"Target fn ({targetName}) was not found."); } processor = h.CreateProcessor(target); if (processor == null) { UnityEngine.Debug.Log($"[{testName}] INFO - Processor=null. BAD"); throw new TestFailed($"Failed to create processor."); } prohibitedPatch = typeof(ACLPatchDefinitions).GetMethod("ProhibitedPatch", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (prohibitedPatch == null) { throw new TestFailed("Patch fn (ProhibitedPatch) was not found."); } processor.AddPostfix(prohibitedPatch); processor.Patch(); throw new TestFailed("Installing a prohibited patch did not throw HarmonyModACLException"); } catch (TestFailed ex) { UnityEngine.Debug.Log($"[{testName}] ERROR : {ex.Message}. BAD"); throw ex; } catch (Exception ex) { if (ex.GetType().Name != "HarmonyModACLException") { throw new TestFailed($"Installing a prohibited patch failed but not because of ACL: {ex.Message}"); } UnityEngine.Debug.Log($"[{testName}] INFO - Attempting to install a prohibited patch was blocked ({ex.Message}). OK."); } finally { if (processor != null && prohibitedPatch != null) { try { processor.Unpatch(prohibitedPatch); } catch (Exception ex) { if (ex.GetType().Name != "HarmonyModACLException") { throw new TestFailed($"Uninstalling a prohibited patch failed but not because of ACL: {ex.Message}"); } UnityEngine.Debug.Log($"[{testName}] INFO - Attempting to remove a prohibited patch was blocked ({ex.Message}). OK."); } } else { throw new TestFailed($"Prohibited patch test is broken. processor={processor != null} patch={prohibitedPatch != null}"); } } }
public void MethodRestorationTest() { var originalMethod = typeof(RestoreableClass).GetMethod("Method2"); Assert.IsNotNull(originalMethod); MethodInfo prefixMethod; MethodInfo postfixMethod; MethodInfo transpilerMethod; PatchTools.GetPatches(typeof(Class2Patch), out prefixMethod, out postfixMethod, out transpilerMethod); var instance = HarmonyInstance.Create("test"); var patcher = new PatchProcessor(instance, new List <MethodBase>() { originalMethod }, new HarmonyMethod(prefixMethod), new HarmonyMethod(postfixMethod), null); // Check if the class is clean before using it for patching Assert.AreEqual(null, instance.IsPatched(originalMethod), "Class already patched!"); Exception ex; var start = Memory.GetMethodStart(originalMethod, out ex); var oldBytes = new byte[12]; if (IntPtr.Size == sizeof(long)) { Marshal.Copy((IntPtr)start, oldBytes, 0, 12); } else { Marshal.Copy((IntPtr)start, oldBytes, 0, 6); } patcher.Patch(); patcher.Unpatch(originalMethod); var newBytes = new byte[12]; if (IntPtr.Size == sizeof(long)) { Marshal.Copy((IntPtr)start, newBytes, 0, 12); } else { Marshal.Copy((IntPtr)start, newBytes, 0, 6); } for (int i = 0; i < oldBytes.Length; i++) { Assert.AreEqual(oldBytes[i], newBytes[i], string.Format("Byte {0} differs after restoration", i)); } Class2Patch._reset(); new RestoreableClass().Method2(); Assert.IsFalse(Class2Patch.prefixed); Assert.IsTrue(Class2Patch.originalExecuted); Assert.IsFalse(Class2Patch.postfixed); Assert.AreEqual(0, instance.IsPatched(originalMethod).Postfixes.Count); Assert.AreEqual(0, instance.IsPatched(originalMethod).Prefixes.Count); Assert.AreEqual(0, instance.IsPatched(originalMethod).Transpilers.Count); }