private static Harmony CreateHarmony(string harmonyId) { var stack = new StackTrace(); var lastCaller = stack.GetFrame(0).GetMethod(); MethodBase caller = lastCaller; int assemblyDepth = 0; SameAssemblyName assemblyComparator = new SameAssemblyName(true, false, true, true); /* Search in the stack for the assembly that called * my caller(0Harmony 1.x) */ for (int i = 1; i < stack.FrameCount && assemblyDepth < 2; ++i) { caller = stack.GetFrame(i).GetMethod(); if (!assemblyComparator.Equals(lastCaller.DeclaringType.Assembly.GetName(), caller.DeclaringType.Assembly.GetName())) { lastCaller = caller; ++assemblyDepth; } } if (!Harmony.harmonyUsers.TryGetValue(caller.DeclaringType.Assembly.FullName, out var userStatus)) { Harmony.harmonyUsers[caller.DeclaringType.Assembly.FullName] = new Harmony.HarmonyUser() { checkBeforeUse = false, legacyCaller = true, instancesCreated = 0, }; } return(new Harmony(harmonyId, caller)); }
internal ModReport(PluginInfo p, HashSet <AssemblyName> haveAssemblies, HarmonyModSupportException unsupportedLibs = null, bool enumerated = true) { plugin = p; isEnumerated = enumerated; SameAssemblyName sameName = new SameAssemblyName(); if (p.assemblyCount != 0) { p.GetAssemblies() .Do((assembly) => { var refs = assembly.GetReferencedAssemblies(); foreach (var assemblyName in refs) { switch (assemblyName.Name) { case "0Harmony": needsHarmony = assemblyName.Version; m_usesHarmony = true; break; case "CitiesHarmony.API": needsHarmonyAPI = assemblyName.Version; m_usesHarmony = true; break; case "CitiesHarmony.Harmony": needsNewHarmony = assemblyName.Version; m_usesHarmony = true; break; } if (!haveAssemblies.Contains(assemblyName)) { m_missingAssemblies.Add(assemblyName); } if (unsupportedLibs != null) { unsupportedLibs.unsupportedAssemblies.ForEach((u) => { if (sameName.Equals(u.assembly.GetName(), assemblyName)) { ReportProblem(ModReport.ProblemType.ExceptionThrown, unsupportedLibs, u.Message); } }); } } }); } }
void ProhibitRemovingHarmony(MethodBase orginal, MethodBase caller, MethodInfo patchMethod) { SameAssemblyName sameAssembly = new SameAssemblyName(); var myAssembly = Assembly.GetExecutingAssembly(); if (sameAssembly.Equals(patchMethod.DeclaringType.Assembly.GetName(), myAssembly.GetName()) && !sameAssembly.Equals(caller.DeclaringType.Assembly.GetName(), myAssembly.GetName())) { throw new HarmonyModACLException($"(Un)Patching {Versioning.PACKAGE_NAME} is prohibited"); } #if HEAVY_TRACE UnityEngine.Debug.Log($"[{Versioning.FULL_PACKAGE_NAME}] UnpatchACL allows because caller is self or patch is not mine."); #endif }
internal void ReportUnsupportedHarmony(HarmonyModSupportException e) { SameAssemblyName sameName = new SameAssemblyName(); Array.ForEach(plugin.userModInstance.GetType().Assembly.GetReferencedAssemblies(), (refa) => { e.unsupportedAssemblies.ForEach((u) => { if (sameName.Equals(u.assembly.GetName(), refa)) { ReportProblem(ModReport.ProblemType.ExceptionThrown, e, u.Message); } }); }); }
void ProhibitPatchingHarmony(MethodBase original, MethodBase caller) { SameAssemblyName sameAssembly = new SameAssemblyName(); var myAssembly = Assembly.GetExecutingAssembly(); if (sameAssembly.Equals(caller.DeclaringType.Assembly.GetName(), myAssembly.GetName())) { return; } var originalAssemblyName = original.DeclaringType.Assembly.GetName(); SameAssemblyName signatureComparer = new SameAssemblyName(false, true, false, false); if (signatureComparer.Equals(originalAssemblyName, myAssembly.GetName()) || originalAssemblyName.Name == "0Harmony") { throw new HarmonyModACLException($"(Un)Patching {Versioning.PACKAGE_NAME} is prohibited"); } }