Decompiled source of Crazy Russian translator v0.1.0
BepInEx/core/0Harmony.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using HarmonyLib.Internal.Patching; using HarmonyLib.Internal.RuntimeFixes; using HarmonyLib.Internal.Util; using HarmonyLib.Public.Patching; using HarmonyLib.Tools; using JetBrains.Annotations; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Cil; using MonoMod.RuntimeDetour; using MonoMod.Utils; using MonoMod.Utils.Cil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: ComVisible(false)] [assembly: InternalsVisibleTo("HarmonyTests")] [assembly: InternalsVisibleTo("MonoMod.Utils.Cil.ILGeneratorProxy")] [assembly: Guid("69aee16a-b6e7-4642-8081-3928b32455df")] [assembly: AssemblyCompany("BepInEx")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © BepInEx 2022")] [assembly: AssemblyDescription("A library for patching, replacing and decorating .NET and Mono methods during runtime powered by MonoMod.")] [assembly: AssemblyFileVersion("2.9.0.0")] [assembly: AssemblyInformationalVersion("2.9.0")] [assembly: AssemblyProduct("HarmonyX")] [assembly: AssemblyTitle("0Harmony")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.9.0.0")] [module: UnverifiableCode] namespace System { internal struct ValueTuple<T1, T2> { public T1 Item1; public T2 Item2; public ValueTuple(T1 first, T2 second) { Item1 = first; Item2 = second; } } internal struct ValueTuple<T1, T2, T3> { public T1 Item1; public T2 Item2; public T3 Item3; public ValueTuple(T1 first, T2 second, T3 third) { Item1 = first; Item2 = second; Item3 = third; } } } namespace JetBrains.Annotations { [AttributeUsage(AttributeTargets.All)] internal sealed class UsedImplicitlyAttribute : Attribute { public ImplicitUseKindFlags UseKindFlags { get; } public ImplicitUseTargetFlags TargetFlags { get; } public UsedImplicitlyAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) { } public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) { } public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) { UseKindFlags = useKindFlags; TargetFlags = targetFlags; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter | AttributeTargets.GenericParameter)] internal sealed class MeansImplicitUseAttribute : Attribute { [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; } [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; } public MeansImplicitUseAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) { } public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) { } public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) { UseKindFlags = useKindFlags; TargetFlags = targetFlags; } } [Flags] internal enum ImplicitUseKindFlags { Default = 7, Access = 1, Assign = 2, InstantiatedWithFixedConstructorSignature = 4, InstantiatedNoFixedConstructorSignature = 8 } [Flags] internal enum ImplicitUseTargetFlags { Default = 1, Itself = 1, Members = 2, WithInheritors = 4, WithMembers = 3 } } namespace HarmonyLib { public class DelegateTypeFactory { private class DelegateEntry { public CallingConvention? callingConvention; public Type delegateType; } private static int counter; private static readonly Dictionary<MethodInfo, List<DelegateEntry>> TypeCache = new Dictionary<MethodInfo, List<DelegateEntry>>(); private static readonly MethodBase CallingConvAttr = AccessTools.Constructor(typeof(UnmanagedFunctionPointerAttribute), new Type[1] { typeof(CallingConvention) }); public static readonly DelegateTypeFactory instance = new DelegateTypeFactory(); public Type CreateDelegateType(Type returnType, Type[] argTypes) { return CreateDelegateType(returnType, argTypes, null); } public Type CreateDelegateType(Type returnType, Type[] argTypes, CallingConvention? convention) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) counter++; AssemblyDefinition val = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition($"HarmonyDTFAssembly{counter}", new Version(1, 0)), $"HarmonyDTFModule{counter}", (ModuleKind)0); ModuleDefinition module = val.MainModule; TypeDefinition val2 = new TypeDefinition("", $"HarmonyDTFType{counter}", (TypeAttributes)257) { BaseType = module.ImportReference(typeof(MulticastDelegate)) }; module.Types.Add(val2); if (convention.HasValue) { CustomAttribute val3 = new CustomAttribute(module.ImportReference(CallingConvAttr)); val3.ConstructorArguments.Add(new CustomAttributeArgument(module.ImportReference(typeof(CallingConvention)), (object)convention.Value)); val2.CustomAttributes.Add(val3); } MethodDefinition val4 = new MethodDefinition(".ctor", (MethodAttributes)4230, module.ImportReference(typeof(void))) { ImplAttributes = (MethodImplAttributes)3 }; Extensions.AddRange<ParameterDefinition>(((MethodReference)val4).Parameters, (IEnumerable<ParameterDefinition>)(object)new ParameterDefinition[2] { new ParameterDefinition(module.ImportReference(typeof(object))), new ParameterDefinition(module.ImportReference(typeof(IntPtr))) }); val2.Methods.Add(val4); MethodDefinition val5 = new MethodDefinition("Invoke", (MethodAttributes)198, module.ImportReference(returnType)) { ImplAttributes = (MethodImplAttributes)3 }; Extensions.AddRange<ParameterDefinition>(((MethodReference)val5).Parameters, ((IEnumerable<Type>)argTypes).Select((Func<Type, ParameterDefinition>)((Type t) => new ParameterDefinition(module.ImportReference(t))))); val2.Methods.Add(val5); return ReflectionHelper.Load(val.MainModule).GetType($"HarmonyDTFType{counter}"); } public Type CreateDelegateType(MethodInfo method) { return CreateDelegateType(method, null); } public Type CreateDelegateType(MethodInfo method, CallingConvention? convention) { DelegateEntry delegateEntry; if (TypeCache.TryGetValue(method, out var value) && (delegateEntry = value.FirstOrDefault((DelegateEntry e) => e.callingConvention == convention)) != null) { return delegateEntry.delegateType; } if (value == null) { value = (TypeCache[method] = new List<DelegateEntry>()); } delegateEntry = new DelegateEntry { delegateType = CreateDelegateType(method.ReturnType, method.GetParameters().Types().ToArray(), convention), callingConvention = convention }; value.Add(delegateEntry); return delegateEntry.delegateType; } } [Obsolete("Use AccessTools.FieldRefAccess<T, S> for fields and AccessTools.MethodDelegate<Func<T, S>> for property getters")] public delegate S GetterHandler<in T, out S>(T source); [Obsolete("Use AccessTools.FieldRefAccess<T, S> for fields and AccessTools.MethodDelegate<Action<T, S>> for property setters")] public delegate void SetterHandler<in T, in S>(T source, S value); public delegate T InstantiationHandler<out T>(); public static class FastAccess { public static InstantiationHandler<T> CreateInstantiationHandler<T>() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) ConstructorInfo constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null); if ((object)constructor == null) { throw new ApplicationException($"The type {typeof(T)} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public)."); } DynamicMethodDefinition val = new DynamicMethodDefinition("InstantiateObject_" + typeof(T).Name, typeof(T), (Type[])null); ILGenerator iLGenerator = val.GetILGenerator(); iLGenerator.Emit(OpCodes.Newobj, constructor); iLGenerator.Emit(OpCodes.Ret); return (InstantiationHandler<T>)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(InstantiationHandler<T>)); } [Obsolete("Use AccessTools.MethodDelegate<Func<T, S>>(PropertyInfo.GetGetMethod(true))")] public static GetterHandler<T, S> CreateGetterHandler<T, S>(PropertyInfo propertyInfo) { MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); DynamicMethodDefinition obj = CreateGetDynamicMethod<T, S>(propertyInfo.DeclaringType); ILGenerator iLGenerator = obj.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Call, getMethod); iLGenerator.Emit(OpCodes.Ret); return (GetterHandler<T, S>)Extensions.CreateDelegate((MethodBase)obj.Generate(), typeof(GetterHandler<T, S>)); } [Obsolete("Use AccessTools.FieldRefAccess<T, S>(fieldInfo)")] public static GetterHandler<T, S> CreateGetterHandler<T, S>(FieldInfo fieldInfo) { DynamicMethodDefinition obj = CreateGetDynamicMethod<T, S>(fieldInfo.DeclaringType); ILGenerator iLGenerator = obj.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldfld, fieldInfo); iLGenerator.Emit(OpCodes.Ret); return (GetterHandler<T, S>)Extensions.CreateDelegate((MethodBase)obj.Generate(), typeof(GetterHandler<T, S>)); } [Obsolete("Use AccessTools.FieldRefAccess<T, S>(name) for fields and AccessTools.MethodDelegate<Func<T, S>>(AccessTools.PropertyGetter(typeof(T), name)) for properties")] public static GetterHandler<T, S> CreateFieldGetter<T, S>(params string[] names) { foreach (string name in names) { FieldInfo field = typeof(T).GetField(name, AccessTools.all); if ((object)field != null) { return CreateGetterHandler<T, S>(field); } PropertyInfo property = typeof(T).GetProperty(name, AccessTools.all); if ((object)property != null) { return CreateGetterHandler<T, S>(property); } } return null; } [Obsolete("Use AccessTools.MethodDelegate<Action<T, S>>(PropertyInfo.GetSetMethod(true))")] public static SetterHandler<T, S> CreateSetterHandler<T, S>(PropertyInfo propertyInfo) { MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); DynamicMethodDefinition obj = CreateSetDynamicMethod<T, S>(propertyInfo.DeclaringType); ILGenerator iLGenerator = obj.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Call, setMethod); iLGenerator.Emit(OpCodes.Ret); return (SetterHandler<T, S>)Extensions.CreateDelegate((MethodBase)obj.Generate(), typeof(SetterHandler<T, S>)); } [Obsolete("Use AccessTools.FieldRefAccess<T, S>(fieldInfo)")] public static SetterHandler<T, S> CreateSetterHandler<T, S>(FieldInfo fieldInfo) { DynamicMethodDefinition obj = CreateSetDynamicMethod<T, S>(fieldInfo.DeclaringType); ILGenerator iLGenerator = obj.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Stfld, fieldInfo); iLGenerator.Emit(OpCodes.Ret); return (SetterHandler<T, S>)Extensions.CreateDelegate((MethodBase)obj.Generate(), typeof(SetterHandler<T, S>)); } private static DynamicMethodDefinition CreateGetDynamicMethod<T, S>(Type type) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown return new DynamicMethodDefinition("DynamicGet_" + type.Name, typeof(S), new Type[1] { typeof(T) }); } private static DynamicMethodDefinition CreateSetDynamicMethod<T, S>(Type type) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown return new DynamicMethodDefinition("DynamicSet_" + type.Name, typeof(void), new Type[2] { typeof(T), typeof(S) }); } } public delegate object FastInvokeHandler(object target, params object[] parameters); public static class MethodInvoker { public static FastInvokeHandler GetHandler(MethodInfo methodInfo, bool directBoxValueAccess = false) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown DynamicMethodDefinition val = new DynamicMethodDefinition("FastInvoke_" + methodInfo.Name + "_" + (directBoxValueAccess ? "direct" : "indirect"), typeof(object), new Type[2] { typeof(object), typeof(object[]) }); ILGenerator iLGenerator = val.GetILGenerator(); if (!methodInfo.IsStatic) { Emit(iLGenerator, OpCodes.Ldarg_0); EmitUnboxIfNeeded(iLGenerator, methodInfo.DeclaringType); } bool flag = true; ParameterInfo[] parameters = methodInfo.GetParameters(); for (int i = 0; i < parameters.Length; i++) { Type type = parameters[i].ParameterType; bool isByRef = type.IsByRef; if (isByRef) { type = type.GetElementType(); } bool isValueType = type.IsValueType; if (isByRef && isValueType && !directBoxValueAccess) { Emit(iLGenerator, OpCodes.Ldarg_1); EmitFastInt(iLGenerator, i); } Emit(iLGenerator, OpCodes.Ldarg_1); EmitFastInt(iLGenerator, i); if (isByRef && !isValueType) { Emit(iLGenerator, OpCodes.Ldelema, typeof(object)); continue; } Emit(iLGenerator, OpCodes.Ldelem_Ref); if (!isValueType) { continue; } if (!isByRef || !directBoxValueAccess) { Emit(iLGenerator, OpCodes.Unbox_Any, type); if (isByRef) { Emit(iLGenerator, OpCodes.Box, type); Emit(iLGenerator, OpCodes.Dup); if (flag) { flag = false; iLGenerator.DeclareLocal(typeof(object), pinned: false); } Emit(iLGenerator, OpCodes.Stloc_0); Emit(iLGenerator, OpCodes.Stelem_Ref); Emit(iLGenerator, OpCodes.Ldloc_0); Emit(iLGenerator, OpCodes.Unbox, type); } } else { Emit(iLGenerator, OpCodes.Unbox, type); } } if (methodInfo.IsStatic) { EmitCall(iLGenerator, OpCodes.Call, methodInfo); } else { EmitCall(iLGenerator, OpCodes.Callvirt, methodInfo); } if ((object)methodInfo.ReturnType == typeof(void)) { Emit(iLGenerator, OpCodes.Ldnull); } else { EmitBoxIfNeeded(iLGenerator, methodInfo.ReturnType); } Emit(iLGenerator, OpCodes.Ret); return (FastInvokeHandler)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(FastInvokeHandler)); } internal static void Emit(ILGenerator il, OpCode opcode) { il.Emit(opcode); } internal static void Emit(ILGenerator il, OpCode opcode, Type type) { il.Emit(opcode, type); } internal static void EmitCall(ILGenerator il, OpCode opcode, MethodInfo methodInfo) { il.EmitCall(opcode, methodInfo, null); } private static void EmitUnboxIfNeeded(ILGenerator il, Type type) { if (type.IsValueType) { Emit(il, OpCodes.Unbox_Any, type); } } private static void EmitBoxIfNeeded(ILGenerator il, Type type) { if (type.IsValueType) { Emit(il, OpCodes.Box, type); } } internal static void EmitFastInt(ILGenerator il, int value) { switch (value) { case -1: il.Emit(OpCodes.Ldc_I4_M1); return; case 0: il.Emit(OpCodes.Ldc_I4_0); return; case 1: il.Emit(OpCodes.Ldc_I4_1); return; case 2: il.Emit(OpCodes.Ldc_I4_2); return; case 3: il.Emit(OpCodes.Ldc_I4_3); return; case 4: il.Emit(OpCodes.Ldc_I4_4); return; case 5: il.Emit(OpCodes.Ldc_I4_5); return; case 6: il.Emit(OpCodes.Ldc_I4_6); return; case 7: il.Emit(OpCodes.Ldc_I4_7); return; case 8: il.Emit(OpCodes.Ldc_I4_8); return; } if (value > -129 && value < 128) { il.Emit(OpCodes.Ldc_I4_S, (sbyte)value); } else { il.Emit(OpCodes.Ldc_I4, value); } } } internal class AccessCache { internal enum MemberType { Any, Static, Instance } private const BindingFlags BasicFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty; private static readonly Dictionary<MemberType, BindingFlags> declaredOnlyBindingFlags = new Dictionary<MemberType, BindingFlags> { { MemberType.Any, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty }, { MemberType.Instance, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty }, { MemberType.Static, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty } }; private readonly Dictionary<Type, Dictionary<string, FieldInfo>> declaredFields = new Dictionary<Type, Dictionary<string, FieldInfo>>(); private readonly Dictionary<Type, Dictionary<string, PropertyInfo>> declaredProperties = new Dictionary<Type, Dictionary<string, PropertyInfo>>(); private readonly Dictionary<Type, Dictionary<string, Dictionary<int, MethodBase>>> declaredMethods = new Dictionary<Type, Dictionary<string, Dictionary<int, MethodBase>>>(); private readonly Dictionary<Type, Dictionary<string, FieldInfo>> inheritedFields = new Dictionary<Type, Dictionary<string, FieldInfo>>(); private readonly Dictionary<Type, Dictionary<string, PropertyInfo>> inheritedProperties = new Dictionary<Type, Dictionary<string, PropertyInfo>>(); private readonly Dictionary<Type, Dictionary<string, Dictionary<int, MethodBase>>> inheritedMethods = new Dictionary<Type, Dictionary<string, Dictionary<int, MethodBase>>>(); private static T Get<T>(Dictionary<Type, Dictionary<string, T>> dict, Type type, string name, Func<T> fetcher) { lock (dict) { if (!dict.TryGetValue(type, out var value)) { value = (dict[type] = new Dictionary<string, T>()); } if (!value.TryGetValue(name, out var value2)) { value2 = (value[name] = fetcher()); } return value2; } } private static T Get<T>(Dictionary<Type, Dictionary<string, Dictionary<int, T>>> dict, Type type, string name, Type[] arguments, Func<T> fetcher) { lock (dict) { if (!dict.TryGetValue(type, out var value)) { value = (dict[type] = new Dictionary<string, Dictionary<int, T>>()); } if (!value.TryGetValue(name, out var value2)) { value2 = (value[name] = new Dictionary<int, T>()); } int key = AccessTools.CombinedHashCode(arguments); if (!value2.TryGetValue(key, out var value3)) { value3 = (value2[key] = fetcher()); } return value3; } } internal FieldInfo GetFieldInfo(Type type, string name, MemberType memberType = MemberType.Any, bool declaredOnly = false) { FieldInfo fieldInfo = Get(declaredFields, type, name, () => type.GetField(name, declaredOnlyBindingFlags[memberType])); if ((object)fieldInfo == null && !declaredOnly) { fieldInfo = Get(inheritedFields, type, name, () => AccessTools.FindIncludingBaseTypes(type, (Type t) => t.GetField(name, AccessTools.all))); } return fieldInfo; } internal PropertyInfo GetPropertyInfo(Type type, string name, MemberType memberType = MemberType.Any, bool declaredOnly = false) { PropertyInfo propertyInfo = Get(declaredProperties, type, name, () => type.GetProperty(name, declaredOnlyBindingFlags[memberType])); if ((object)propertyInfo == null && !declaredOnly) { propertyInfo = Get(inheritedProperties, type, name, () => AccessTools.FindIncludingBaseTypes(type, (Type t) => t.GetProperty(name, AccessTools.all))); } return propertyInfo; } internal MethodBase GetMethodInfo(Type type, string name, Type[] arguments, MemberType memberType = MemberType.Any, bool declaredOnly = false) { MethodBase methodBase = Get(declaredMethods, type, name, arguments, () => type.GetMethod(name, declaredOnlyBindingFlags[memberType], null, arguments, null)); if ((object)methodBase == null && !declaredOnly) { methodBase = Get(inheritedMethods, type, name, arguments, () => AccessTools.Method(type, name, arguments)); } return methodBase; } } internal static class PatchArgumentExtensions { private static HarmonyArgument[] AllHarmonyArguments(object[] attributes) { return (from attr in attributes select (attr.GetType().Name != "HarmonyArgument") ? null : AccessTools.MakeDeepCopy<HarmonyArgument>(attr) into harg where harg != null select harg).ToArray(); } private static HarmonyArgument GetArgumentAttribute(this ParameterInfo parameter) { return AllHarmonyArguments(parameter.GetCustomAttributes(inherit: false)).FirstOrDefault(); } private static HarmonyArgument[] GetArgumentAttributes(this MethodInfo method) { if ((object)method == null || method is DynamicMethod) { return null; } return AllHarmonyArguments(method.GetCustomAttributes(inherit: false)); } private static HarmonyArgument[] GetArgumentAttributes(this Type type) { return AllHarmonyArguments(type.GetCustomAttributes(inherit: false)); } private static string GetOriginalArgumentName(this ParameterInfo parameter, string[] originalParameterNames) { HarmonyArgument argumentAttribute = parameter.GetArgumentAttribute(); if (argumentAttribute == null) { return null; } if (!string.IsNullOrEmpty(argumentAttribute.OriginalName)) { return argumentAttribute.OriginalName; } if (argumentAttribute.Index >= 0 && argumentAttribute.Index < originalParameterNames.Length) { return originalParameterNames[argumentAttribute.Index]; } return null; } private static string GetOriginalArgumentName(HarmonyArgument[] attributes, string name, string[] originalParameterNames) { if (((attributes != null && attributes.Length != 0) ? 1 : 0) <= (false ? 1 : 0)) { return null; } HarmonyArgument harmonyArgument = attributes.SingleOrDefault((HarmonyArgument p) => p.NewName == name); if (harmonyArgument == null) { return null; } if (!string.IsNullOrEmpty(harmonyArgument.OriginalName)) { return harmonyArgument.OriginalName; } if (originalParameterNames != null && harmonyArgument.Index >= 0 && harmonyArgument.Index < originalParameterNames.Length) { return originalParameterNames[harmonyArgument.Index]; } return null; } private static string GetOriginalArgumentName(this MethodInfo method, string[] originalParameterNames, string name) { string originalArgumentName = GetOriginalArgumentName(((object)method != null) ? method.GetArgumentAttributes() : null, name, originalParameterNames); if (originalArgumentName != null) { return originalArgumentName; } object attributes; if ((object)method == null) { attributes = null; } else { Type? declaringType = method.DeclaringType; attributes = (((object)declaringType != null) ? declaringType.GetArgumentAttributes() : null); } originalArgumentName = GetOriginalArgumentName((HarmonyArgument[])attributes, name, originalParameterNames); if (originalArgumentName != null) { return originalArgumentName; } return name; } internal static int GetArgumentIndex(this MethodInfo patch, string[] originalParameterNames, ParameterInfo patchParam) { if (patch is DynamicMethod) { return Array.IndexOf<string>(originalParameterNames, patchParam.Name); } string originalArgumentName = patchParam.GetOriginalArgumentName(originalParameterNames); if (originalArgumentName != null) { return Array.IndexOf(originalParameterNames, originalArgumentName); } originalArgumentName = patch.GetOriginalArgumentName(originalParameterNames, patchParam.Name); if (originalArgumentName != null) { return Array.IndexOf(originalParameterNames, originalArgumentName); } return -1; } } internal static class PatchFunctions { internal static List<MethodInfo> GetSortedPatchMethods(MethodBase original, Patch[] patches, bool debug) { return new PatchSorter(patches, debug).Sort(original); } internal static Patch[] GetSortedPatchMethodsAsPatches(MethodBase original, Patch[] patches, bool debug) { return new PatchSorter(patches, debug).SortAsPatches(original); } internal static MethodInfo UpdateWrapper(MethodBase original, PatchInfo patchInfo) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown MethodPatcher methodPatcher = original.GetMethodPatcher(); DynamicMethodDefinition val = methodPatcher.PrepareOriginal(); if (val != null) { ILContext ctx = new ILContext(val.Definition); HarmonyManipulator.Manipulate(original, patchInfo, ctx); } try { return methodPatcher.DetourTo((val != null) ? val.Generate() : null) as MethodInfo; } catch (Exception ex) { object body; if (val == null) { body = null; } else { MethodDefinition definition = val.Definition; body = ((definition != null) ? definition.Body : null); } throw HarmonyException.Create(ex, (MethodBody)body); } } internal static MethodInfo ReversePatch(HarmonyMethod standin, MethodBase original, MethodInfo postTranspiler, MethodInfo postManipulator) { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown if (standin == null) { throw new ArgumentNullException("standin"); } if ((object)standin.method == null) { throw new ArgumentNullException("standin", "standin.method is NULL"); } bool debug = standin.debug.GetValueOrDefault(); List<MethodInfo> transpilers = new List<MethodInfo>(); List<MethodInfo> ilmanipulators = new List<MethodInfo>(); if (standin.reversePatchType == HarmonyReversePatchType.Snapshot) { Patches patchInfo = Harmony.GetPatchInfo(original); transpilers.AddRange(GetSortedPatchMethods(original, patchInfo.Transpilers.ToArray(), debug)); ilmanipulators.AddRange(GetSortedPatchMethods(original, patchInfo.ILManipulators.ToArray(), debug)); } if ((object)postTranspiler != null) { transpilers.Add(postTranspiler); } if ((object)postManipulator != null) { ilmanipulators.Add(postManipulator); } Logger.Log(Logger.LogChannel.Info, delegate { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Reverse patching " + standin.method.FullDescription() + " with " + original.FullDescription()); PrintInfo(stringBuilder, transpilers, "Transpiler"); PrintInfo(stringBuilder, ilmanipulators, "Manipulators"); return stringBuilder.ToString(); }, debug); MethodBody patchBody = null; ILHook val = new ILHook((MethodBase)standin.method, (Manipulator)delegate(ILContext ctx) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) if (original is MethodInfo methodInfo2) { patchBody = ctx.Body; MethodPatcher methodPatcher = methodInfo2.GetMethodPatcher(); DynamicMethodDefinition val2 = methodPatcher.CopyOriginal(); if (val2 == null) { throw new NullReferenceException("Cannot reverse patch " + methodInfo2.FullDescription() + ": method patcher (" + methodPatcher.GetType().FullDescription() + ") can't copy original method body"); } ILManipulator iLManipulator = new ILManipulator(val2.Definition.Body, debug); ctx.Body.Variables.Clear(); Enumerator<VariableDefinition> enumerator2 = iLManipulator.Body.Variables.GetEnumerator(); try { while (enumerator2.MoveNext()) { VariableDefinition current2 = enumerator2.Current; ctx.Body.Variables.Add(new VariableDefinition(ctx.Module.ImportReference(((VariableReference)current2).VariableType))); } } finally { ((IDisposable)enumerator2).Dispose(); } foreach (MethodInfo item in transpilers) { iLManipulator.AddTranspiler(item); } iLManipulator.WriteTo(ctx.Body, standin.method); HarmonyManipulator.ApplyManipulators(ctx, original, ilmanipulators, null); Instruction val3 = null; foreach (Instruction item2 in ((IEnumerable<Instruction>)ctx.Instrs).Where((Instruction i) => i.OpCode == OpCodes.Ret)) { if (val3 == null) { val3 = ctx.IL.Create(OpCodes.Ret); } item2.OpCode = OpCodes.Br; item2.Operand = val3; } if (val3 != null) { ctx.IL.Append(val3); } Logger.Log(Logger.LogChannel.IL, () => "Generated reverse patcher (" + ((MemberReference)ctx.Method).FullName + "):\n" + ctx.Body.ToILDasmString(), debug); } }, new ILHookConfig { ManualApply = true }); try { val.Apply(); } catch (Exception ex) { throw HarmonyException.Create(ex, patchBody); } MethodInfo methodInfo = val.GetCurrentTarget() as MethodInfo; PatchTools.RememberObject(standin.method, methodInfo); return methodInfo; static void PrintInfo(StringBuilder sb, ICollection<MethodInfo> methods, string name) { if (methods.Count <= 0) { return; } sb.AppendLine(name + ":"); foreach (MethodInfo method in methods) { sb.AppendLine(" * " + method.FullDescription()); } } } internal static IEnumerable<CodeInstruction> ApplyTranspilers(MethodBase methodBase, ILGenerator generator, int maxTranspilers = 0) { MethodPatcher methodPatcher = methodBase.GetMethodPatcher(); DynamicMethodDefinition val = methodPatcher.CopyOriginal(); if (val == null) { throw new NullReferenceException("Cannot reverse patch " + methodBase.FullDescription() + ": method patcher (" + methodPatcher.GetType().FullDescription() + ") can't copy original method body"); } ILManipulator iLManipulator = new ILManipulator(val.Definition.Body, debug: false); PatchInfo patchInfo = methodBase.GetPatchInfo(); if (patchInfo != null) { List<MethodInfo> sortedPatchMethods = GetSortedPatchMethods(methodBase, patchInfo.transpilers, debug: false); for (int i = 0; i < maxTranspilers && i < sortedPatchMethods.Count; i++) { iLManipulator.AddTranspiler(sortedPatchMethods[i]); } } return iLManipulator.GetInstructions(generator, methodBase); } internal static void UnpatchConditional(Func<Patch, bool> executionCondition) { foreach (MethodBase item in PatchProcessor.GetAllPatchedMethods().ToList()) { bool num = item.HasMethodBody(); Patches patchInfo2 = PatchProcessor.GetPatchInfo(item); PatchProcessor patchProcessor = new PatchProcessor(null, item); if (num) { patchInfo2.Postfixes.DoIf(executionCondition, delegate(Patch patchInfo) { patchProcessor.Unpatch(patchInfo.PatchMethod); }); patchInfo2.Prefixes.DoIf(executionCondition, delegate(Patch patchInfo) { patchProcessor.Unpatch(patchInfo.PatchMethod); }); } patchInfo2.ILManipulators.DoIf(executionCondition, delegate(Patch patchInfo) { patchProcessor.Unpatch(patchInfo.PatchMethod); }); patchInfo2.Transpilers.DoIf(executionCondition, delegate(Patch patchInfo) { patchProcessor.Unpatch(patchInfo.PatchMethod); }); if (num) { patchInfo2.Finalizers.DoIf(executionCondition, delegate(Patch patchInfo) { patchProcessor.Unpatch(patchInfo.PatchMethod); }); } } } } internal class PatchJobs<T> { internal class Job { internal MethodBase original; internal T replacement; internal List<HarmonyMethod> prefixes = new List<HarmonyMethod>(); internal List<HarmonyMethod> postfixes = new List<HarmonyMethod>(); internal List<HarmonyMethod> transpilers = new List<HarmonyMethod>(); internal List<HarmonyMethod> finalizers = new List<HarmonyMethod>(); internal List<HarmonyMethod> ilmanipulators = new List<HarmonyMethod>(); internal void AddPatch(AttributePatch patch) { HarmonyPatchType? type = patch.type; if (type.HasValue) { switch (type.GetValueOrDefault()) { case HarmonyPatchType.Prefix: prefixes.Add(patch.info); break; case HarmonyPatchType.Postfix: postfixes.Add(patch.info); break; case HarmonyPatchType.Transpiler: transpilers.Add(patch.info); break; case HarmonyPatchType.Finalizer: finalizers.Add(patch.info); break; case HarmonyPatchType.ILManipulator: ilmanipulators.Add(patch.info); break; case HarmonyPatchType.ReversePatch: break; } } } } internal Dictionary<MethodBase, Job> state = new Dictionary<MethodBase, Job>(); internal Job GetJob(MethodBase method) { if ((object)method == null) { return null; } if (!state.TryGetValue(method, out var value)) { value = new Job { original = method }; state[method] = value; } return value; } internal List<Job> GetJobs() { return state.Values.Where((Job job) => job.prefixes.Count + job.postfixes.Count + job.transpilers.Count + job.finalizers.Count + job.ilmanipulators.Count > 0).ToList(); } internal List<T> GetReplacements() { return state.Values.Select((Job job) => job.replacement).ToList(); } } internal class AttributePatch { private static readonly HarmonyPatchType[] allPatchTypes = new HarmonyPatchType[6] { HarmonyPatchType.Prefix, HarmonyPatchType.Postfix, HarmonyPatchType.Transpiler, HarmonyPatchType.Finalizer, HarmonyPatchType.ReversePatch, HarmonyPatchType.ILManipulator }; internal HarmonyMethod info; internal HarmonyPatchType? type; private static readonly string harmonyAttributeName = typeof(HarmonyAttribute).FullName; internal static IEnumerable<AttributePatch> Create(MethodInfo patch, bool collectIncomplete = false) { if ((object)patch == null) { throw new NullReferenceException("Patch method cannot be null"); } object[] customAttributes = patch.GetCustomAttributes(inherit: true); string name = patch.Name; HarmonyPatchType? type = GetPatchType(name, customAttributes); if (!type.HasValue) { return Enumerable.Empty<AttributePatch>(); } if (type != HarmonyPatchType.ReversePatch && !patch.IsStatic) { throw new ArgumentException("Patch method " + patch.FullDescription() + " must be static"); } List<HarmonyMethod> list = (from attr in customAttributes where attr.GetType().BaseType.FullName == harmonyAttributeName select AccessTools.Field(attr.GetType(), "info").GetValue(attr) into harmonyInfo select AccessTools.MakeDeepCopy<HarmonyMethod>(harmonyInfo)).ToList(); List<HarmonyMethod> list2 = new List<HarmonyMethod>(); ILookup<bool, HarmonyMethod> lookup = list.ToLookup((HarmonyMethod m) => IsComplete(m, collectIncomplete)); List<HarmonyMethod> incomplete = lookup[false].ToList(); HarmonyMethod info = HarmonyMethod.Merge(incomplete); List<HarmonyMethod> list3 = lookup[true].Where((HarmonyMethod m) => !Same(m, info)).ToList(); if (list3.Count > 1) { list2.AddRange(list3.Select((HarmonyMethod m) => HarmonyMethod.Merge(incomplete.AddItem(m)))); } else { list2.Add(HarmonyMethod.Merge(list)); } foreach (HarmonyMethod item in list2) { item.method = patch; } return list2.Select((HarmonyMethod i) => new AttributePatch { info = i, type = type }).ToList(); static bool IsComplete(HarmonyMethod m, bool collectIncomplete) { if (collectIncomplete || (object)m.GetDeclaringType() != null) { return m.methodName != null; } return false; } static bool Same(HarmonyMethod m1, HarmonyMethod m2) { if ((object)m1.GetDeclaringType() == m2.GetDeclaringType() && m1.methodName == m2.methodName) { return m1.GetArgumentList().SequenceEqual(m2.GetArgumentList()); } return false; } } private static HarmonyPatchType? GetPatchType(string methodName, object[] allAttributes) { HashSet<string> hashSet = new HashSet<string>(from attr in allAttributes select attr.GetType().FullName into name where name.StartsWith("Harmony") select name); HarmonyPatchType? result = null; HarmonyPatchType[] array = allPatchTypes; for (int i = 0; i < array.Length; i++) { HarmonyPatchType value = array[i]; string text = value.ToString(); if (text == methodName || hashSet.Contains("HarmonyLib.Harmony" + text)) { result = value; break; } } return result; } } internal class PatchSorter { private class PatchSortingWrapper : IComparable { internal readonly HashSet<PatchSortingWrapper> after; internal readonly HashSet<PatchSortingWrapper> before; internal readonly Patch innerPatch; internal PatchSortingWrapper(Patch patch) { innerPatch = patch; before = new HashSet<PatchSortingWrapper>(); after = new HashSet<PatchSortingWrapper>(); } public int CompareTo(object obj) { return PatchInfoSerialization.PriorityComparer((obj as PatchSortingWrapper)?.innerPatch, innerPatch.index, innerPatch.priority); } public override bool Equals(object obj) { if (obj is PatchSortingWrapper patchSortingWrapper) { return (object)innerPatch.PatchMethod == patchSortingWrapper.innerPatch.PatchMethod; } return false; } public override int GetHashCode() { return innerPatch.PatchMethod.GetHashCode(); } internal void AddBeforeDependency(IEnumerable<PatchSortingWrapper> dependencies) { foreach (PatchSortingWrapper dependency in dependencies) { before.Add(dependency); dependency.after.Add(this); } } internal void AddAfterDependency(IEnumerable<PatchSortingWrapper> dependencies) { foreach (PatchSortingWrapper dependency in dependencies) { after.Add(dependency); dependency.before.Add(this); } } internal void RemoveAfterDependency(PatchSortingWrapper afterNode) { after.Remove(afterNode); afterNode.before.Remove(this); } internal void RemoveBeforeDependency(PatchSortingWrapper beforeNode) { before.Remove(beforeNode); beforeNode.after.Remove(this); } } internal class PatchDetailedComparer : IEqualityComparer<Patch> { public bool Equals(Patch x, Patch y) { if (y != null && x != null && x.owner == y.owner && (object)x.PatchMethod == y.PatchMethod && x.index == y.index && x.priority == y.priority && x.before.Length == y.before.Length && x.after.Length == y.after.Length && x.before.All(((IEnumerable<string>)y.before).Contains<string>)) { return x.after.All(((IEnumerable<string>)y.after).Contains<string>); } return false; } public int GetHashCode(Patch obj) { return obj.GetHashCode(); } } private List<PatchSortingWrapper> patches; private HashSet<PatchSortingWrapper> handledPatches; private List<PatchSortingWrapper> result; private List<PatchSortingWrapper> waitingList; internal Patch[] sortedPatchArray; private readonly bool debug; internal PatchSorter(Patch[] patches, bool debug = false) { this.patches = patches.Select((Patch x) => new PatchSortingWrapper(x)).ToList(); this.debug = debug; foreach (PatchSortingWrapper node in this.patches) { node.AddBeforeDependency(this.patches.Where((PatchSortingWrapper x) => node.innerPatch.before.Contains(x.innerPatch.owner))); node.AddAfterDependency(this.patches.Where((PatchSortingWrapper x) => node.innerPatch.after.Contains(x.innerPatch.owner))); } this.patches.Sort(); } internal List<MethodInfo> Sort(MethodBase original) { return (from x in SortAsPatches(original) select x.GetMethod(original)).ToList(); } internal Patch[] SortAsPatches(MethodBase original) { if (sortedPatchArray != null) { return sortedPatchArray; } handledPatches = new HashSet<PatchSortingWrapper>(); waitingList = new List<PatchSortingWrapper>(); result = new List<PatchSortingWrapper>(patches.Count); Queue<PatchSortingWrapper> queue = new Queue<PatchSortingWrapper>(patches); while (queue.Count != 0) { foreach (PatchSortingWrapper item in queue) { if (item.after.All((PatchSortingWrapper x) => handledPatches.Contains(x))) { AddNodeToResult(item); if (item.before.Count != 0) { ProcessWaitingList(); } } else { waitingList.Add(item); } } CullDependency(); queue = new Queue<PatchSortingWrapper>(waitingList); waitingList.Clear(); } sortedPatchArray = result.Select((PatchSortingWrapper x) => x.innerPatch).ToArray(); handledPatches = null; waitingList = null; patches = null; return sortedPatchArray; } internal bool ComparePatchLists(Patch[] patches) { if (sortedPatchArray == null) { Sort(null); } if (patches != null && sortedPatchArray.Length == patches.Length) { return sortedPatchArray.All((Patch x) => patches.Contains(x, new PatchDetailedComparer())); } return false; } private void CullDependency() { for (int i = waitingList.Count - 1; i >= 0; i--) { foreach (PatchSortingWrapper afterNode in waitingList[i].after) { if (!handledPatches.Contains(afterNode)) { waitingList[i].RemoveAfterDependency(afterNode); Logger.Log(Logger.LogChannel.Debug, delegate { string text = afterNode.innerPatch.PatchMethod.FullDescription(); string text2 = waitingList[i].innerPatch.PatchMethod.FullDescription(); return "Breaking dependence between " + text + " and " + text2; }, debug); return; } } } } private void ProcessWaitingList() { int num = waitingList.Count; int num2 = 0; while (num2 < num) { PatchSortingWrapper patchSortingWrapper = waitingList[num2]; if (patchSortingWrapper.after.All(handledPatches.Contains)) { waitingList.Remove(patchSortingWrapper); AddNodeToResult(patchSortingWrapper); num--; num2 = 0; } else { num2++; } } } private void AddNodeToResult(PatchSortingWrapper node) { result.Add(node); handledPatches.Add(node); } } internal static class PatchTools { [ThreadStatic] private static Dictionary<object, object> objectReferences; internal static void RememberObject(object key, object value) { if (objectReferences == null) { objectReferences = new Dictionary<object, object>(); } objectReferences[key] = value; } internal static MethodInfo GetPatchMethod(Type patchType, string attributeName) { MethodInfo methodInfo = patchType.GetMethods(AccessTools.all).FirstOrDefault((MethodInfo m) => m.GetCustomAttributes(inherit: true).Any((object a) => a.GetType().FullName == attributeName)); if ((object)methodInfo == null) { string name = attributeName.Replace("HarmonyLib.Harmony", ""); methodInfo = patchType.GetMethod(name, AccessTools.all); } return methodInfo; } internal static AssemblyBuilder DefineDynamicAssembly(string name) { AssemblyName assemblyName = new AssemblyName(name); return AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); } internal static List<AttributePatch> GetPatchMethods(Type type, bool collectIncomplete = false) { return (from attributePatch in AccessTools.GetDeclaredMethods(type).SelectMany((MethodInfo m) => AttributePatch.Create(m, collectIncomplete)) where attributePatch != null select attributePatch).ToList(); } internal static MethodBase GetOriginalMethod(this HarmonyMethod attr) { try { MethodType? methodType = attr.methodType; if (methodType.HasValue) { switch (methodType.GetValueOrDefault()) { case MethodType.Normal: if (attr.methodName == null) { return null; } return AccessTools.DeclaredMethod(attr.GetDeclaringType(), attr.methodName, attr.argumentTypes); case MethodType.Getter: if (attr.methodName == null) { return null; } return AccessTools.DeclaredProperty(attr.GetDeclaringType(), attr.methodName).GetGetMethod(nonPublic: true); case MethodType.Setter: if (attr.methodName == null) { return null; } return AccessTools.DeclaredProperty(attr.GetDeclaringType(), attr.methodName).GetSetMethod(nonPublic: true); case MethodType.Constructor: return AccessTools.DeclaredConstructor(attr.GetDeclaringType(), attr.argumentTypes); case MethodType.StaticConstructor: return AccessTools.GetDeclaredConstructors(attr.GetDeclaringType()).FirstOrDefault((ConstructorInfo c) => c.IsStatic); case MethodType.Enumerator: if (attr.methodName == null) { return null; } return AccessTools.EnumeratorMoveNext(AccessTools.DeclaredMethod(attr.GetDeclaringType(), attr.methodName, attr.argumentTypes)); } } } catch (AmbiguousMatchException ex) { throw new HarmonyException("Ambiguous match for HarmonyMethod[" + attr.Description() + "]", ex.InnerException ?? ex); } return null; } } public enum MethodType { Normal, Getter, Setter, Constructor, StaticConstructor, Enumerator } public enum ArgumentType { Normal, Ref, Out, Pointer } public enum HarmonyPatchType { All, Prefix, Postfix, Transpiler, Finalizer, ReversePatch, ILManipulator } public enum HarmonyReversePatchType { Original, Snapshot } public enum MethodDispatchType { VirtualCall, Call } [MeansImplicitUse] public class HarmonyAttribute : Attribute { public HarmonyMethod info = new HarmonyMethod(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Delegate, AllowMultiple = true)] public class HarmonyPatch : HarmonyAttribute { public HarmonyPatch() { } public HarmonyPatch(Type declaringType) { info.declaringType = declaringType; } public HarmonyPatch(Type declaringType, Type[] argumentTypes) { info.declaringType = declaringType; info.argumentTypes = argumentTypes; } public HarmonyPatch(Type declaringType, string methodName) { info.declaringType = declaringType; info.methodName = methodName; } public HarmonyPatch(Type declaringType, string methodName, params Type[] argumentTypes) { info.declaringType = declaringType; info.methodName = methodName; info.argumentTypes = argumentTypes; } public HarmonyPatch(Type declaringType, string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.declaringType = declaringType; info.methodName = methodName; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(string assemblyQualifiedDeclaringType, string methodName) { info.assemblyQualifiedDeclaringTypeName = assemblyQualifiedDeclaringType; info.methodName = methodName; } public HarmonyPatch(string assemblyQualifiedDeclaringType, string methodName, MethodType methodType, Type[] argumentTypes = null, ArgumentType[] argumentVariations = null) { info.assemblyQualifiedDeclaringTypeName = assemblyQualifiedDeclaringType; info.methodName = methodName; info.methodType = methodType; if (argumentTypes != null) { ParseSpecialArguments(argumentTypes, argumentVariations); } } public HarmonyPatch(Type declaringType, MethodType methodType) { info.declaringType = declaringType; info.methodType = methodType; } public HarmonyPatch(Type declaringType, MethodType methodType, params Type[] argumentTypes) { info.declaringType = declaringType; info.methodType = methodType; info.argumentTypes = argumentTypes; } public HarmonyPatch(Type declaringType, MethodType methodType, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.declaringType = declaringType; info.methodType = methodType; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(Type declaringType, string methodName, MethodType methodType) { info.declaringType = declaringType; info.methodName = methodName; info.methodType = methodType; } public HarmonyPatch(string methodName) { info.methodName = methodName; } public HarmonyPatch(string methodName, params Type[] argumentTypes) { info.methodName = methodName; info.argumentTypes = argumentTypes; } public HarmonyPatch(string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.methodName = methodName; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(string methodName, MethodType methodType) { info.methodName = methodName; info.methodType = methodType; } public HarmonyPatch(MethodType methodType) { info.methodType = methodType; } public HarmonyPatch(MethodType methodType, params Type[] argumentTypes) { info.methodType = methodType; info.argumentTypes = argumentTypes; } public HarmonyPatch(MethodType methodType, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.methodType = methodType; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(Type[] argumentTypes) { info.argumentTypes = argumentTypes; } public HarmonyPatch(Type[] argumentTypes, ArgumentType[] argumentVariations) { ParseSpecialArguments(argumentTypes, argumentVariations); } private void ParseSpecialArguments(Type[] argumentTypes, ArgumentType[] argumentVariations) { if (argumentVariations == null || argumentVariations.Length == 0) { info.argumentTypes = argumentTypes; return; } if (argumentTypes.Length < argumentVariations.Length) { throw new ArgumentException("argumentVariations contains more elements than argumentTypes", "argumentVariations"); } List<Type> list = new List<Type>(); for (int i = 0; i < argumentTypes.Length; i++) { Type type = argumentTypes[i]; switch (argumentVariations[i]) { case ArgumentType.Ref: case ArgumentType.Out: type = type.MakeByRefType(); break; case ArgumentType.Pointer: type = type.MakePointerType(); break; } list.Add(type); } info.argumentTypes = list.ToArray(); } } [AttributeUsage(AttributeTargets.Delegate, AllowMultiple = true)] public class HarmonyDelegate : HarmonyPatch { public HarmonyDelegate(Type declaringType) : base(declaringType) { } public HarmonyDelegate(Type declaringType, Type[] argumentTypes) : base(declaringType, argumentTypes) { } public HarmonyDelegate(Type declaringType, string methodName) : base(declaringType, methodName) { } public HarmonyDelegate(Type declaringType, string methodName, params Type[] argumentTypes) : base(declaringType, methodName, argumentTypes) { } public HarmonyDelegate(Type declaringType, string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) : base(declaringType, methodName, argumentTypes, argumentVariations) { } public HarmonyDelegate(Type declaringType, MethodDispatchType methodDispatchType) : base(declaringType, MethodType.Normal) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(Type declaringType, MethodDispatchType methodDispatchType, params Type[] argumentTypes) : base(declaringType, MethodType.Normal, argumentTypes) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(Type declaringType, MethodDispatchType methodDispatchType, Type[] argumentTypes, ArgumentType[] argumentVariations) : base(declaringType, MethodType.Normal, argumentTypes, argumentVariations) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(Type declaringType, string methodName, MethodDispatchType methodDispatchType) : base(declaringType, methodName, MethodType.Normal) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(string methodName) : base(methodName) { } public HarmonyDelegate(string methodName, params Type[] argumentTypes) : base(methodName, argumentTypes) { } public HarmonyDelegate(string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) : base(methodName, argumentTypes, argumentVariations) { } public HarmonyDelegate(string methodName, MethodDispatchType methodDispatchType) : base(methodName, MethodType.Normal) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(MethodDispatchType methodDispatchType) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(MethodDispatchType methodDispatchType, params Type[] argumentTypes) : base(MethodType.Normal, argumentTypes) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(MethodDispatchType methodDispatchType, Type[] argumentTypes, ArgumentType[] argumentVariations) : base(MethodType.Normal, argumentTypes, argumentVariations) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(Type[] argumentTypes) : base(argumentTypes) { } public HarmonyDelegate(Type[] argumentTypes, ArgumentType[] argumentVariations) : base(argumentTypes, argumentVariations) { } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class HarmonyReversePatch : HarmonyAttribute { public HarmonyReversePatch(HarmonyReversePatchType type = HarmonyReversePatchType.Original) { info.reversePatchType = type; } } [AttributeUsage(AttributeTargets.Class)] public class HarmonyPatchAll : HarmonyAttribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyPriority : HarmonyAttribute { public HarmonyPriority(int priority) { info.priority = priority; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyBefore : HarmonyAttribute { public HarmonyBefore(params string[] before) { info.before = before; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyAfter : HarmonyAttribute { public HarmonyAfter(params string[] after) { info.after = after; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyDebug : HarmonyAttribute { public HarmonyDebug() { info.debug = true; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyEmitIL : HarmonyAttribute { public HarmonyEmitIL() { info.debugEmitPath = "./"; } public HarmonyEmitIL(string dir) { info.debugEmitPath = dir; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyWrapSafe : HarmonyAttribute { public HarmonyWrapSafe() { info.wrapTryCatch = true; } } [AttributeUsage(AttributeTargets.Method)] public class HarmonyPrepare : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyCleanup : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyTargetMethod : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyTargetMethods : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyPrefix : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyPostfix : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyTranspiler : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyILManipulator : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyFinalizer : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter, AllowMultiple = true)] public class HarmonyArgument : Attribute { public string OriginalName { get; private set; } public int Index { get; private set; } public string NewName { get; private set; } public HarmonyArgument(string originalName) : this(originalName, null) { } public HarmonyArgument(int index) : this(index, null) { } public HarmonyArgument(string originalName, string newName) { OriginalName = originalName; Index = -1; NewName = newName; } public HarmonyArgument(int index, string name) { OriginalName = null; Index = index; NewName = name; } } public class CodeInstruction { public OpCode opcode; public object operand; public List<Label> labels = new List<Label>(); public List<ExceptionBlock> blocks = new List<ExceptionBlock>(); internal CodeInstruction() { } public CodeInstruction(OpCode opcode, object operand = null) { this.opcode = opcode; this.operand = operand; } public CodeInstruction(CodeInstruction instruction) { opcode = instruction.opcode; operand = instruction.operand; labels = instruction.labels.ToList(); blocks = instruction.blocks.ToList(); } public CodeInstruction Clone() { return new CodeInstruction(this) { labels = new List<Label>(), blocks = new List<ExceptionBlock>() }; } public CodeInstruction Clone(OpCode opcode) { CodeInstruction codeInstruction = Clone(); codeInstruction.opcode = opcode; return codeInstruction; } public CodeInstruction Clone(object operand) { CodeInstruction codeInstruction = Clone(); codeInstruction.operand = operand; return codeInstruction; } public static CodeInstruction Call(Type type, string name, Type[] parameters = null, Type[] generics = null) { MethodInfo methodInfo = AccessTools.Method(type, name, parameters, generics); if ((object)methodInfo == null) { throw new ArgumentException($"No method found for type={type}, name={name}, parameters={parameters.Description()}, generics={generics.Description()}"); } return new CodeInstruction(OpCodes.Call, methodInfo); } public static CodeInstruction Call(string typeColonMethodname, Type[] parameters = null, Type[] generics = null) { MethodInfo methodInfo = AccessTools.Method(typeColonMethodname, parameters, generics); if ((object)methodInfo == null) { throw new ArgumentException("No method found for " + typeColonMethodname + ", parameters=" + parameters.Description() + ", generics=" + generics.Description()); } return new CodeInstruction(OpCodes.Call, methodInfo); } public static CodeInstruction Call(Expression<Action> expression) { return new CodeInstruction(OpCodes.Call, SymbolExtensions.GetMethodInfo(expression)); } public static CodeInstruction Call<T>(Expression<Action<T>> expression) { return new CodeInstruction(OpCodes.Call, SymbolExtensions.GetMethodInfo(expression)); } public static CodeInstruction Call<T, TResult>(Expression<Func<T, TResult>> expression) { return new CodeInstruction(OpCodes.Call, SymbolExtensions.GetMethodInfo(expression)); } public static CodeInstruction Call(LambdaExpression expression) { return new CodeInstruction(OpCodes.Call, SymbolExtensions.GetMethodInfo(expression)); } public static CodeInstruction CallClosure<T>(T closure) where T : Delegate { return Transpilers.EmitDelegate(closure); } public static CodeInstruction LoadField(Type type, string name, bool useAddress = false) { FieldInfo fieldInfo = AccessTools.Field(type, name); if ((object)fieldInfo == null) { throw new ArgumentException($"No field found for {type} and {name}"); } return new CodeInstruction((!useAddress) ? (fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld) : (fieldInfo.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda), fieldInfo); } public static CodeInstruction StoreField(Type type, string name) { FieldInfo fieldInfo = AccessTools.Field(type, name); if ((object)fieldInfo == null) { throw new ArgumentException($"No field found for {type} and {name}"); } return new CodeInstruction(fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo); } public override string ToString() { List<string> list = new List<string>(); foreach (Label label in labels) { list.Add($"Label{label.GetHashCode()}"); } foreach (ExceptionBlock block in blocks) { list.Add("EX_" + block.blockType.ToString().Replace("Block", "")); } string text = ((list.Count > 0) ? (" [" + string.Join(", ", list.ToArray()) + "]") : ""); string text2 = FormatArgument(operand); if (text2.Length > 0) { text2 = " " + text2; } OpCode opCode = opcode; return opCode.ToString() + text2 + text; } internal static string FormatArgument(object argument, string extra = null) { if (argument == null) { return "NULL"; } Type type = argument.GetType(); if (argument is MethodBase member) { return member.FullDescription() + ((extra != null) ? (" " + extra) : ""); } if (argument is FieldInfo fieldInfo) { return fieldInfo.FieldType.FullDescription() + " " + fieldInfo.DeclaringType.FullDescription() + "::" + fieldInfo.Name; } if ((object)type == typeof(Label)) { return $"Label{((Label)argument).GetHashCode()}"; } if ((object)type == typeof(Label[])) { return "Labels" + string.Join(",", ((Label[])argument).Select((Label l) => l.GetHashCode().ToString()).ToArray()); } if ((object)type == typeof(LocalBuilder)) { return $"{((LocalBuilder)argument).LocalIndex} ({((LocalBuilder)argument).LocalType})"; } if ((object)type == typeof(string)) { return argument.ToString().ToLiteral(); } return argument.ToString().Trim(); } } public enum ExceptionBlockType { BeginExceptionBlock, BeginCatchBlock, BeginExceptFilterBlock, BeginFaultBlock, BeginFinallyBlock, EndExceptionBlock } public class ExceptionBlock { public ExceptionBlockType blockType; public Type catchType; public ExceptionBlock(ExceptionBlockType blockType, Type catchType = null) { this.blockType = blockType; this.catchType = catchType ?? typeof(object); } } public class InvalidHarmonyPatchArgumentException : Exception { public MethodBase Original { get; } public MethodInfo Patch { get; } public override string Message => "(" + Patch.FullDescription() + "): " + base.Message; public InvalidHarmonyPatchArgumentException(string message, MethodBase original, MethodInfo patch) : base(message) { Original = original; Patch = patch; } } public class MemberNotFoundException : Exception { public MemberNotFoundException(string message) : base(message) { } } public class Harmony : IDisposable { [Obsolete("Use HarmonyFileLog.Enabled instead")] public static bool DEBUG; public string Id { get; } static Harmony() { StackTraceFixes.Install(); } public Harmony(string id) { if (string.IsNullOrEmpty(id)) { throw new ArgumentException("id cannot be null or empty"); } try { string environmentVariable = Environment.GetEnvironmentVariable("HARMONY_DEBUG"); if (environmentVariable != null && environmentVariable.Length > 0) { environmentVariable = environmentVariable.Trim(); DEBUG = environmentVariable == "1" || bool.Parse(environmentVariable); } } catch { } if (DEBUG) { HarmonyFileLog.Enabled = true; } MethodBase callingMethod = (Logger.IsEnabledFor(Logger.LogChannel.Info) ? AccessTools.GetOutsideCaller() : null); Logger.Log(Logger.LogChannel.Info, delegate { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); Assembly assembly = typeof(Harmony).Assembly; Version version = assembly.GetName().Version; string text = assembly.Location; string text2 = Environment.Version.ToString(); string text3 = Environment.OSVersion.Platform.ToString(); if (string.IsNullOrEmpty(text)) { text = new Uri(assembly.CodeBase).LocalPath; } int size = IntPtr.Size; Platform current = PlatformHelper.Current; stringBuilder.AppendLine($"### Harmony id={id}, version={version}, location={text}, env/clr={text2}, platform={text3}, ptrsize:runtime/env={size}/{current}"); if ((object)callingMethod?.DeclaringType != null) { Assembly assembly2 = callingMethod.DeclaringType.Assembly; text = assembly2.Location; if (string.IsNullOrEmpty(text)) { text = new Uri(assembly2.CodeBase).LocalPath; } stringBuilder.AppendLine("### Started from " + callingMethod.FullDescription() + ", location " + text); stringBuilder.Append($"### At {DateTime.Now:yyyy-MM-dd hh.mm.ss}"); } return stringBuilder.ToString(); }); Id = id; } public void PatchAll() { Assembly assembly = new StackTrace().GetFrame(1).GetMethod().ReflectedType.Assembly; PatchAll(assembly); } public PatchProcessor CreateProcessor(MethodBase original) { return new PatchProcessor(this, original); } public PatchClassProcessor CreateClassProcessor(Type type) { return new PatchClassProcessor(this, type); } public PatchClassProcessor CreateClassProcessor(Type type, bool allowUnannotatedType) { return new PatchClassProcessor(this, type, allowUnannotatedType); } public ReversePatcher CreateReversePatcher(MethodBase original, HarmonyMethod standin) { return new ReversePatcher(this, original, standin); } public void PatchAll(Assembly assembly) { AccessTools.GetTypesFromAssembly(assembly).Do(delegate(Type type) { CreateClassProcessor(type).Patch(); }); } public void PatchAll(Type type) { CreateClassProcessor(type, allowUnannotatedType: true).Patch(); } public MethodInfo Patch(MethodBase original, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null, HarmonyMethod finalizer = null, HarmonyMethod ilmanipulator = null) { PatchProcessor patchProcessor = CreateProcessor(original); patchProcessor.AddPrefix(prefix); patchProcessor.AddPostfix(postfix); patchProcessor.AddTranspiler(transpiler); patchProcessor.AddFinalizer(finalizer); patchProcessor.AddILManipulator(ilmanipulator); return patchProcessor.Patch(); } [Obsolete("Use newer Patch() instead", true)] public MethodInfo Patch(MethodBase original, HarmonyMethod prefix, HarmonyMethod postfix, HarmonyMethod transpiler, HarmonyMethod finalizer) { return Patch(original, prefix, postfix, transpiler, finalizer, null); } public static MethodInfo ReversePatch(MethodBase original, HarmonyMethod standin, MethodInfo transpiler = null, MethodInfo ilmanipulator = null) { return PatchFunctions.ReversePatch(standin, original, transpiler, ilmanipulator); } [Obsolete("Use newer ReversePatch() instead", true)] public static MethodInfo ReversePatch(MethodBase original, HarmonyMethod standin, MethodInfo transpiler) { return PatchFunctions.ReversePatch(standin, original, transpiler, null); } public static void UnpatchID(string harmonyID) { if (string.IsNullOrEmpty(harmonyID)) { throw new ArgumentNullException("harmonyID", "UnpatchID was called with a null or empty harmonyID."); } PatchFunctions.UnpatchConditional((Patch patchInfo) => patchInfo.owner == harmonyID); } void IDisposable.Dispose() { UnpatchSelf(); } public void UnpatchSelf() { UnpatchID(Id); } public static void UnpatchAll() { Logger.Log(Logger.LogChannel.Warn, () => "UnpatchAll has been called - This will remove ALL HARMONY PATCHES."); PatchFunctions.UnpatchConditional((Patch _) => true); } [Obsolete("Use UnpatchSelf() to unpatch the current instance. The functionality to unpatch either other ids or EVERYTHING has been moved the static methods UnpatchID() and UnpatchAll() respectively", true)] public void UnpatchAll(string harmonyID = null) { if (harmonyID == null) { if (HarmonyGlobalSettings.DisallowLegacyGlobalUnpatchAll) { Logger.Log(Logger.LogChannel.Warn, () => "Legacy UnpatchAll has been called AND DisallowLegacyGlobalUnpatchAll=true. Skipping execution of UnpatchAll"); } else { UnpatchAll(); } } else if (harmonyID.Length == 0) { Logger.Log(Logger.LogChannel.Warn, () => "Legacy UnpatchAll was called with harmonyID=\"\" which is an invalid id. Skipping execution of UnpatchAll"); } else { UnpatchID(harmonyID); } } public void Unpatch(MethodBase original, HarmonyPatchType type, string harmonyID = null) { CreateProcessor(original).Unpatch(type, harmonyID); } public void Unpatch(MethodBase original, MethodInfo patch) { CreateProcessor(original).Unpatch(patch); } public static bool HasAnyPatches(string harmonyID) { return (from original in GetAllPatchedMethods() select GetPatchInfo(original)).Any((Patches info) => info.Owners.Contains(harmonyID)); } public static Patches GetPatchInfo(MethodBase method) { return PatchProcessor.GetPatchInfo(method); } public IEnumerable<MethodBase> GetPatchedMethods() { return from original in GetAllPatchedMethods() where GetPatchInfo(original).Owners.Contains(Id) select original; } public static IEnumerable<MethodBase> GetAllPatchedMethods() { return PatchProcessor.GetAllPatchedMethods(); } public static MethodBase GetOriginalMethod(MethodInfo replacement) { if ((object)replacement == null) { throw new ArgumentNullException("replacement"); } return PatchManager.GetOriginal(replacement); } public static MethodBase GetMethodFromStackframe(StackFrame frame) { if (frame == null) { throw new ArgumentNullException("frame"); } return PatchManager.FindReplacement(frame) ?? frame.GetMethod(); } public static Dictionary<string, Version> VersionInfo(out Version currentVersion) { return PatchProcessor.VersionInfo(out currentVersion); } public static Harmony CreateAndPatchAll(Type type, string harmonyInstanceId = null) { Harmony harmony = new Harmony(harmonyInstanceId ?? $"harmony-auto-{Guid.NewGuid()}"); harmony.PatchAll(type); return harmony; } public static Harmony CreateAndPatchAll(Assembly assembly, string harmonyInstanceId = null) { Harmony harmony = new Harmony(harmonyInstanceId ?? $"harmony-auto-{Guid.NewGuid()}"); harmony.PatchAll(assembly); return harmony; } } [Serializable] public class HarmonyException : Exception { private Dictionary<int, CodeInstruction> instructions; private int errorOffset; internal HarmonyException() { } internal HarmonyException(string message) : base(message) { } internal HarmonyException(string message, Exception innerException) : base(message, innerException) { } protected HarmonyException(SerializationInfo serializationInfo, StreamingContext streamingContext) { throw new NotImplementedException(); } internal HarmonyException(Exception innerException, Dictionary<int, CodeInstruction> instructions, int errorOffset) : base("IL Compile Error", innerException) { this.instructions = instructions; this.errorOffset = errorOffset; } internal static Exception Create(Exception ex, MethodBody body) { Match match = Regex.Match(ex.Message.TrimEnd(new char[0]), "Reason: Invalid IL code in.+: IL_(\\d{4}): (.+)$"); if (!match.Success) { return new HarmonyException("IL Compile Error (unknown location)", ex); } Dictionary<int, CodeInstruction> dictionary = ILManipulator.GetInstructions(body) ?? new Dictionary<int, CodeInstruction>(); int num = int.Parse(match.Groups[1].Value, NumberStyles.HexNumber); Regex.Replace(match.Groups[2].Value, " {2,}", " "); if (ex is HarmonyException ex2) { if (dictionary.Count != 0) { ex2.instructions = dictionary; ex2.errorOffset = num; } return ex2; } return new HarmonyException(ex, dictionary, num); } public List<KeyValuePair<int, CodeInstruction>> GetInstructionsWithOffsets() { return instructions.OrderBy((KeyValuePair<int, CodeInstruction> ins) => ins.Key).ToList(); } public List<CodeInstruction> GetInstructions() { return (from ins in instructions orderby ins.Key select ins.Value).ToList(); } public int GetErrorOffset() { return errorOffset; } public int GetErrorIndex() { if (instructions.TryGetValue(errorOffset, out var value)) { return GetInstructions().IndexOf(value); } return -1; } } public static class HarmonyGlobalSettings { public static bool DisallowLegacyGlobalUnpatchAll { get; set; } } public class HarmonyMethod { public MethodInfo method; public Type declaringType; public string methodName; public MethodType? methodType; public Type[] argumentTypes; public int priority = -1; public string[] before; public string[] after; public HarmonyReversePatchType? reversePatchType; public bool? debug; public string debugEmitPath; public bool nonVirtualDelegate; public bool? wrapTryCatch; internal string assemblyQualifiedDeclaringTypeName; public HarmonyMethod() { } private void ImportMethod(MethodInfo theMethod) { method = theMethod; if ((object)method != null) { List<HarmonyMethod> fromMethod = HarmonyMethodExtensions.GetFromMethod(method); if (fromMethod != null) { Merge(fromMethod).CopyTo(this); } } } public HarmonyMethod(MethodInfo method) { if ((object)method == null) { throw new ArgumentNullException("method"); } ImportMethod(method); } public HarmonyMethod(MethodInfo method, int priority = -1, string[] before = null, string[] after = null, bool? debug = null) { if ((object)method == null) { throw new ArgumentNullException("method"); } ImportMethod(method); this.priority = priority; this.before = before; this.after = after; this.debug = debug; } public HarmonyMethod(Type methodType, string methodName, Type[] argumentTypes = null) { MethodInfo methodInfo = AccessTools.Method(methodType, methodName, argumentTypes); if ((object)methodInfo == null) { throw new ArgumentException($"Cannot not find method for type {methodType} and name {methodName} and parameters {argumentTypes?.Description()}"); } ImportMethod(methodInfo); } public static List<string> HarmonyFields() { return (from s in AccessTools.GetFieldNames(typeof(HarmonyMethod)) where s != "method" select s).ToList(); } public static HarmonyMethod Merge(List<HarmonyMethod> attributes) { return Merge((IEnumerable<HarmonyMethod>)attributes); } internal static HarmonyMethod Merge(IEnumerable<HarmonyMethod> attributes) { HarmonyMethod harmonyMethod = new HarmonyMethod(); if (attributes == null) { return harmonyMethod; } Traverse resultTrv = Traverse.Create(harmonyMethod); attributes.Do(delegate(HarmonyMethod attribute) { Traverse trv = Traverse.Create(attribute); HarmonyFields().ForEach(delegate(string f) { object value = trv.Field(f).GetValue(); if (value != null && (f != "priority" || (int)value != -1)) { HarmonyMethodExtensions.SetValue(resultTrv, f, value); } }); }); return harmonyMethod; } public override string ToString() { string result = ""; Traverse trv = Traverse.Create(this); HarmonyFields().ForEach(delegate(string f) { if (result.Length > 0) { result += ", "; } result += $"{f}={trv.Field(f).GetValue()}"; }); return "HarmonyMethod[" + result + "]"; } internal string Description() { string text = (((object)declaringType != null) ? declaringType.FullName : ((assemblyQualifiedDeclaringTypeName != null) ? assemblyQualifiedDeclaringTypeName : "undefined")); string text2 = methodName ?? "undefined"; string text3 = (methodType.HasValue ? methodType.Value.ToString() : "undefined"); string text4 = ((argumentTypes != null) ? argumentTypes.Description() : "undefined"); return "(class=" + text + ", methodname=" + text2 + ", type=" + text3 + ", args=" + text4 + ")"; } internal Type GetDeclaringType() { if ((object)declaringType == null && assemblyQualifiedDeclaringTypeName != null) { declaringType = Type.GetType(assemblyQualifiedDeclaringTypeName, throwOnError: true); } return declaringType; } internal Type[] GetArgumentList() { return argumentTypes ?? EmptyType.NoArgs; } } internal static class EmptyType { internal static readonly Type[] NoArgs = new Type[0]; } public static class HarmonyMethodExtensions { internal static void SetValue(Traverse trv, string name, object val) { if (val != null) { Traverse traverse = trv.Field(name); if (name == "methodType" || name == "reversePatchType") { val = Enum.ToObject(Nullable.GetUnderlyingType(traverse.GetValueType()), (int)val); } traverse.SetValue(val); } } public static void CopyTo(this HarmonyMethod from, HarmonyMethod to) { if (to == null) { return; } Traverse fromTrv = Traverse.Create(from); Traverse toTrv = Traverse.Create(to); HarmonyMethod.HarmonyFields().ForEach(delegate(string f) { object value = fromTrv.Field(f).GetValue(); if (value != null) { SetValue(toTrv, f, value); } }); } public static HarmonyMethod Clone(this HarmonyMethod original) { HarmonyMethod harmonyMethod = new HarmonyMethod(); original.CopyTo(harmonyMethod); return harmonyMethod; } public static HarmonyMethod Merge(this HarmonyMethod master, HarmonyMethod detail) { if (detail == null) { return master; } HarmonyMethod harmonyMethod = new HarmonyMethod(); Traverse resultTrv = Traverse.Create(harmonyMethod); Traverse masterTrv = Traverse.Create(master); Traverse detailTrv = Traverse.Create(detail); HarmonyMethod.HarmonyFields().ForEach(delegate(string f) { object value = masterTrv.Field(f).GetValue(); object value2 = detailTrv.Field(f).GetValue(); if (f != "priority" || (int)value2 != -1) { SetValue(resultTrv, f, value2 ?? value); } }); return harmonyMethod; } private static HarmonyMethod GetHarmonyMethodInfo(object attribute) { FieldInfo field = attribute.GetType().GetField("info", AccessTools.all); if ((object)field == null) { return null; } if (field.FieldType.FullName != typeof(HarmonyMethod).FullName) { return null; } return AccessTools.MakeDeepCopy<HarmonyMethod>(field.GetValue(attribute)); } public static List<HarmonyMethod> GetFromType(Type type) { return (from attr in type.GetCustomAttributes(inherit: true) select GetHarmonyMethodInfo(attr) into info where info != null select info).ToList(); } public static HarmonyMethod GetMergedFromType(Type type) { return HarmonyMethod.Merge(GetFromType(type)); } public static List<HarmonyMethod> GetFromMethod(MethodBase method) { return (from attr in method.GetCustomAttributes(inherit: true) select GetHarmonyMethodInfo(attr) into info where info != null select info).ToList(); } public static HarmonyMethod GetMergedFromMethod(MethodBase method) { return HarmonyMethod.Merge(GetFromMethod(method)); } } public class InlineSignature : ICallSiteGenerator { public class ModifierType { public bool IsOptional; public Type Modifier; public object Type; public override string ToString() { return ((Type is Type type) ? type.FullDescription() : Type?.ToString()) + " mod" + (IsOptional ? "opt" : "req") + "(" + Modifier?.FullDescription() + ")"; } internal TypeReference ToTypeReference(ModuleDefinition module) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if (!IsOptional) { return (TypeReference)new RequiredModifierType(module.ImportReference(Modifier), GetTypeReference(module, Type)); } return (TypeReference)new OptionalModifierType(module.ImportReference(Modifier), GetTypeReference(module, Type)); } } public bool HasThis { get; set; } public bool ExplicitThis { get; set; } public CallingConvention CallingConvention { get; set; } = CallingConvention.Winapi; public List<object> Parameters { get; set; } = new List<object>(); public object ReturnType { get; set; } = typeof(void); public override string ToString() { return ((ReturnType is Type type) ? type.FullDescription() : ReturnType?.ToString()) + " (" + Parameters.Join((object p) => (!(p is Type type2)) ? p?.ToString() : type2.FullDescription()) + ")"; } internal static TypeReference GetTypeReference(ModuleDefinition module, object param) { if (!(param is Type type)) { if (!(param is InlineSignature inlineSignature)) { if (param is ModifierType modifierType) { return modifierType.ToTypeReference(module); } throw new NotSupportedException($"Unsupported inline signature parameter type: {param} ({param?.GetType().FullDescription()})"); } return (TypeReference)(object)inlineSignature.ToFunctionPointer(module); } return module.ImportReference(type); } CallSite ICallSiteGenerator.ToCallSite(ModuleDefinition module) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown CallSite val = new CallSite(GetTypeReference(module, ReturnType)) { HasThis = HasThis, ExplicitThis = ExplicitThis, CallingConvention = (MethodCallingConvention)(byte)((byte)CallingConvention - 1) }; foreach (object parameter in Parameters) { val.Parameters.Add(new ParameterDefinition(GetTypeReference(module, parameter))); } return val; } private FunctionPointerType ToFunctionPointer(ModuleDefinition module) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown FunctionPointerType val = new FunctionPointerType { ReturnType = GetTypeReference(module, ReturnType), HasThis = HasThis, ExplicitThis = ExplicitThis, CallingConvention = (MethodCallingConvention)(byte)((byte)CallingConvention - 1) }; foreach (object parameter in Parameters) { val.Parameters.Add(new ParameterDefinition(GetTypeReference(module, parameter))); } return val; } } internal static class PatchInfoSerialization { private class Binder : SerializationBinder { public override Type BindToType(string assemblyName, string typeName) { Type[] array = new Type[3] { typeof(PatchInfo), typeof(Patch[]), typeof(Patch) }; foreach (Type type in array) { if (typeName == type.FullName) { return type; } } return Type.GetType($"{typeName}, {assemblyName}"); } } internal static byte[] Serialize(this PatchInfo patchInfo) { using MemoryStream memoryStream = new MemoryStream(); new BinaryFormatter().Serialize(memoryStream, patchInfo); return memoryStream.GetBuffer(); } internal static PatchInfo Deserialize(byte[] bytes) { BinaryFormatter obj = new BinaryFormatter { Binder = new Binder() }; MemoryStream serializationStream = new MemoryStream(bytes); return (PatchInfo)obj.Deserialize(serializationStream); } internal static int PriorityComparer(object obj, int index, int priority) { Traverse traverse = Traverse.Create(obj); int value = traverse.Field("priority").GetValue<int>(); int value2 = traverse.Field("index").GetValue<int>(); if (priority != value) { return -priority.CompareTo(value); } return index.CompareTo(value2); } } [Serializable] public class PatchInfo { public Patch[] prefixes = new Patch[0]; public Patch[] postfixes = new Patch[0]; public Patch[] transpilers = new Patch[0]; public Patch[] finalizers = new Patch[0]; public Patch[] ilmanipulators = new Patch[0]; public bool Debugging { get { if (!prefixes.Any((Patch p) => p.debug) && !postfixes.Any((Patch p) => p.debug) && !transpilers.Any((Patch p) => p.debug) && !finalizers.Any((Patch p) => p.debug)) { return ilmanipulators.Any((Patch p) => p.debug); } return true; } } public string[] DebugEmitPaths => (from p in prefixes.Concat(postfixes).Concat(transpilers).Concat(finalizers) .Concat(ilmanipulators) select p.debugEmitPath into p where p != null select p).ToArray(); internal void AddPrefixes(string owner, params HarmonyMethod[] methods) { prefixes = Add(owner, methods, prefixes); } [Obsolete("This method only exists for backwards compatibility since the class is public.")] public void AddPrefix(MethodInfo patch, string owner, int priority, string[] before, string[] after, bool debug) { AddPrefixes(owner, new HarmonyMethod(patch, priority, before, after, debug)); } public void RemovePrefix(string owner) { prefixes = Remove(owner, prefixes); } internal void AddPostfixes(string owner, params HarmonyMethod[] methods) { postfixes = Add(owner, methods, postfixes); } [Obsolete("This method only exists for backwards compatibility since the class is public.")] public void AddPostfix(MethodInfo patch, string owner, int priority, string[] before, string[] after, bool debug) { AddPostfixes(owner, new HarmonyMethod(patch, priority, before, after, debug)); } public void RemovePostfix(string owner) { postfixes = Remove(owner, postfixes); } internal void AddTranspilers(string owner, params HarmonyMethod[] methods) { transpilers = Add(owner, methods, transpilers); } [Obsolete("This method only exists for backwards compatibility since the class is public.")] public void AddTranspiler(MethodInfo patch, string owner, int priority, string[] before, string[] after, bool debug) { AddTranspilers(owner, new HarmonyMethod(patch, priority, before, after, debug)); } public void RemoveTranspiler(string owner) { transpilers = Remove(owner, transpilers); } internal void AddFinalizers(string owner, params HarmonyMethod[] methods) { finalizers = Add(owner, methods, finalizers); } [Obsolete("This method only exists for backwards compatibility since the class is public.")] public void AddFinalizer(MethodInfo patch, string owner, int priority, string[] before, string[] after, bool debug) { AddFinalizers(owner, new HarmonyMethod(patch, priority, before, after, debug)); } public void RemoveFinalizer(string owner) { finalizers = Remove(owner, finalizers); } internal void AddILManipulators(string owner, params HarmonyMethod[] methods) { ilmanipulators = Add(owner, methods, ilmanipulators); } public void RemoveILManipulator(string owner) { ilmanipulators = Remove(owner, ilmanipulators); } public void RemovePatch(MethodInfo patch) { prefixes = prefixes.Where((Patch p) => (object)p.PatchMethod != patch).ToArray(); postfixes = postfixes.Where((Patch p) => (object)p.PatchMethod != patch).ToArray(); transpilers = transpilers.Where((Patch p) => (object)p.PatchMethod != patch).ToArray(); finalizers = finalizers.Where((Patch p) => (object)p.PatchMethod != patch).ToArray(); ilmanipulators = ilmanipulators.Where((Patch p) => (object)p.PatchMethod != patch).ToArray(); } private static Patch[] Add(string owner, HarmonyMethod[] add, Patch[] current) { if (add.Length == 0) { return current; } int initialIndex = current.Length; return current.Concat(add.Where((HarmonyMethod method) => method != null).Select((HarmonyMethod method, int i) => new Patch(method, i + initialIndex, owner))).ToArray(); } private static Patch[] Remove(string owner, Patch[] current) { if (!(owner == "*")) { return current.Where((Patch patch) => patch.owner != owner).ToArray(); } return new Patch[0]; } } [Serializable] public class Patch : IComparable { public readonly int index; public readonly string owner; public readonly int priority; public readonly string[] before; public readonly string[] after; public readonly bool debug; public readonly string debugEmitPath; public readonly bool wrapTryCatch; [NonSerialized] private MethodInfo patchMethod; private int methodToken; private string moduleGUID; public MethodInfo PatchMethod { get { if ((object)patchMethod == null) { Module module = (from a in AppDomain.CurrentDomain.GetAssemblies() where !a.FullName.StartsWith("Microsoft.VisualStudio") select a).SelectMany((Assembly a) => a.GetLoadedModules()).First((Module m) => m.ModuleVersionId.ToString() == moduleGUID); patchMethod = (MethodInfo)module.ResolveMethod(methodToken); } return patchMethod; } set { patchMethod = value; methodToken = patchMethod.MetadataToken; moduleGUID = patchMethod.Module.ModuleVersionId.ToString(); } } public Patch(MethodInfo patch, int index, string owner, int priority, string[] before, string[] after, bool debug) { if (patch is DynamicMethod) { throw new Exception("Cannot directly reference dynamic method \"" + patch.FullDescription() + "\" in Harmony. Use a factory method instead that will return the dynamic method."); } this.index = index; this.owner = owner; this.priority = ((priority == -1) ? 400 : priority); this.before = before ?? new string[0]; this.after = after ?? new string[0]; this.debug = debug; PatchMethod = patch; } public Patch(MethodInfo patch, int index, string owner, int priority, string[] before, string[] after, bool debug, bool wrapTryCatch) { if (patch is DynamicMethod) { throw new Exception("Cannot directly reference dynamic method \"" + patch.FullDescription() + "\" in Harmony. Use a factory method instead that will return the dynamic method."); } this.index = index; this.owner = owner; this.priority = ((priority == -1) ? 400 : priority); this.before = before ?? new string[0]; this.after = after ?? new string[0]; this.debug = debug; this.wrapTryCatch = wrapTryCatch; PatchMethod = patch; } public Patch(MethodInfo patch, int index, string owner, int priority, string[] before, string[] after, bool debug, bool wrapTryCatch, string debugEmitPath) { if (patch is DynamicMethod) { throw new Exception("Cannot directly reference dynamic method \"" + patch.FullDescription() + "\" in Harmony. Use a factory method instead that will return the dynamic method."); } this.index = index; this.owner = owner; this.priority = ((priority == -1) ? 400 : priority); this.before = before ?? new string[0]; this.after = after ?? new string[0]; this.debug = debug; this.debugEmitPath = debugEmitPath; this.wrapTryCatch = wrapTryCatch; PatchMethod = patch; } public Patch(HarmonyMethod method, int index, string owner) : this(method.method, index, owner, method.priority, method.before, method.after, method.debug.GetValueOrDefault(), method.wrapTryCatch.GetValueOrDefault(), method.debugEmitPath) { } public MethodInfo GetMethod(MethodBase original) { MethodInfo methodInfo = PatchMethod; if ((object)methodInfo.ReturnType != typeof(DynamicMethod) && (object)methodInfo.ReturnType != typeof(MethodInfo)) { return methodInfo; } if (!methodInfo.IsStatic) { return methodInfo; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 1) { return methodInfo; } if ((object)parameters[0].ParameterType != typeof(MethodBase)) { return methodInfo; } return methodInfo.Invoke(null, new object[1] { original }) as MethodInfo; } public override bool Equals(object obj) { if (obj != null && obj is Patch) { return (object)PatchMethod == ((Patch)obj).PatchMethod; } return false; } public int CompareTo(object obj) { return PatchInfoSerialization.PriorityComparer(obj, index, priority); } public override int GetHashCode() { return PatchMethod.GetHashCode(); } } public class PatchClassProcessor { private readonly Harmony instance; private readonly Type containerType; private readonly HarmonyMethod containerAttributes; private readonly Dictionary<Type, MethodInfo> auxilaryMethods; private readonly List<AttributePatch> patchMethods; private static readonly List<Type> auxilaryTypes = new List<Type> { typeof(HarmonyPrepare), typeof(HarmonyCleanup), typeof(HarmonyTargetMethod), typeof(HarmonyTargetMethods) }; public PatchClassProcessor(Harmony instance, Type type) : this(instance, type, allowUnannotatedType: false) { } public PatchClassProcessor(Harmony instance, Type type, bool allowUnannotatedType) { if (instance == null) { throw new ArgumentNullException("instance"); } if ((object)type == null) { throw new ArgumentNullException("type"); } this.instance = instance; containerType = type; List<HarmonyMethod> fromType = HarmonyMethodExtensions.GetFromType(type); if (!allowUnannotatedType && (fromType == null || fromType.Count == 0)) { return; } containerAttributes = HarmonyMethod.Merge(fromType); MethodType? methodType = containerAttributes.methodType; if (!methodType.HasValue) { containerAttributes.methodType = MethodType.Normal; } auxilaryMethods = new Dictionary<Type, MethodInfo>(); foreach (Type auxilaryType in auxilaryTypes) { MethodInfo patchMethod = PatchTools.GetPatchMethod(containerType, auxilaryType.FullName); if ((object)patchMethod != null) { auxilaryMethods[auxilaryType] = patchMethod; } } patchMethods = PatchTools.GetPatchMethods(containerType, (object)containerAttributes.GetDeclaringType() != null); foreach (AttributePatch patchMethod2 in patchMethods) { MethodInfo method = patchMethod2.info.method; patchMethod2.info = containerAttributes.Merge(patchMethod2.info); patchMethod2.info.method = method; } } public List<MethodInfo> Patch() { if (containerAttributes == null) { return null; } Exception exception = null; if (!RunMethod<HarmonyPrepare, bool>(defaultIfNotExisting: true, defaultIfFailing: false, null, new object[0])) { RunMethod<HarmonyCleanup>(ref exception, new object[0]); ReportException(exception, null); return new List<MethodInfo>(); } List<MethodInfo> result = new List<MethodInfo>(); MethodBase lastOriginal = null; try { List<MethodBase> bulkMethods = GetBulkMethods(); if (bulkMethods.Count == 1) { lastOriginal = bulkMethods[0]; } ReversePatch(ref lastOriginal); result = ((bulkMethods.Count > 0) ? BulkPatch(bulkMethods, ref lastOriginal) : PatchWithAttributes(ref lastOriginal)); } catch (Exception ex) { exception = ex; } RunMethod<HarmonyCleanup>(ref exception, new object[1] { exception }); ReportException(exception, lastOriginal); return result; } private void ReversePatch(ref MethodBase lastOriginal) { for (int i = 0; i < patchMethods.Count; i++) { AttributePatch attributePatch = patchMethods[i]; if (attributePatch.type == HarmonyPatchType.ReversePatch) { MethodBase originalMethod = attributePatch.info.GetOriginalMethod(); if ((object)originalMethod != null) { lastOriginal = originalMethod; } ReversePatcher reversePatcher = instance.CreateReversePatcher(lastOriginal, attributePatch.info); lock (PatchProcessor.locker) { reversePatcher.Patch(); } } } } private List<MethodInfo> BulkPatch(List<MethodBase> originals, ref MethodBase lastOriginal) { PatchJobs<MethodInfo> patchJobs = new PatchJobs<MethodInfo>(); for (int i = 0; i < originals.Count; i++) { lastOriginal = originals[i]; PatchJobs<MethodInfo>.Job job = patchJobs.GetJob(lastOriginal); foreach (AttributePatch patchMethod in patchMethods) { string text = "You cannot combine TargetMethod, TargetMethods or [HarmonyPatchAll] with individual annotations"; HarmonyMethod info = patchMethod.info; if (info.methodName != null) { throw new ArgumentException(text + " [" + info.methodName + "]"); } if (info.methodType.HasValue && info.methodType.Value != 0) { throw new ArgumentException($"{text} [{info.methodType}]"); } if (info.argumentTypes != null) { throw new ArgumentException(text + " [" + info.argumentTypes.Description() + "]"); } job.AddPatch(patchMethod); } } foreach (PatchJobs<MethodInfo>.Job job2 in patchJobs.GetJobs()) { lastOriginal = job2.original; ProcessPatchJob(job2); } return patchJobs.GetReplacements(); } private List<MethodInfo> PatchWithAttributes(ref MethodBase lastOriginal) { PatchJobs<MethodInfo> patchJobs = new PatchJobs<MethodInfo>(); foreach (AttributePatch patchMethod in patchMethods) { lastOriginal = patchMethod.info.GetOriginalMethod(); if ((object)lastOriginal == null) { throw new ArgumentException("Undefined target method for patch method " + patchMethod.info.method.FullDescription()); } patchJobs.GetJob(lastOriginal).AddPatch(patchMethod); } foreach (PatchJob
BepInEx/core/0Harmony20.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using HarmonyLib.Internal; using HarmonyLib.Internal.Patching; using HarmonyLib.Internal.Util; using HarmonyLib.Tools; using HarmonyXInterop; using JetBrains.Annotations; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Cil; using MonoMod.RuntimeDetour; using MonoMod.Utils; using MonoMod.Utils.Cil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("HarmonyX2Interop")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HarmonyX2Interop")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("69F6541D-A0F5-419D-B0EE-F5017F1D34F3")] [assembly: AssemblyFileVersion("2.0.0.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.0.0")] [module: UnverifiableCode] namespace JetBrains.Annotations { [AttributeUsage(AttributeTargets.All)] internal sealed class UsedImplicitlyAttribute : Attribute { public ImplicitUseKindFlags UseKindFlags { get; } public ImplicitUseTargetFlags TargetFlags { get; } public UsedImplicitlyAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) { } public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) { } public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) { UseKindFlags = useKindFlags; TargetFlags = targetFlags; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter | AttributeTargets.GenericParameter)] internal sealed class MeansImplicitUseAttribute : Attribute { [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; } [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; } public MeansImplicitUseAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) { } public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) { } public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) { UseKindFlags = useKindFlags; TargetFlags = targetFlags; } } [Flags] internal enum ImplicitUseKindFlags { Default = 7, Access = 1, Assign = 2, InstantiatedWithFixedConstructorSignature = 4, InstantiatedNoFixedConstructorSignature = 8 } [Flags] internal enum ImplicitUseTargetFlags { Default = 1, Itself = 1, Members = 2, WithInheritors = 4, WithMembers = 3 } } namespace HarmonyLib { public static class Priority { public const int Last = 0; public const int VeryLow = 100; public const int Low = 200; public const int LowerThanNormal = 300; public const int Normal = 400; public const int HigherThanNormal = 500; public const int High = 600; public const int VeryHigh = 700; public const int First = 800; } public enum MethodType { Normal, Getter, Setter, Constructor, StaticConstructor } public enum ArgumentType { Normal, Ref, Out, Pointer } public enum HarmonyPatchType { All, Prefix, Postfix, Transpiler, Finalizer, ReversePatch } public enum HarmonyReversePatchType { Original, Snapshot } [MeansImplicitUse] public class HarmonyAttribute : Attribute { public HarmonyMethod info = new HarmonyMethod(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class HarmonyPatch : HarmonyAttribute { public HarmonyPatch() { } public HarmonyPatch(Type declaringType) { info.declaringType = declaringType; } public HarmonyPatch(Type declaringType, Type[] argumentTypes) { info.declaringType = declaringType; info.argumentTypes = argumentTypes; } public HarmonyPatch(Type declaringType, string methodName) { info.declaringType = declaringType; info.methodName = methodName; } public HarmonyPatch(Type declaringType, string methodName, params Type[] argumentTypes) { info.declaringType = declaringType; info.methodName = methodName; info.argumentTypes = argumentTypes; } public HarmonyPatch(Type declaringType, string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.declaringType = declaringType; info.methodName = methodName; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(Type declaringType, MethodType methodType) { info.declaringType = declaringType; info.methodType = methodType; } public HarmonyPatch(Type declaringType, MethodType methodType, params Type[] argumentTypes) { info.declaringType = declaringType; info.methodType = methodType; info.argumentTypes = argumentTypes; } public HarmonyPatch(Type declaringType, MethodType methodType, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.declaringType = declaringType; info.methodType = methodType; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(Type declaringType, string methodName, MethodType methodType) { info.declaringType = declaringType; info.methodName = methodName; info.methodType = methodType; } public HarmonyPatch(string methodName) { info.methodName = methodName; } public HarmonyPatch(string methodName, params Type[] argumentTypes) { info.methodName = methodName; info.argumentTypes = argumentTypes; } public HarmonyPatch(string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.methodName = methodName; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(string methodName, MethodType methodType) { info.methodName = methodName; info.methodType = methodType; } public HarmonyPatch(MethodType methodType) { info.methodType = methodType; } public HarmonyPatch(MethodType methodType, params Type[] argumentTypes) { info.methodType = methodType; info.argumentTypes = argumentTypes; } public HarmonyPatch(MethodType methodType, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.methodType = methodType; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(Type[] argumentTypes) { info.argumentTypes = argumentTypes; } public HarmonyPatch(Type[] argumentTypes, ArgumentType[] argumentVariations) { ParseSpecialArguments(argumentTypes, argumentVariations); } private void ParseSpecialArguments(Type[] argumentTypes, ArgumentType[] argumentVariations) { if (argumentVariations == null || argumentVariations.Length == 0) { info.argumentTypes = argumentTypes; return; } if (argumentTypes.Length < argumentVariations.Length) { throw new ArgumentException("argumentVariations contains more elements than argumentTypes", "argumentVariations"); } List<Type> list = new List<Type>(); for (int i = 0; i < argumentTypes.Length; i++) { Type type = argumentTypes[i]; switch (argumentVariations[i]) { case ArgumentType.Ref: case ArgumentType.Out: type = type.MakeByRefType(); break; case ArgumentType.Pointer: type = type.MakePointerType(); break; } list.Add(type); } info.argumentTypes = list.ToArray(); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class HarmonyReversePatch : HarmonyAttribute { public HarmonyReversePatch(HarmonyReversePatchType type = HarmonyReversePatchType.Original) { info.reversePatchType = type; } } [AttributeUsage(AttributeTargets.Class)] public class HarmonyPatchAll : HarmonyAttribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyPriority : HarmonyAttribute { public HarmonyPriority(int priority) { info.priority = priority; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyBefore : HarmonyAttribute { public HarmonyBefore(params string[] before) { info.before = before; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyAfter : HarmonyAttribute { public HarmonyAfter(params string[] after) { info.after = after; } } [AttributeUsage(AttributeTargets.Method)] public class HarmonyPrepare : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyCleanup : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyTargetMethod : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyTargetMethods : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyPrefix : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyPostfix : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyTranspiler : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyFinalizer : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter, AllowMultiple = true)] public class HarmonyArgument : Attribute { public string OriginalName { get; private set; } public int Index { get; private set; } public string NewName { get; private set; } public HarmonyArgument(string originalName) : this(originalName, null) { } public HarmonyArgument(int index) : this(index, null) { } public HarmonyArgument(string originalName, string newName) { OriginalName = originalName; Index = -1; NewName = newName; } public HarmonyArgument(int index, string name) { OriginalName = null; Index = index; NewName = name; } } [AttributeUsage(AttributeTargets.Method)] public class ParameterByRefAttribute : Attribute { public int[] ParameterIndices { get; } public ParameterByRefAttribute(params int[] parameterIndices) { ParameterIndices = parameterIndices; } } public class InvalidHarmonyPatchArgumentException : Exception { public MethodBase Original { get; } public MethodInfo Patch { get; } public override string Message => "(" + Extensions.GetID((MethodBase)Patch, (string)null, (string)null, true, false, false) + "): " + base.Message; public InvalidHarmonyPatchArgumentException(string message, MethodBase original, MethodInfo patch) : base(message) { Original = original; Patch = patch; } } public class MemberNotFoundException : Exception { public MemberNotFoundException(string message) : base(message) { } } public class Harmony { [Obsolete("No longer used, subscribe to Logger.LogChannel.Info")] public static bool DEBUG; [Obsolete("Not supported by HarmonyX", true)] public static bool SELF_PATCHING; public string Id { get; private set; } public Harmony(string id) { if (string.IsNullOrEmpty(id)) { throw new ArgumentException("id cannot be null or empty"); } Logger.Log(Logger.LogChannel.Info, delegate { Assembly assembly = typeof(Harmony).Assembly; Version version = assembly.GetName().Version; string text = assembly.Location; if (string.IsNullOrEmpty(text)) { text = new Uri(assembly.CodeBase).LocalPath; } MethodBase outsideCaller = AccessTools.GetOutsideCaller(); Assembly assembly2 = outsideCaller.DeclaringType?.Assembly; string text2 = assembly2?.Location; if (string.IsNullOrEmpty(text2)) { text2 = (((object)assembly2 != null) ? new Uri(assembly2.CodeBase).LocalPath : string.Empty); } return $"Created Harmony instance id={id}, version={version}, location={text} - Started from {Extensions.GetID(outsideCaller, (string)null, (string)null, true, false, false)} location={text2}"; }); Id = id; } public void PatchAll() { Assembly assembly = new StackTrace().GetFrame(1).GetMethod().ReflectedType.Assembly; PatchAll(assembly); } public PatchProcessor ProcessorForAnnotatedClass(Type type) { List<HarmonyMethod> fromType = HarmonyMethodExtensions.GetFromType(type); if (fromType != null && fromType.Any()) { HarmonyMethod attributes = HarmonyMethod.Merge(fromType); return new PatchProcessor(this, type, attributes); } return null; } public void PatchAll(Assembly assembly) { if ((object)assembly == null) { throw new ArgumentNullException("assembly"); } List<PatchProcessor> list = (from x in assembly.GetTypes().Select(ProcessorForAnnotatedClass) where x != null select x).ToList(); foreach (PatchProcessor item in list) { item.Patch(); } if (list.Count == 0) { Logger.Log(Logger.LogChannel.Warn, () => "Could not find any valid Harmony patches inside of assembly " + assembly.FullName); } } public DynamicMethod Patch(MethodBase original, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null, HarmonyMethod finalizer = null) { PatchProcessor patchProcessor = new PatchProcessor(this, original); patchProcessor.AddPrefix(prefix); patchProcessor.AddPostfix(postfix); patchProcessor.AddTranspiler(transpiler); patchProcessor.AddFinalizer(finalizer); return patchProcessor.Patch().FirstOrDefault(); } public MethodInfo ReversePatch(MethodBase original, HarmonyMethod standin, MethodInfo transpiler = null) { return null; } public ReversePatcher CreateReversePatcher(MethodBase original, MethodInfo standin) { return new ReversePatcher(this, original, standin); } public void UnpatchAll(string harmonyID = null) { foreach (MethodBase item in GetAllPatchedMethods().ToList()) { Patches patchInfo = GetPatchInfo(item); UnpatchAllId(item, patchInfo.Prefixes); UnpatchAllId(item, patchInfo.Postfixes); UnpatchAllId(item, patchInfo.Transpilers); UnpatchAllId(item, patchInfo.Finalizers); } void UnpatchAllId(MethodBase original, IEnumerable<Patch> patches) { foreach (Patch patch in patches) { if (harmonyID == null || patch.owner == harmonyID) { Unpatch(original, patch.patch); } } } } public void Unpatch(MethodBase original, HarmonyPatchType type, string harmonyID = null) { new PatchProcessor(this, original).Unpatch(type, harmonyID); } public void Unpatch(MethodBase original, MethodInfo patch) { new PatchProcessor(this, original).Unpatch(patch); } public static bool HasAnyPatches(string harmonyID) { return GetAllPatchedMethods().Select(GetPatchInfo).Any((Patches info) => info.Owners.Contains(harmonyID)); } public static Patches GetPatchInfo(MethodBase method) { return PatchProcessor.GetPatchInfo(method); } public IEnumerable<MethodBase> GetPatchedMethods() { return from original in GetAllPatchedMethods() where GetPatchInfo(original).Owners.Contains(Id) select original; } public static IEnumerable<MethodBase> GetAllPatchedMethods() { return GlobalPatchState.GetPatchedMethods(); } public static Dictionary<string, Version> VersionInfo(out Version currentVersion) { return PatchProcessor.VersionInfo(out currentVersion); } public void PatchAll(Type type) { if ((object)type == null) { throw new ArgumentNullException("type"); } MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { List<HarmonyMethod> fromMethod = HarmonyMethodExtensions.GetFromMethod(methodInfo); if (fromMethod != null && fromMethod.Any()) { object[] customAttributes = methodInfo.GetCustomAttributes(inherit: true); HarmonyMethod combinedInfo = HarmonyMethod.Merge(fromMethod); List<HarmonyMethod> list = fromMethod.Where(IsMethodComplete).ToList(); if (fromMethod.All((HarmonyMethod x) => (object)x.declaringType != combinedInfo.declaringType && x.methodName != combinedInfo.methodName)) { list.Add(combinedInfo); } List<MethodBase> list2 = new List<MethodBase>(); foreach (HarmonyMethod item in list) { foreach (int item2 in customAttributes.OfType<ParameterByRefAttribute>().SelectMany((ParameterByRefAttribute x) => x.ParameterIndices)) { if (!item.argumentTypes[item2].IsByRef) { item.argumentTypes[item2] = item.argumentTypes[item2].MakeByRefType(); } } if (!item.methodType.HasValue) { item.methodType = MethodType.Normal; } if ((object)item.method == null) { item.method = methodInfo; } MethodBase originalMethod = PatchProcessor.GetOriginalMethod(item); if ((object)originalMethod != null) { list2.Add(originalMethod); } } PatchProcessor patchProcessor = new PatchProcessor(this); foreach (MethodBase item3 in list2) { patchProcessor.AddOriginal(item3); } if (customAttributes.Any((object x) => x is HarmonyPrefix)) { patchProcessor.AddPrefix(new HarmonyMethod(methodInfo)); } if (customAttributes.Any((object x) => x is HarmonyTranspiler)) { patchProcessor.AddTranspiler(new HarmonyMethod(methodInfo)); } if (customAttributes.Any((object x) => x is HarmonyPostfix)) { patchProcessor.AddPostfix(new HarmonyMethod(methodInfo)); } if (customAttributes.Any((object x) => x is HarmonyFinalizer)) { patchProcessor.AddFinalizer(new HarmonyMethod(methodInfo)); } patchProcessor.Patch(); } else if ((Logger.ChannelFilter & Logger.LogChannel.Warn) != 0 && methodInfo.GetCustomAttributes(typeof(HarmonyAttribute), inherit: true).Any()) { Logger.LogText(Logger.LogChannel.Warn, "Method " + methodInfo.FullDescription() + " has an invalid combination of Harmony attributes and will be ignored"); } } static bool IsMethodComplete(HarmonyMethod m) { if ((object)m.declaringType != null) { if (m.methodName == null && m.methodType != MethodType.Constructor) { return m.methodType == MethodType.StaticConstructor; } return true; } return false; } } public static Harmony CreateAndPatchAll(Type type, string harmonyInstanceId = null) { Harmony harmony = new Harmony(harmonyInstanceId ?? $"harmony-auto-{Guid.NewGuid()}"); harmony.PatchAll(type); return harmony; } public static Harmony CreateAndPatchAll(Assembly assembly, string harmonyInstanceId = null) { Harmony harmony = new Harmony(harmonyInstanceId ?? $"harmony-auto-{Guid.NewGuid()}"); harmony.PatchAll(assembly); return harmony; } } public class HarmonyMethod { public MethodInfo method; public Type declaringType; public string methodName; public MethodType? methodType; public Type[] argumentTypes; public int priority = -1; public string[] before; public string[] after; public HarmonyReversePatchType? reversePatchType; public HarmonyMethod() { } private void ImportMethod(MethodInfo theMethod) { method = theMethod; if ((object)method != null) { List<HarmonyMethod> fromMethod = HarmonyMethodExtensions.GetFromMethod(method); if (fromMethod != null) { Merge(fromMethod).CopyTo(this); } } } public HarmonyMethod(MethodInfo method) { if ((object)method == null) { throw new ArgumentNullException("method"); } ImportMethod(method); } public HarmonyMethod(Type type, string name, Type[] parameters = null) { MethodInfo methodInfo = AccessTools.Method(type, name, parameters); if ((object)methodInfo == null) { throw new ArgumentException($"Cannot not find method for type {type} and name {name} and parameters {parameters?.Description()}"); } ImportMethod(methodInfo); } public static List<string> HarmonyFields() { return (from s in AccessTools.GetFieldNames(typeof(HarmonyMethod)) where s != "method" select s).ToList(); } public static HarmonyMethod Merge(List<HarmonyMethod> attributes) { HarmonyMethod harmonyMethod = new HarmonyMethod(); if (attributes == null) { return harmonyMethod; } Traverse resultTrv = Traverse.Create(harmonyMethod); attributes.ForEach(delegate(HarmonyMethod attribute) { Traverse trv = Traverse.Create(attribute); HarmonyFields().ForEach(delegate(string f) { object value = trv.Field(f).GetValue(); if (value != null) { HarmonyMethodExtensions.SetValue(resultTrv, f, value); } }); }); return harmonyMethod; } public override string ToString() { string result = "HarmonyMethod["; Traverse trv = Traverse.Create(this); HarmonyFields().ForEach(delegate(string f) { result += $"{f}{'='}{trv.Field(f).GetValue()}"; }); return result + "]"; } } public static class HarmonyMethodExtensions { internal static void SetValue(Traverse trv, string name, object val) { if (val != null) { Traverse traverse = trv.Field(name); if (name == "methodType" || name == "reversePatchType") { val = Enum.ToObject(Nullable.GetUnderlyingType(traverse.GetValueType()), (int)val); } traverse.SetValue(val); } } public static void CopyTo(this HarmonyMethod from, HarmonyMethod to) { if (to == null) { return; } Traverse fromTrv = Traverse.Create(from); Traverse toTrv = Traverse.Create(to); HarmonyMethod.HarmonyFields().ForEach(delegate(string f) { object value = fromTrv.Field(f).GetValue(); if (value != null) { SetValue(toTrv, f, value); } }); } public static HarmonyMethod Clone(this HarmonyMethod original) { HarmonyMethod harmonyMethod = new HarmonyMethod(); original.CopyTo(harmonyMethod); return harmonyMethod; } public static HarmonyMethod Merge(this HarmonyMethod master, HarmonyMethod detail) { if (detail == null) { return master; } HarmonyMethod harmonyMethod = new HarmonyMethod(); Traverse resultTrv = Traverse.Create(harmonyMethod); Traverse masterTrv = Traverse.Create(master); Traverse detailTrv = Traverse.Create(detail); HarmonyMethod.HarmonyFields().ForEach(delegate(string f) { object value = masterTrv.Field(f).GetValue(); object value2 = detailTrv.Field(f).GetValue(); SetValue(resultTrv, f, value2 ?? value); }); return harmonyMethod; } private static HarmonyMethod GetHarmonyMethodInfo(object attribute) { FieldInfo field = attribute.GetType().GetField("info", AccessTools.all); if ((object)field == null) { return null; } if (field.FieldType.Name != "HarmonyMethod") { return null; } return AccessTools.MakeDeepCopy<HarmonyMethod>(field.GetValue(attribute)); } public static List<HarmonyMethod> GetFromType(Type type) { if ((object)type == null) { throw new ArgumentNullException("type"); } return (from attr in type.GetCustomAttributes(inherit: true) select GetHarmonyMethodInfo(attr) into info where info != null select info).ToList(); } public static HarmonyMethod GetMergedFromType(Type type) { return HarmonyMethod.Merge(GetFromType(type)); } public static HarmonyMethod GetMergedFromMethod(MethodBase method) { return HarmonyMethod.Merge(GetFromMethod(method)); } public static List<HarmonyMethod> GetFromMethod(MethodBase method) { return (from attr in method.GetCustomAttributes(inherit: true) select GetHarmonyMethodInfo(attr) into info where info != null select info).ToList(); } } [Obsolete("Exists for legacy support", true)] internal static class HarmonySharedState { [Obsolete("Exists for legacy support", true)] public static PatchInfo GetPatchInfo(MethodBase method) { return method.ToPatchInfo(); } [Obsolete("Exists for legacy support", true)] public static IEnumerable<MethodBase> GetPatchedMethods() { return GlobalPatchState.GetPatchedMethods(); } [Obsolete("Exists for legacy support", true)] public static void UpdatePatchInfo(MethodBase methodBase, PatchInfo patchInfo) { } } [Obsolete("Exists for legacy support", true)] internal static class PatchFunctions { [Obsolete("Exists for legacy support", true)] public static DynamicMethod UpdateWrapper(MethodBase original, PatchInfo info, string id) { original.GetMethodPatcher().Apply(); return null; } } public class PatchInfo { public Patch[] prefixes; public Patch[] postfixes; public Patch[] transpilers; public Patch[] finalizers; public PatchInfo() { prefixes = new Patch[0]; postfixes = new Patch[0]; transpilers = new Patch[0]; finalizers = new Patch[0]; } private void AddPatch(ref Patch[] list, string owner, HarmonyMethod info) { if ((object)info?.method != null) { int priority = ((info.priority == -1) ? 400 : info.priority); string[] before = info.before ?? new string[0]; string[] after = info.after ?? new string[0]; AddPatch(ref list, info.method, owner, priority, before, after); } } private void AddPatch(ref Patch[] list, MethodInfo patch, string owner, int priority, string[] before, string[] after) { List<Patch> list2 = list.ToList(); list2.Add(new Patch(patch, prefixes.Count() + 1, owner, priority, before, after)); list = list2.ToArray(); } private void RemovePatch(ref Patch[] list, string owner) { if (owner == "*") { list = new Patch[0]; return; } list = list.Where((Patch patch) => patch.owner != owner).ToArray(); } public void AddPrefix(MethodInfo patch, string owner, int priority, string[] before, string[] after) { AddPatch(ref prefixes, patch, owner, priority, before, after); } public void AddPrefix(string owner, HarmonyMethod info) { AddPatch(ref prefixes, owner, info); } public void RemovePrefix(string owner) { RemovePatch(ref prefixes, owner); } public void AddPostfix(MethodInfo patch, string owner, int priority, string[] before, string[] after) { AddPatch(ref postfixes, patch, owner, priority, before, after); } public void AddPostfix(string owner, HarmonyMethod info) { AddPatch(ref postfixes, owner, info); } public void RemovePostfix(string owner) { RemovePatch(ref postfixes, owner); } public void AddTranspiler(MethodInfo patch, string owner, int priority, string[] before, string[] after) { AddPatch(ref transpilers, patch, owner, priority, before, after); } public void AddTranspiler(string owner, HarmonyMethod info) { AddPatch(ref transpilers, owner, info); } public void RemoveTranspiler(string owner) { RemovePatch(ref transpilers, owner); } public void AddFinalizer(MethodInfo patch, string owner, int priority, string[] before, string[] after) { AddPatch(ref finalizers, patch, owner, priority, before, after); } public void AddFinalizer(string owner, HarmonyMethod info) { AddPatch(ref finalizers, owner, info); } public void RemoveFinalizer(string owner) { RemovePatch(ref finalizers, owner); } public void RemovePatch(MethodInfo patch) { lock (this) { prefixes = prefixes.Where((Patch p) => (object)p.patch != patch).ToArray(); postfixes = postfixes.Where((Patch p) => (object)p.patch != patch).ToArray(); transpilers = transpilers.Where((Patch p) => (object)p.patch != patch).ToArray(); finalizers = finalizers.Where((Patch p) => (object)p.patch != patch).ToArray(); } } } public class Patch : IComparable { public readonly int index; public readonly string owner; public readonly int priority; public readonly string[] before; public readonly string[] after; public MethodInfo patch; public MethodInfo PatchMethod { get { return patch; } set { patch = value; } } public Patch(MethodInfo patch, int index, string owner, int priority, string[] before, string[] after) { if (patch is DynamicMethod) { throw new ArgumentException("Cannot directly reference dynamic method \"" + Extensions.GetID((MethodBase)patch, (string)null, (string)null, true, false, false) + "\" in Harmony. Use a factory method instead that will return the dynamic method.", "patch"); } this.index = index; this.owner = owner; this.priority = priority; this.before = before; this.after = after; this.patch = patch; } public MethodInfo GetMethod(MethodBase original) { if ((object)patch.ReturnType != typeof(DynamicMethod) && (object)patch.ReturnType != typeof(MethodInfo)) { return patch; } if (!patch.IsStatic) { return patch; } ParameterInfo[] parameters = patch.GetParameters(); if (parameters.Count() != 1) { return patch; } if ((object)parameters[0].ParameterType != typeof(MethodBase)) { return patch; } return patch.Invoke(null, new object[1] { original }) as MethodInfo; } public override bool Equals(object obj) { if (obj is Patch patch) { return (object)this.patch == patch.patch; } return false; } public int CompareTo(object obj) { if (!(obj is Patch patch)) { return 0; } int num; if (patch.priority != priority) { num = priority; return -num.CompareTo(patch.priority); } num = index; return num.CompareTo(patch.index); } public override int GetHashCode() { return patch.GetHashCode(); } } public class Patches { public readonly ReadOnlyCollection<Patch> Prefixes; public readonly ReadOnlyCollection<Patch> Postfixes; public readonly ReadOnlyCollection<Patch> Transpilers; public readonly ReadOnlyCollection<Patch> Finalizers; public ReadOnlyCollection<string> Owners { get { HashSet<string> hashSet = new HashSet<string>(); hashSet.UnionWith(Prefixes.Select((Patch p) => p.owner)); hashSet.UnionWith(Postfixes.Select((Patch p) => p.owner)); hashSet.UnionWith(Transpilers.Select((Patch p) => p.owner)); hashSet.UnionWith(Finalizers.Select((Patch p) => p.owner)); return hashSet.ToList().AsReadOnly(); } } public Patches(Patch[] prefixes, Patch[] postfixes, Patch[] transpilers, Patch[] finalizers) { if (prefixes == null) { prefixes = new Patch[0]; } if (postfixes == null) { postfixes = new Patch[0]; } if (transpilers == null) { transpilers = new Patch[0]; } if (finalizers == null) { finalizers = new Patch[0]; } Prefixes = prefixes.ToList().AsReadOnly(); Postfixes = postfixes.ToList().AsReadOnly(); Transpilers = transpilers.ToList().AsReadOnly(); Finalizers = finalizers.ToList().AsReadOnly(); } } public class PatchProcessor { private readonly Harmony instance; private readonly Type container; private readonly HarmonyMethod containerAttributes; private readonly List<MethodBase> originals = new List<MethodBase>(); private HarmonyMethod prefix; private HarmonyMethod postfix; private HarmonyMethod transpiler; private HarmonyMethod finalizer; public PatchProcessor(Harmony instance, MethodBase original = null) { this.instance = instance; if ((object)original != null) { originals.Add(original); } } public PatchProcessor(Harmony instance, Type type, HarmonyMethod attributes) { this.instance = instance; container = type; containerAttributes = attributes ?? new HarmonyMethod(); prefix = containerAttributes.Clone(); postfix = containerAttributes.Clone(); transpiler = containerAttributes.Clone(); finalizer = containerAttributes.Clone(); PrepareType(); } [Obsolete("Use other constructors and Add* methods")] public PatchProcessor(Harmony instance, List<MethodBase> originals, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null, HarmonyMethod finalizer = null) { this.instance = instance; this.originals = originals; this.prefix = prefix; this.postfix = postfix; this.transpiler = transpiler; this.finalizer = finalizer; } public PatchProcessor AddOriginal(MethodBase original) { if (!originals.Contains(original)) { originals.Add(original); } return this; } public PatchProcessor SetOriginals(List<MethodBase> originals) { this.originals.Clear(); this.originals.AddRange(originals); return this; } public PatchProcessor AddPrefix(HarmonyMethod prefix) { this.prefix = prefix; return this; } public PatchProcessor AddPrefix(MethodInfo fixMethod) { prefix = new HarmonyMethod(fixMethod); return this; } public PatchProcessor AddPostfix(HarmonyMethod postfix) { this.postfix = postfix; return this; } public PatchProcessor AddPostfix(MethodInfo fixMethod) { postfix = new HarmonyMethod(fixMethod); return this; } public PatchProcessor AddTranspiler(HarmonyMethod transpiler) { this.transpiler = transpiler; return this; } public PatchProcessor AddTranspiler(MethodInfo fixMethod) { transpiler = new HarmonyMethod(fixMethod); return this; } public PatchProcessor AddFinalizer(HarmonyMethod finalizer) { this.finalizer = finalizer; return this; } public PatchProcessor AddFinalizer(MethodInfo fixMethod) { finalizer = new HarmonyMethod(fixMethod); return this; } public static Patches GetPatchInfo(MethodBase method) { PatchInfo patchInfo = method.GetPatchInfo(); if (patchInfo == null) { return null; } lock (patchInfo) { return new Patches(patchInfo.prefixes, patchInfo.postfixes, patchInfo.transpilers, patchInfo.finalizers); } } public static Dictionary<string, Version> VersionInfo(out Version currentVersion) { currentVersion = typeof(Harmony).Assembly.GetName().Version; Dictionary<string, Assembly> assemblies = new Dictionary<string, Assembly>(); foreach (MethodBase allPatchedMethod in GetAllPatchedMethods()) { Patches patchInfo = GetPatchInfo(allPatchedMethod); AddAssemblies(patchInfo.Prefixes); AddAssemblies(patchInfo.Postfixes); AddAssemblies(patchInfo.Transpilers); AddAssemblies(patchInfo.Finalizers); } Dictionary<string, Version> dictionary = new Dictionary<string, Version>(); foreach (KeyValuePair<string, Assembly> item in assemblies) { AssemblyName assemblyName = item.Value.GetReferencedAssemblies().FirstOrDefault((AssemblyName a) => a.FullName.StartsWith("0Harmony, Version", StringComparison.Ordinal)); if (assemblyName != null) { dictionary[item.Key] = assemblyName.Version; } } return dictionary; void AddAssemblies(IEnumerable<Patch> patches) { foreach (Patch patch in patches) { assemblies[patch.owner] = patch.patch.DeclaringType?.Assembly; } } } public static List<CodeInstruction> GetOriginalInstructions(MethodBase original, ILGenerator generator = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) DynamicMethodDefinition val = new DynamicMethodDefinition(original); ILManipulator iLManipulator = new ILManipulator(val.Definition.Body); ILGenerator il = generator ?? ((ILGeneratorShim)new CecilILGenerator(val.GetILProcessor())).GetProxy(); return iLManipulator.GetInstructions(il); } public static List<CodeInstruction> GetOriginalInstructions(MethodBase original, out ILGenerator generator) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) DynamicMethodDefinition val = new DynamicMethodDefinition(original); ILManipulator iLManipulator = new ILManipulator(val.Definition.Body); generator = ((ILGeneratorShim)new CecilILGenerator(val.GetILProcessor())).GetProxy(); return iLManipulator.GetInstructions(generator); } [Obsolete("Use GetAllPatchedMethods instead")] public static IEnumerable<MethodBase> AllPatchedMethods() { return GlobalPatchState.GetPatchedMethods(); } public static IEnumerable<MethodBase> GetAllPatchedMethods() { return GlobalPatchState.GetPatchedMethods(); } public List<DynamicMethod> Patch() { Stopwatch sw = null; Logger.Log(Logger.LogChannel.Info, delegate { sw = Stopwatch.StartNew(); return "Patching " + instance.Id + "..."; }); List<DynamicMethod> result = new List<DynamicMethod>(); foreach (MethodBase original in originals) { if ((object)original == null) { throw new NullReferenceException("Null method for " + instance.Id); } Logger.Log(Logger.LogChannel.Info, () => "Patching " + Extensions.GetID(original, (string)null, (string)null, true, false, false)); bool individualPrepareResult = RunMethod<HarmonyPrepare, bool>(defaultIfNotExisting: true, new object[1] { original }); Logger.Log(Logger.LogChannel.Info, () => $"HarmonyPrepare result: {individualPrepareResult}"); if (individualPrepareResult) { PatchInfo patchInfo = original.ToPatchInfo(); lock (patchInfo) { patchInfo.AddPrefix(instance.Id, prefix); patchInfo.AddPostfix(instance.Id, postfix); patchInfo.AddTranspiler(instance.Id, transpiler); patchInfo.AddFinalizer(instance.Id, finalizer); } original.GetMethodPatcher().Apply(); RunMethod<HarmonyCleanup>(new object[1] { original }); } } Logger.Log(Logger.LogChannel.Info, () => $"Patching {instance.Id} took {sw.ElapsedMilliseconds}ms"); return result; } public PatchProcessor Unpatch(HarmonyPatchType type, string harmonyID) { foreach (MethodBase original in originals) { PatchInfo patchInfo = original.ToPatchInfo(); lock (patchInfo) { if (type == HarmonyPatchType.All || type == HarmonyPatchType.Prefix) { patchInfo.RemovePrefix(harmonyID); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Postfix) { patchInfo.RemovePostfix(harmonyID); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Transpiler) { patchInfo.RemoveTranspiler(harmonyID); } if (type == HarmonyPatchType.All || type == HarmonyPatchType.Finalizer) { patchInfo.RemoveFinalizer(harmonyID); } } original.GetMethodPatcher().Apply(); } return this; } public PatchProcessor Unpatch(MethodInfo patch) { foreach (MethodBase original in originals) { original.ToPatchInfo().RemovePatch(patch); original.GetMethodPatcher().Apply(); } return this; } private void PrepareType() { if (!RunMethod<HarmonyPrepare, bool>(defaultIfNotExisting: true, new object[0])) { return; } MethodType? methodType = containerAttributes.methodType; if (!containerAttributes.methodType.HasValue) { containerAttributes.methodType = MethodType.Normal; } string reversePatchAttr = typeof(HarmonyReversePatch).FullName; foreach (MethodInfo item in (from m in container.GetMethods(AccessTools.all) where m.GetCustomAttributes(inherit: true).Any((object a) => a.GetType().FullName == reversePatchAttr) select m).ToList()) { MethodBase originalMethod = GetOriginalMethod(containerAttributes.Merge(new HarmonyMethod(item))); instance.CreateReversePatcher(originalMethod, item).Patch(); } IEnumerable<MethodBase> enumerable = RunMethod<HarmonyTargetMethods, IEnumerable<MethodBase>>(null, new object[0]); if (enumerable != null) { originals.Clear(); originals.AddRange(enumerable); } else if (container.GetCustomAttributes(inherit: true).Any((object a) => a.GetType().FullName == typeof(HarmonyPatchAll).FullName)) { Type declaringType = containerAttributes.declaringType; originals.AddRange(AccessTools.GetDeclaredConstructors(declaringType).Cast<MethodBase>()); originals.AddRange(AccessTools.GetDeclaredMethods(declaringType).Cast<MethodBase>()); List<PropertyInfo> declaredProperties = AccessTools.GetDeclaredProperties(declaringType); originals.AddRange((from prop in declaredProperties select prop.GetGetMethod(nonPublic: true) into method where (object)method != null select method).Cast<MethodBase>()); originals.AddRange((from prop in declaredProperties select prop.GetSetMethod(nonPublic: true) into method where (object)method != null select method).Cast<MethodBase>()); } else { MethodBase methodBase = RunMethod<HarmonyTargetMethod, MethodBase>(null, new object[0]) ?? GetOriginalMethod(containerAttributes); if ((object)methodBase == null) { string text = "("; text += $"declaringType={containerAttributes.declaringType}, "; text = text + "methodName =" + containerAttributes.methodName + ", "; text += $"methodType={methodType}, "; text = text + "argumentTypes=" + containerAttributes.argumentTypes.Description(); text += ")"; throw new ArgumentException("No target method specified for class " + container.FullName + " " + text); } originals.Add(methodBase); } GetPatches(container, out var methodInfo, out var methodInfo2, out var methodInfo3, out var methodInfo4); if (prefix != null) { prefix.method = methodInfo; } if (postfix != null) { postfix.method = methodInfo2; } if (transpiler != null) { transpiler.method = methodInfo3; } if (finalizer != null) { finalizer.method = methodInfo4; } if ((object)methodInfo != null) { if (!methodInfo.IsStatic) { throw new ArgumentException("Patch method " + Extensions.GetID((MethodBase)methodInfo, (string)null, (string)null, true, false, false) + " must be static"); } List<HarmonyMethod> fromMethod = HarmonyMethodExtensions.GetFromMethod(methodInfo); containerAttributes.Merge(HarmonyMethod.Merge(fromMethod)).CopyTo(prefix); } if ((object)methodInfo2 != null) { if (!methodInfo2.IsStatic) { throw new ArgumentException("Patch method " + Extensions.GetID((MethodBase)methodInfo2, (string)null, (string)null, true, false, false) + " must be static"); } List<HarmonyMethod> fromMethod2 = HarmonyMethodExtensions.GetFromMethod(methodInfo2); containerAttributes.Merge(HarmonyMethod.Merge(fromMethod2)).CopyTo(postfix); } if ((object)methodInfo3 != null) { if (!methodInfo3.IsStatic) { throw new ArgumentException("Patch method " + Extensions.GetID((MethodBase)methodInfo3, (string)null, (string)null, true, false, false) + " must be static"); } List<HarmonyMethod> fromMethod3 = HarmonyMethodExtensions.GetFromMethod(methodInfo3); containerAttributes.Merge(HarmonyMethod.Merge(fromMethod3)).CopyTo(transpiler); } if ((object)methodInfo4 != null) { if (!methodInfo4.IsStatic) { throw new ArgumentException("Patch method " + Extensions.GetID((MethodBase)methodInfo4, (string)null, (string)null, true, false, false) + " must be static"); } List<HarmonyMethod> fromMethod4 = HarmonyMethodExtensions.GetFromMethod(methodInfo4); containerAttributes.Merge(HarmonyMethod.Merge(fromMethod4)).CopyTo(finalizer); } } internal static MethodBase GetOriginalMethod(HarmonyMethod attribute) { if (attribute == null) { throw new ArgumentNullException("attribute"); } if ((object)attribute.declaringType == null) { return MakeFailure("declaringType cannot be null"); } switch (attribute.methodType) { case MethodType.Normal: { if (string.IsNullOrEmpty(attribute.methodName)) { return MakeFailure("methodName can't be empty"); } if (attribute.methodName == ".ctor") { Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + " - MethodType.Constructor should be used instead of setting methodName to .ctor"); goto case MethodType.Constructor; } if (attribute.methodName == ".cctor") { Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + " - MethodType.StaticConstructor should be used instead of setting methodName to .cctor"); goto case MethodType.StaticConstructor; } if (attribute.methodName.StartsWith("get_") || attribute.methodName.StartsWith("set_")) { Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + " - MethodType.Getter and MethodType.Setter should be used instead adding get_ and set_ to property names"); } MethodInfo methodInfo = AccessTools.DeclaredMethod(attribute.declaringType, attribute.methodName, attribute.argumentTypes); if ((object)methodInfo != null) { return methodInfo; } methodInfo = AccessTools.Method(attribute.declaringType, attribute.methodName, attribute.argumentTypes); if ((object)methodInfo != null) { string text = GetPatchName(); object[] obj = new object[4] { attribute.methodName, null, null, null }; Type[] argumentTypes = attribute.argumentTypes; obj[1] = ((argumentTypes != null) ? argumentTypes.Length : 0); obj[2] = attribute.declaringType.FullDescription(); obj[3] = methodInfo.DeclaringType.FullDescription(); Logger.LogText(Logger.LogChannel.Warn, text + string.Format(" - Could not find method {0} with {1} parameters in type {2}, but it was found in base class of this type {3}", obj)); return methodInfo; } return MakeFailure("Could not find method " + attribute.methodName + " with " + attribute.argumentTypes.Description() + " parameters in type " + attribute.declaringType.FullDescription()); } case MethodType.Getter: { if (string.IsNullOrEmpty(attribute.methodName)) { return MakeFailure("methodName can't be empty"); } PropertyInfo propertyInfo2 = AccessTools.DeclaredProperty(attribute.declaringType, attribute.methodName); if ((object)propertyInfo2 != null) { MethodInfo getMethod = propertyInfo2.GetGetMethod(nonPublic: true); if ((object)getMethod == null) { return MakeFailure("Property " + attribute.methodName + " does not have a Getter"); } return getMethod; } propertyInfo2 = AccessTools.Property(attribute.declaringType, attribute.methodName); if ((object)propertyInfo2 != null) { Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + " - Could not find property " + attribute.methodName + " in type " + attribute.declaringType.FullDescription() + ", but it was found in base class of this type: " + propertyInfo2.DeclaringType.FullDescription()); MethodInfo getMethod2 = propertyInfo2.GetGetMethod(nonPublic: true); if ((object)getMethod2 == null) { return MakeFailure("Property " + attribute.methodName + " does not have a Getter"); } return getMethod2; } return MakeFailure("Could not find property " + attribute.methodName + " in type " + attribute.declaringType.FullDescription()); } case MethodType.Setter: { if (string.IsNullOrEmpty(attribute.methodName)) { return MakeFailure("methodName can't be empty"); } PropertyInfo propertyInfo = AccessTools.DeclaredProperty(attribute.declaringType, attribute.methodName); if ((object)propertyInfo != null) { MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); if ((object)setMethod == null) { return MakeFailure("Property " + attribute.methodName + " does not have a Setter"); } return setMethod; } propertyInfo = AccessTools.Property(attribute.declaringType, attribute.methodName); if ((object)propertyInfo != null) { Logger.LogText(Logger.LogChannel.Warn, GetPatchName() + " - Could not find property " + attribute.methodName + " in type " + attribute.declaringType.FullDescription() + ", but it was found in base class of this type: " + propertyInfo.DeclaringType.FullDescription()); MethodInfo setMethod2 = propertyInfo.GetSetMethod(nonPublic: true); if ((object)setMethod2 == null) { return MakeFailure("Property " + attribute.methodName + " does not have a Setter"); } return setMethod2; } return MakeFailure("Could not find property " + attribute.methodName + " in type " + attribute.declaringType.FullDescription()); } case MethodType.Constructor: { ConstructorInfo constructorInfo2 = AccessTools.DeclaredConstructor(attribute.declaringType, attribute.argumentTypes); if ((object)constructorInfo2 != null) { return constructorInfo2; } return MakeFailure("Could not find constructor with " + attribute.argumentTypes.Description() + " parameters in type " + attribute.declaringType.FullDescription()); } case MethodType.StaticConstructor: { ConstructorInfo constructorInfo = AccessTools.GetDeclaredConstructors(attribute.declaringType).FirstOrDefault((ConstructorInfo c) => c.IsStatic); if ((object)constructorInfo != null) { return constructorInfo; } return MakeFailure("Could not find static constructor in type " + attribute.declaringType.FullDescription()); } default: throw new ArgumentOutOfRangeException("methodType", attribute.methodType, "Unknown method type"); } string GetPatchName() { return attribute.method?.FullDescription() ?? "Unknown patch"; } MethodBase MakeFailure(string reason) { Logger.Log(Logger.LogChannel.Error, () => "Failed to process patch " + GetPatchName() + " - " + reason); return null; } } private T RunMethod<S, T>(T defaultIfNotExisting, params object[] parameters) { if ((object)container == null) { return defaultIfNotExisting; } string name = typeof(S).Name.Replace("Harmony", ""); MethodInfo patchMethod = GetPatchMethod<S>(container, name); if ((object)patchMethod != null) { if (typeof(T).IsAssignableFrom(patchMethod.ReturnType)) { object[] emptyTypes = Type.EmptyTypes; return (T)patchMethod.Invoke(null, emptyTypes); } object[] inputs = (parameters ?? new object[0]).Union(new object[1] { instance }).ToArray(); object[] parameters2 = AccessTools.ActualParameters(patchMethod, inputs); patchMethod.Invoke(null, parameters2); return defaultIfNotExisting; } return defaultIfNotExisting; } private void RunMethod<S>(params object[] parameters) { if ((object)container != null) { string name = typeof(S).Name.Replace("Harmony", ""); MethodInfo patchMethod = GetPatchMethod<S>(container, name); if ((object)patchMethod != null) { object[] inputs = (parameters ?? new object[0]).Union(new object[1] { instance }).ToArray(); object[] parameters2 = AccessTools.ActualParameters(patchMethod, inputs); patchMethod.Invoke(null, parameters2); } } } private MethodInfo GetPatchMethod<T>(Type patchType, string name) { string attributeType = typeof(T).FullName; MethodInfo methodInfo = patchType.GetMethods(AccessTools.all).FirstOrDefault((MethodInfo m) => m.GetCustomAttributes(inherit: true).Any((object a) => a.GetType().FullName == attributeType)); if ((object)methodInfo == null) { methodInfo = patchType.GetMethod(name, AccessTools.all); } return methodInfo; } private void GetPatches(Type patchType, out MethodInfo prefix, out MethodInfo postfix, out MethodInfo transpiler, out MethodInfo finalizer) { prefix = GetPatchMethod<HarmonyPrefix>(patchType, "Prefix"); postfix = GetPatchMethod<HarmonyPostfix>(patchType, "Postfix"); transpiler = GetPatchMethod<HarmonyTranspiler>(patchType, "Transpiler"); finalizer = GetPatchMethod<HarmonyFinalizer>(patchType, "Finalizer"); } } public class ReversePatcher { private readonly Harmony instance; private readonly MethodBase original; private readonly MethodInfo standin; private readonly ILHook ilHook; public ReversePatcher(Harmony instance, MethodBase original, MethodInfo standin) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown this.instance = instance; this.original = original; this.standin = standin; ilHook = new ILHook((MethodBase)standin, new Manipulator(ApplyReversePatch), new ILHookConfig { ManualApply = true }); } private void ApplyReversePatch(ILContext ctx) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) DynamicMethodDefinition val = new DynamicMethodDefinition(original); ILManipulator iLManipulator = new ILManipulator(val.Definition.Body); ctx.Body.Variables.Clear(); Enumerator<VariableDefinition> enumerator = val.Definition.Body.Variables.GetEnumerator(); try { while (enumerator.MoveNext()) { VariableDefinition current = enumerator.Current; ctx.Body.Variables.Add(new VariableDefinition(ctx.Module.ImportReference(((VariableReference)current).VariableType))); } } finally { ((IDisposable)enumerator).Dispose(); } MethodInfo transpiler = GetTranspiler(standin); if ((object)transpiler != null) { iLManipulator.AddTranspiler(transpiler); } iLManipulator.WriteTo(ctx.Body, standin); ctx.IL.Emit(OpCodes.Ret); } public void Patch(HarmonyReversePatchType type = HarmonyReversePatchType.Original) { if ((object)original == null) { throw new NullReferenceException("Null method for " + instance.Id); } ilHook.Apply(); } private MethodInfo GetTranspiler(MethodInfo method) { string methodName = method.Name; List<MethodInfo> declaredMethods = AccessTools.GetDeclaredMethods(method.DeclaringType); Type ici = typeof(IEnumerable<CodeInstruction>); return declaredMethods.FirstOrDefault((MethodInfo m) => (object)m.ReturnType == ici && m.Name.StartsWith("<" + methodName + ">")); } } public class CodeMatch { public string name; public List<OpCode> opcodes = new List<OpCode>(); public List<object> operands = new List<object>(); public List<Label> labels = new List<Label>(); public List<ExceptionBlock> blocks = new List<ExceptionBlock>(); public List<int> jumpsFrom = new List<int>(); public List<int> jumpsTo = new List<int>(); public Func<CodeInstruction, bool> predicate; public CodeMatch(OpCode? opcode = null, object operand = null, string name = null) { if (opcode.HasValue) { OpCode valueOrDefault = opcode.GetValueOrDefault(); opcodes.Add(valueOrDefault); } if (operand != null) { operands.Add(operand); } this.name = name; } public CodeMatch(CodeInstruction instruction, string name = null) : this(instruction.opcode, instruction.operand, name) { } public CodeMatch(Func<CodeInstruction, bool> predicate, string name = null) { this.predicate = predicate; this.name = name; } internal bool Matches(List<CodeInstruction> codes, CodeInstruction instruction) { if (predicate != null) { return predicate(instruction); } if (opcodes.Count > 0 && !opcodes.Contains(instruction.opcode)) { return false; } if (operands.Count > 0 && !operands.Contains(instruction.operand)) { return false; } if (labels.Count > 0 && !labels.Intersect(instruction.labels).Any()) { return false; } if (blocks.Count > 0 && !blocks.Intersect(instruction.blocks).Any()) { return false; } if (jumpsFrom.Count > 0 && !jumpsFrom.Select((int index) => codes[index].operand).OfType<Label>().Intersect(instruction.labels) .Any()) { return false; } if (jumpsTo.Count > 0) { object operand = instruction.operand; if (operand == null || (object)operand.GetType() != typeof(Label)) { return false; } Label label = (Label)operand; IEnumerable<int> second = from idx in Enumerable.Range(0, codes.Count) where codes[idx].labels.Contains(label) select idx; if (!jumpsTo.Intersect(second).Any()) { return false; } } return true; } public override string ToString() { string text = "["; if (name != null) { text = text + name + ": "; } if (opcodes.Count > 0) { text = text + "opcodes=" + opcodes.Join() + " "; } if (operands.Count > 0) { text = text + "operands=" + operands.Join() + " "; } if (labels.Count > 0) { text = text + "labels=" + labels.Join() + " "; } if (blocks.Count > 0) { text = text + "blocks=" + blocks.Join() + " "; } if (jumpsFrom.Count > 0) { text = text + "jumpsFrom=" + jumpsFrom.Join() + " "; } if (jumpsTo.Count > 0) { text = text + "jumpsTo=" + jumpsTo.Join() + " "; } if (predicate != null) { text += "predicate=yes "; } return text.TrimEnd(new char[0]) + "]"; } } public class CodeMatcher { private readonly ILGenerator generator; private readonly List<CodeInstruction> codes = new List<CodeInstruction>(); private Dictionary<string, CodeInstruction> lastMatches = new Dictionary<string, CodeInstruction>(); private string lastError; private bool lastUseEnd; private CodeMatch[] lastCodeMatches; public int Pos { get; private set; } = -1; public int Length => codes.Count; public bool IsValid { get { if (Pos >= 0) { return Pos < Length; } return false; } } public bool IsInvalid { get { if (Pos >= 0) { return Pos >= Length; } return true; } } public int Remaining => Length - Math.Max(0, Pos); public ref OpCode Opcode => ref codes[Pos].opcode; public ref object Operand => ref codes[Pos].operand; public ref List<Label> Labels => ref codes[Pos].labels; public ref List<ExceptionBlock> Blocks => ref codes[Pos].blocks; public CodeInstruction Instruction => codes[Pos]; private void FixStart() { Pos = Math.Max(0, Pos); } private void SetOutOfBounds(int direction) { Pos = ((direction > 0) ? Length : (-1)); } public CodeMatcher() { } public CodeMatcher(IEnumerable<CodeInstruction> instructions, ILGenerator generator = null) { this.generator = generator; codes = instructions.Select((CodeInstruction c) => new CodeInstruction(c)).ToList(); } public CodeMatcher Clone() { return new CodeMatcher(codes, generator) { Pos = Pos, lastMatches = lastMatches, lastError = lastError, lastUseEnd = lastUseEnd, lastCodeMatches = lastCodeMatches }; } public CodeInstruction InstructionAt(int offset) { return codes[Pos + offset]; } public List<CodeInstruction> Instructions() { return codes; } public IEnumerable<CodeInstruction> InstructionEnumeration() { return codes.AsEnumerable(); } public List<CodeInstruction> Instructions(int count) { return (from c in codes.GetRange(Pos, count) select new CodeInstruction(c)).ToList(); } public List<CodeInstruction> InstructionsInRange(int start, int end) { List<CodeInstruction> list = codes; if (start > end) { int num = start; start = end; end = num; } return (from c in list.GetRange(start, end - start + 1) select new CodeInstruction(c)).ToList(); } public List<CodeInstruction> InstructionsWithOffsets(int startOffset, int endOffset) { return InstructionsInRange(Pos + startOffset, Pos + endOffset); } public List<Label> DistinctLabels(IEnumerable<CodeInstruction> instructions) { return instructions.SelectMany((CodeInstruction instruction) => instruction.labels).Distinct().ToList(); } public bool ReportFailure(MethodBase method, Action<string> logger) { if (IsValid) { return false; } string arg = lastError ?? "Unexpected code"; logger($"{arg} in {method}"); return true; } public CodeMatcher SetInstruction(CodeInstruction instruction) { codes[Pos] = instruction; return this; } public CodeMatcher SetInstructionAndAdvance(CodeInstruction instruction) { SetInstruction(instruction); Pos++; return this; } public CodeMatcher Set(OpCode opcode, object operand) { Opcode = opcode; Operand = operand; return this; } public CodeMatcher SetAndAdvance(OpCode opcode, object operand) { Set(opcode, operand); Pos++; return this; } public CodeMatcher SetOpcodeAndAdvance(OpCode opcode) { Opcode = opcode; Pos++; return this; } public CodeMatcher SetOperandAndAdvance(object operand) { Operand = operand; Pos++; return this; } public CodeMatcher CreateLabel(out Label label) { label = generator.DefineLabel(); Labels.Add(label); return this; } public CodeMatcher CreateLabelAt(int position, out Label label) { label = generator.DefineLabel(); AddLabelsAt(position, new Label[1] { label }); return this; } public CodeMatcher AddLabels(IEnumerable<Label> labels) { Labels.AddRange(labels); return this; } public CodeMatcher AddLabelsAt(int position, IEnumerable<Label> labels) { codes[position].labels.AddRange(labels); return this; } public CodeMatcher SetJumpTo(OpCode opcode, int destination, out Label label) { CreateLabelAt(destination, out label); Set(opcode, label); return this; } public CodeMatcher Insert(params CodeInstruction[] instructions) { codes.InsertRange(Pos, instructions); return this; } public CodeMatcher Insert(IEnumerable<CodeInstruction> instructions) { codes.InsertRange(Pos, instructions); return this; } public CodeMatcher InsertBranch(OpCode opcode, int destination) { CreateLabelAt(destination, out var label); codes.Insert(Pos, new CodeInstruction(opcode, label)); return this; } public CodeMatcher InsertAndAdvance(params CodeInstruction[] instructions) { foreach (CodeInstruction codeInstruction in instructions) { Insert(codeInstruction); Pos++; } return this; } public CodeMatcher InsertAndAdvance(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { InsertAndAdvance(instruction); } return this; } public CodeMatcher InsertBranchAndAdvance(OpCode opcode, int destination) { InsertBranch(opcode, destination); Pos++; return this; } public CodeMatcher RemoveInstruction() { codes.RemoveAt(Pos); return this; } public CodeMatcher RemoveInstructions(int count) { codes.RemoveRange(Pos, count); return this; } public CodeMatcher RemoveInstructionsInRange(int start, int end) { if (start > end) { int num = start; start = end; end = num; } codes.RemoveRange(start, end - start + 1); return this; } public CodeMatcher RemoveInstructionsWithOffsets(int startOffset, int endOffset) { RemoveInstructionsInRange(Pos + startOffset, Pos + endOffset); return this; } public CodeMatcher Advance(int offset) { Pos += offset; if (!IsValid) { SetOutOfBounds(offset); } return this; } public CodeMatcher Start() { Pos = 0; return this; } public CodeMatcher End() { Pos = Length - 1; return this; } public CodeMatcher SearchForward(Func<CodeInstruction, bool> predicate) { return Search(predicate, 1); } public CodeMatcher SearchBack(Func<CodeInstruction, bool> predicate) { return Search(predicate, -1); } private CodeMatcher Search(Func<CodeInstruction, bool> predicate, int direction) { FixStart(); while (IsValid && !predicate(Instruction)) { Pos += direction; } lastError = (IsInvalid ? $"Cannot find {predicate}" : null); return this; } public CodeMatcher MatchForward(bool useEnd, params CodeMatch[] matches) { return Match(matches, 1, useEnd); } public CodeMatcher MatchBack(bool useEnd, params CodeMatch[] matches) { return Match(matches, -1, useEnd); } private CodeMatcher Match(CodeMatch[] matches, int direction, bool useEnd) { FixStart(); while (IsValid) { lastUseEnd = useEnd; lastCodeMatches = matches; if (MatchSequence(Pos, matches)) { if (useEnd) { Pos += matches.Count() - 1; } break; } Pos += direction; } lastError = (IsInvalid ? ("Cannot find " + matches.Join()) : null); return this; } public CodeMatcher Repeat(Action<CodeMatcher> matchAction, Action<string> notFoundAction = null) { int num = 0; if (lastCodeMatches == null) { throw new InvalidOperationException("No previous Match operation - cannot repeat"); } while (IsValid) { matchAction(this); MatchForward(lastUseEnd, lastCodeMatches); num++; } lastCodeMatches = null; if (num == 0) { notFoundAction?.Invoke(lastError); } return this; } public CodeInstruction NamedMatch(string name) { return lastMatches[name]; } private bool MatchSequence(int start, CodeMatch[] matches) { if (start < 0) { return false; } lastMatches = new Dictionary<string, CodeInstruction>(); foreach (CodeMatch codeMatch in matches) { if (start >= Length || !codeMatch.Matches(codes, codes[start])) { return false; } if (codeMatch.name != null) { lastMatches.Add(codeMatch.name, codes[start]); } start++; } return true; } } public static class CodeInstructionExtensions { private static readonly HashSet<OpCode> LoadVarCodes = new HashSet<OpCode> { OpCodes.Ldloc_0, OpCodes.Ldloc_1, OpCodes.Ldloc_2, OpCodes.Ldloc_3, OpCodes.Ldloc, OpCodes.Ldloca, OpCodes.Ldloc_S, OpCodes.Ldloca_S }; private static readonly HashSet<OpCode> StoreVarCodes = new HashSet<OpCode> { OpCodes.Stloc_0, OpCodes.Stloc_1, OpCodes.Stloc_2, OpCodes.Stloc_3, OpCodes.Stloc, OpCodes.Stloc_S }; private static readonly HashSet<OpCode> BranchCodes = new HashSet<OpCode> { OpCodes.Br_S, OpCodes.Brfalse_S, OpCodes.Brtrue_S, OpCodes.Beq_S, OpCodes.Bge_S, OpCodes.Bgt_S, OpCodes.Ble_S, OpCodes.Blt_S, OpCodes.Bne_Un_S, OpCodes.Bge_Un_S, OpCodes.Bgt_Un_S, OpCodes.Ble_Un_S, OpCodes.Blt_Un_S, OpCodes.Br, OpCodes.Brfalse, OpCodes.Brtrue, OpCodes.Beq, OpCodes.Bge, OpCodes.Bgt, OpCodes.Ble, OpCodes.Blt, OpCodes.Bne_Un, OpCodes.Bge_Un, OpCodes.Bgt_Un, OpCodes.Ble_Un, OpCodes.Blt_Un }; private static readonly HashSet<OpCode> ConstantLoadingCodes = new HashSet<OpCode> { OpCodes.Ldc_I4_M1, OpCodes.Ldc_I4_0, OpCodes.Ldc_I4_1, OpCodes.Ldc_I4_2, OpCodes.Ldc_I4_3, OpCodes.Ldc_I4_4, OpCodes.Ldc_I4_5, OpCodes.Ldc_I4_6, OpCodes.Ldc_I4_7, OpCodes.Ldc_I4_8, OpCodes.Ldc_I4, OpCodes.Ldc_I4_S, OpCodes.Ldc_I8, OpCodes.Ldc_R4, OpCodes.Ldc_R8 }; public static bool OperandIs(this CodeInstruction code, object value) { if (value == null) { throw new ArgumentNullException("value"); } if (code.operand == null) { return false; } Type type = value.GetType(); Type type2 = code.operand.GetType(); if (AccessTools.IsInteger(type) && AccessTools.IsNumber(type2)) { return Convert.ToInt64(code.operand) == Convert.ToInt64(value); } if (AccessTools.IsFloatingPoint(type) && AccessTools.IsNumber(type2)) { return Convert.ToDouble(code.operand) == Convert.ToDouble(value); } return object.Equals(code.operand, value); } public static bool Is(this CodeInstruction code, OpCode opcode, object operand) { if (code.opcode == opcode) { return code.OperandIs(operand); } return false; } public static bool IsLdarg(this CodeInstruction code, int? n = null) { if ((!n.HasValue || n.Value == 0) && code.opcode == OpCodes.Ldarg_0) { return true; } if ((!n.HasValue || n.Value == 1) && code.opcode == OpCodes.Ldarg_1) { return true; } if ((!n.HasValue || n.Value == 2) && code.opcode == OpCodes.Ldarg_2) { return true; } if ((!n.HasValue || n.Value == 3) && code.opcode == OpCodes.Ldarg_3) { return true; } if (code.opcode == OpCodes.Ldarg && (!n.HasValue || n.Value == Convert.ToInt32(code.operand))) { return true; } if (code.opcode == OpCodes.Ldarg_S && (!n.HasValue || n.Value == Convert.ToInt32(code.operand))) { return true; } return false; } public static bool IsLdarga(this CodeInstruction code, int? n = null) { if (code.opcode != OpCodes.Ldarga && code.opcode != OpCodes.Ldarga_S) { return false; } if (n.HasValue) { return n.Value == Convert.ToInt32(code.operand); } return true; } public static bool IsStarg(this CodeInstruction code, int? n = null) { if (code.opcode != OpCodes.Starg && code.opcode != OpCodes.Starg_S) { return false; } if (n.HasValue) { return n.Value == Convert.ToInt32(code.operand); } return true; } public static bool IsLdloc(this CodeInstruction code, LocalBuilder variable = null) { if (!LoadVarCodes.Contains(code.opcode)) { return false; } if (variable != null) { return object.Equals(variable, code.operand); } return true; } public static bool IsStloc(this CodeInstruction code, LocalBuilder variable = null) { if (!StoreVarCodes.Contains(code.opcode)) { return false; } if (variable != null) { return object.Equals(variable, code.operand); } return true; } public static bool Branches(this CodeInstruction code, out Label? label) { if (BranchCodes.Contains(code.opcode)) { label = (Label)code.operand; return true; } label = null; return false; } public static bool Calls(this CodeInstruction code, MethodInfo method) { if ((object)method == null) { throw new ArgumentNullException("method"); } if (code.opcode != OpCodes.Call && code.opcode != OpCodes.Callvirt) { return false; } return object.Equals(code.operand, method); } public static bool LoadsConstant(this CodeInstruction code) { return ConstantLoadingCodes.Contains(code.opcode); } public static bool LoadsConstant(this CodeInstruction code, long number) { OpCode opcode = code.opcode; if (number == -1 && opcode == OpCodes.Ldc_I4_M1) { return true; } if (number == 0L && opcode == OpCodes.Ldc_I4_0) { return true; } if (number == 1 && opcode == OpCodes.Ldc_I4_1) { return true; } if (number == 2 && opcode == OpCodes.Ldc_I4_2) { return true; } if (number == 3 && opcode == OpCodes.Ldc_I4_3) { return true; } if (number == 4 && opcode == OpCodes.Ldc_I4_4) { return true; } if (number == 5 && opcode == OpCodes.Ldc_I4_5) { return true; } if (number == 6 && opcode == OpCodes.Ldc_I4_6) { return true; } if (number == 7 && opcode == OpCodes.Ldc_I4_7) { return true; } if (number == 8 && opcode == OpCodes.Ldc_I4_8) { return true; } if (opcode != OpCodes.Ldc_I4 && opcode != OpCodes.Ldc_I4_S && opcode != OpCodes.Ldc_I8) { return false; } return Convert.ToInt64(code.operand) == number; } public static bool LoadsConstant(this CodeInstruction code, double number) { if (code.opcode != OpCodes.Ldc_R4 && code.opcode != OpCodes.Ldc_R8) { return false; } return Convert.ToDouble(code.operand) == number; } public static bool LoadsConstant(this CodeInstruction code, Enum e) { return code.LoadsConstant(Convert.ToInt64(e)); } public static bool LoadsField(this CodeInstruction code, FieldInfo field, bool byAddress = false) { if ((object)field == null) { throw new ArgumentNullException("field"); } OpCode opCode = (field.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld); if (!byAddress && code.opcode == opCode && object.Equals(code.operand, field)) { return true; } OpCode opCode2 = (field.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda); if (byAddress && code.opcode == opCode2 && object.Equals(code.operand, field)) { return true; } return false; } public static bool StoresField(this CodeInstruction code, FieldInfo field) { if ((object)field == null) { throw new ArgumentNullException("field"); } OpCode opCode = (field.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld); if (code.opcode == opCode) { return object.Equals(code.operand, field); } return false; } public static CodeInstruction WithLabels(this CodeInstruction code, params Label[] labels) { code.labels.AddRange(labels); return code; } public static CodeInstruction WithLabels(this CodeInstruction code, IEnumerable<Label> labels) { code.labels.AddRange(labels); return code; } public static List<Label> ExtractLabels(this CodeInstruction code) { List<Label> result = new List<Label>(code.labels); code.labels.Clear(); return result; } public static CodeInstruction MoveLabelsTo(this CodeInstruction code, CodeInstruction other) { other.WithLabels(code.ExtractLabels()); return code; } public static CodeInstruction MoveLabelsFrom(this CodeInstruction code, CodeInstruction other) { return code.WithLabels(other.ExtractLabels()); } public static CodeInstruction WithBlocks(this CodeInstruction code, params ExceptionBlock[] blocks) { code.blocks.AddRange(blocks); return code; } public static CodeInstruction WithBlocks(this CodeInstruction code, IEnumerable<ExceptionBlock> blocks) { code.blocks.AddRange(blocks); return code; } public static List<ExceptionBlock> ExtractBlocks(this CodeInstruction code) { List<ExceptionBlock> result = new List<ExceptionBlock>(code.blocks); code.blocks.Clear(); return result; } public static CodeInstruction MoveBlocksTo(this CodeInstruction code, CodeInstruction other) { other.WithBlocks(code.ExtractBlocks()); return code; } public static CodeInstruction MoveBlocksFrom(this CodeInstruction code, CodeInstruction other) { return code.WithBlocks(other.ExtractBlocks()); } } public static class CollectionExtensions { public static void Do<T>(this IEnumerable<T> sequence, Action<T> action) { if (sequence != null) { IEnumerator<T> enumerator = sequence.GetEnumerator(); while (enumerator.MoveNext()) { action(enumerator.Current); } } } public static void DoIf<T>(this IEnumerable<T> sequence, Func<T, bool> condition, Action<T> action) { sequence.Where(condition).Do(action); } public static IEnumerable<T> AddItem<T>(this IEnumerable<T> sequence, T item) { return (sequence ?? Enumerable.Empty<T>()).Concat(new T[1] { item }); } public static T[] AddToArray<T>(this T[] sequence, T item) { return sequence.AddItem(item).ToArray(); } public static T[] AddRangeToArray<T>(this T[] sequence, T[] items) { return (sequence ?? Enumerable.Empty<T>()).Concat(items).ToArray(); } } public static class GeneralExtensions { public static string Join<T>(this IEnumerable<T> enumeration, Func<T, string> converter = null, string delimiter = ", ") { if (converter == null) { converter = (T t) => t.ToString(); } return enumeration.Aggregate("", (string prev, T curr) => prev + ((prev != "") ? delimiter : "") + converter(curr)); } public static string Description(this Type[] parameters) { if (parameters == null) { return "NULL"; } return "(" + parameters.Join((Type p) => p.FullDescription()) + ")"; } public static string FullDescription(this Type type) { if ((object)type == null) { return "null"; } string text = type.Namespace; if (!string.IsNullOrEmpty(text)) { text += "."; } string text2 = text + type.Name; if (type.IsGenericType) { text2 += "<"; Type[] genericArguments = type.GetGenericArguments(); for (int i = 0; i < genericArguments.Length; i++) { if (!text2.EndsWith("<", StringComparison.Ordinal)) { text2 += ", "; } text2 += genericArguments[i].FullDescription(); } text2 += ">"; } return text2; } public static string FullDescription(this MethodBase method) { if ((object)method == null) { return "null"; } Type[] parameters = (from p in method.GetParameters() select p.ParameterType).ToArray(); Type returnedType = AccessTools.GetReturnedType(method); return returnedType.FullDescription() + " " + method.DeclaringType.FullDescription() + "." + method.Name + parameters.Description(); } public static Type[] Types(this ParameterInfo[] pinfo) { return pinfo.Select((ParameterInfo pi) => pi.ParameterType).ToArray(); } public static T GetValueSafe<S, T>(this Dictionary<S, T> dictionary, S key) { if (dictionary.TryGetValue(key, out var value)) { return value; } return default(T); } public static T GetTypedValue<T>(this Dictionary<string, object> dictionary, string key) { if (dictionary.TryGetValue(key, out var value) && value is T) { return (T)value; } return default(T); } } public static class SymbolExtensions { public static MethodInfo GetMethodInfo(Expression<Action> expression) { return GetMethodInfo((LambdaExpression)expression); } public static MethodInfo GetMethodInfo<T>(Expression<Action<T>> expression) { return GetMethodInfo((LambdaExpression)expression); } public static MethodInfo GetMethodInfo<T, TResult>(Expression<Func<T, TResult>> expression) { return GetMethodInfo((LambdaExpression)expression); } public static MethodInfo GetMethodInfo(LambdaExpression expression) { return ((expression.Body as MethodCallExpression) ?? throw new ArgumentException("Invalid Expression. Expression should consist of a Method call only.")).Method ?? throw new MemberNotFoundException($"Cannot find method for expression {expression}"); } } [Obsolete("Use HarmonyFileLog instead", true)] public static class FileLog { public static string logPath; public static char indentChar; public static int indentLevel; private static List<string> buffer; static FileLog() { indentChar = '\t'; buffer = new List<string>(); logPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}{Path.DirectorySeparatorChar}harmony.log.txt"; } private static string IndentString() { return new string(indentChar, indentLevel); } public static void ChangeIndent(int delta) { indentLevel = Math.Max(0, indentLevel + delta); } public static void LogBuffered(string str) { lock (logPath) { buffer.Add(IndentString() + str); } } public static void LogBuffered(List<string> strings) { lock (logPath) { buffer.AddRange(strings); } } public static List<string> GetBuffer(bool clear) { lock (logPath) { List<string> result = buffer; if (clear) { buffer = new List<string>(); } return result; } } public static void SetBuffer(List<string> buffer) { lock (logPath) { FileLog.buffer = buffer; } } public static void FlushBuffer() { lock (logPath) { if (buffer.Count <= 0) { return; } using (StreamWriter streamWriter = File.AppendText(logPath)) { foreach (string item in buffer) { streamWriter.WriteLine(item); } } buffer.Clear(); } } public static void Log(string str) { lock (logPath) { using StreamWriter streamWriter = File.AppendText(logPath); streamWriter.WriteLine(IndentString() + str); } } public static void Reset() { lock (logPath) { File.Delete($"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}{Path.DirectorySeparatorChar}harmony.log.txt"); } } public unsafe static void LogBytes(long ptr, int len) { lock (logPath) { byte* ptr2 = (byte*)ptr; string text = ""; for (int i = 1; i <= len; i++) { if (text == "") { text = "# "; } text = $"{text}{*ptr2:X2} "; if (i > 1 || len == 1) { if (i % 8 == 0 || i == len) { Log(text); text = ""; } else if (i % 4 == 0) { text += " "; } } ptr2++; } byte[] destination = new byte[len]; Marshal.Copy((IntPtr)ptr, destination, 0, len); byte[] array = MD5.Create().ComputeHash(destination); StringBuilder stringBuilder = new StringBuilder(); for (int j = 0; j < array.Length; j++) { stringBuilder.Append(array[j].ToString("X2")); } Log($"HASH: {stringBuilder}"); } } } public static class AccessTools { public delegate ref U FieldRef<T, U>(T obj = default(T)); public delegate ref F FieldRef<F>(); public static BindingFlags all = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty; public static BindingFlags allDeclared = all | BindingFlags.DeclaredOnly; private static readonly MethodInfo m_PrepForRemoting = Method(typeof(Exception), "PrepForRemoting") ?? Method(typeof(Exception), "FixRemotingException"); private static readonly FastInvokeHandler PrepForRemoting = MethodInvoker.GetHandler(m_PrepForRemoting); public static bool IsMonoRuntime { get; } = (object)Type.GetType("Mono.Runtime") != null; public static Type TypeByName(string name) { if (name == null) { throw new ArgumentNullException("name"); } Type type = Type.GetType(name, throwOnError: false); if ((object)type == null) { type = (from assembly in AppDomain.CurrentDomain.GetAssemblies() select assembly.GetType(name)).FirstOrDefault((Type t) => (object)t != null); } if ((object)type == null) { type = AppDomain.CurrentDomain.GetAssemblies().SelectMany((Assembly x) => x.GetTypes()).FirstOrDefault((Type x) => x.Name == name); } if ((object)type == null) { Logger.Log(Logger.LogChannel.Warn, () => "AccessTools.TypeByName: Could not find type named " + name); } return type; } public static T FindIncludingBaseTypes<T>(Type type, Func<Type, T> func) where T : class { while (true) { T val = func(type); if (val != null) { return val; } if ((object)type == typeof(object)) { break; } type = type.BaseType; } return null; } public static T FindIncludingInnerTypes<T>(Type type, Func<Type, T> func) where T : class { T val = func(type); if (val != null) { return val; } Type[] nestedTypes = type.GetNestedTypes(all); for (int i = 0; i < nestedTypes.Length; i++) { val = FindIncludingInnerTypes(nestedTypes[i], func); if (val != null) { break; } } return val; } public static FieldInfo DeclaredField(Type type, string name) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (name == null) { throw new ArgumentNullException("name"); } FieldInfo? field = type.GetField(name, allDeclared); if ((object)field == null) { Logger.Log(Logger.LogChannel.Warn, () => $"AccessTools.DeclaredField: Could not find field for type {type} and name {name}"); } return field; } public static FieldInfo Field(Type type, string name) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (name == null) { throw new ArgumentNullException("name"); } FieldInfo? fieldInfo = FindIncludingBaseTypes(type, (Type t) => t.GetField(name, all)); if ((object)fieldInfo == null) { Logger.Log(Logger.LogChannel.Warn, () => $"AccessTools.Field: Could not find field for type {type} and name {name}"); } return fieldInfo; } public static FieldInfo DeclaredField(Type type, int idx) { if ((object)type == null) { throw new ArgumentNullException("type"); } FieldInfo? fieldInfo = GetDeclaredFields(type).ElementAtOrDefault(idx); if ((object)fieldInfo == null) { Logger.Log(Logger.LogChannel.Warn, () => $"AccessTools.DeclaredField: Could not find field for type {type} and idx {idx}"); } return fieldInfo; } public static PropertyInfo DeclaredProperty(Type type, string name) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (name == null) { throw new ArgumentNullException("name"); } try { PropertyInfo? property = type.GetProperty(name, allDeclared); if ((object)property == null) { Logger.Log(Logger.LogChannel.Warn, () => $"AccessTools.DeclaredProperty: Could not find property for type {type} and name {name}"); } return property; } catch (AmbiguousMatchException inner) { throw new AmbiguousMatchException($"Ambiguous match for property {type}::{name}", inner); } } public static MethodInfo DeclaredPropertyGetter(Type type, string name) { return DeclaredProperty(type, name)?.GetGetMethod(nonPublic: true); } public static MethodInfo DeclaredPropertySetter(Type type, string name) { return DeclaredProperty(type, name)?.GetSetMethod(nonPublic: true); } public static PropertyInfo Property(Type type, string name) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (name == null) { throw new ArgumentNullException("name"); } PropertyInfo? propertyInfo = FindIncludingBaseTypes(type, (Type t) => t.GetProperty(name, all)); if ((object)propertyInfo == null) { Logger.Log(Logger.LogChannel.Warn, () => $"AccessTools.Property: Could not find property for type {type} and name {name}"); } return propertyInfo; } public static MethodInfo PropertyGetter(Type type, string name) { return Property(type, name)?.GetGetMethod(nonPublic: true); } public static MethodInfo PropertySetter(Type type, string name) { return Property(type, name)?.GetSetMethod(nonPublic: true); } public static MethodInfo DeclaredMethod(Type type, string name, Type[] parameters = null, Type[] generics = null) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (name == null) { throw new ArgumentNullException("name"); } ParameterModifier[] modifiers = new ParameterModifier[0]; try { MethodInfo methodInfo = ((parameters != null) ? type.GetMethod(name, allDeclared, null, parameters, modifiers) : type.GetMethod(name, allDeclared)); if ((object)methodInfo == null) { Logger.Log(Logger.LogChannel.Warn, () => $"AccessTools.DeclaredMethod: Could not find method for type {type} and name {name} and parameters {parameters?.Description()}"); return null; } if (generics != null) { methodInfo = methodInfo.MakeGenericMethod(generics); } return methodInfo; } catch (AmbiguousMatchException inner) { string text = ""; if (generics != null) { text = "<" + string.Join(", ", generics.Select((Type g) => g.FullName).ToArray()) + ">"; } string text2 = ""; if (parameters != null) { text2 = string.Join(", ", parameters.Select((Type p) => p.FullName).ToArray()); } throw new AmbiguousMatchException($"Ambiguous match for {type}::{name}{text}(${text2})", inner); } } public static MethodInfo Method(Type type, string name, Type[] parameters = null, Type[] generics = null) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (name == null) { throw new ArgumentNullException("name"); } try { ParameterModifier[] modifiers = new ParameterModifier[0]; MethodInfo methodInfo; if (parameters == null) { try { methodInfo = FindIncludingBaseTypes(type, (Type t) => t.GetMethod(name, all)); } catch (AmbiguousMatchException inner) { methodInfo = FindIncludingBaseTypes(type, (Type t) => t.GetMethod(name, all, null, new Type[0], modifiers)); if ((object)methodInfo == null) { throw new AmbiguousMatchException($"Ambiguous match for {type}:{name}", inner); } } } else { methodInfo = FindIncludingBaseTypes(type, (Type t) => t.GetMethod(name, all, null, parameters, modifiers)); } if ((object)methodInfo == null) { Logger.Log(Logger.LogChannel.Warn, () => $"AccessTools.Method: Could not find method for type {type} and name {name} and parameters {parameters?.Description()}"); return null; } if (generics != null) { methodInfo = methodInfo.MakeGenericMethod(generics); } return methodInfo; } catch (AmbiguousMatchException inner2) { string text = ""; if (generics != null) { text = "<" + string.Join(", ", generics.Select((Type g) => g.FullName).ToArray()) + ">"; } string text2 = ""; if (parameters != null) { text2 = string.Join(", ", parameters.Select((Type p) => p.FullName).ToArray()); } throw new AmbiguousMatchException($"Ambiguous match for {type}::{name}{text}(${text2})", inner2); } } public static MethodInfo Method(string typeColonMethodname, Type[] parameters = null, Type[] generics = null) { if (typeColonMethodname == null) { throw new ArgumentNullException("typeColonMethodname"); } string[] array = typeColonMethodname.Split(new char[1] { ':' }); if (array.Length != 2) { throw new ArgumentException("Method must be specified as 'Namespace.Type1.Type2:MethodName", "typeColonMethodname"); } return Method(TypeByName(array[0]), array[1], parameters, generics); } public static List<string> GetMethodNames(Type type) { if ((object)type == null) { throw new ArgumentNullException("type"); } return (from m in GetDeclaredMethods(type) select m.Name).ToList(); } public static List<string> GetMethodNames(object instance) { if (instance == null) { throw new ArgumentNullException("instance"); } return GetMethodNames(instance.GetType()); } public static List<string> GetFieldNames(Type type) { if ((object)type == null) { throw new ArgumentNullException("type"); } return (from f in GetDeclaredFields(type) select f.Name).ToList(); } public static List<string> GetFieldNames(object instance) { if (instance == null) { throw new ArgumentNullException("instance"); } return GetFieldNames(instance.GetType()); } public static List<string> GetPropertyNames(Type type) { if ((object)type == null) { throw new ArgumentNullException("type"); } return (from f in GetDeclaredProperties(type) select f.Name).ToList(); } public static List<string> GetPropertyNames(object instance) { if (instance == null) { throw new ArgumentNullException("instance"); } return GetPropertyNames(instance.GetType()); } public static Type GetUnderlyingType(this MemberInfo member) { if ((object)member == null) { throw new ArgumentNullException("member"); } return member.MemberType switch { MemberTypes.Event => ((EventInfo)member).EventHandlerType, MemberTypes.Field => ((FieldInfo)member).FieldType, MemberTypes.Method => ((MethodInfo)member).ReturnType, MemberTypes.Property => ((PropertyInfo)member).PropertyType, _ => throw new ArgumentException("Member must be of type EventInfo, FieldInfo, MethodInfo, or PropertyInfo"), }; } public static ConstructorInfo DeclaredConstructor(Type type, Type[] parameters = null) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (parameters == null) { parameters = new Type[0]; } return type.GetConstructor(allDeclared, null, parameters, new ParameterModifier[0]); } public static ConstructorInfo DeclaredConstructor(Type type, Type[] parameters, bool searchForStatic) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (parameters == null) { parameters = new Type[0]; } BindingFlags bindingFlags = (searchForStatic ? BindingFlags.Instance : BindingFlags.Static); return type.GetConstructor(allDeclared & ~bindingFlags, null, parameters, new ParameterModifier[0]); } public static ConstructorInfo Constructor(Type type, Type[] parameters = null) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (parameters == null) { parameters = new Type[0]; } return FindIncludingBaseTypes(type, (Type t) => t.GetConstructor(all, null, parameters, new ParameterModifier[0])); } public static ConstructorInfo Constructor(Type type, Type[] parameters, bool searchForStatic) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (parameters == null) { parameters = new Type[0]; } BindingFlags exclude = (searchForStatic ? BindingFlags.Instance : BindingFlags.Static); return FindIncludingBaseTypes(type, (Type t) => t.GetConstructor(all & ~exclude, null, parameters, new ParameterModifier[0])); } public static List<ConstructorInfo> GetDeclaredConstructors(Type type) { if ((object)type == null) { throw new ArgumentNullException("type"); } return (from method in type.GetConstructors(allDeclared) where (object)method.DeclaringType == type select method).ToList(); } public static List<ConstructorInfo> GetDeclaredConstructors(Type type, bool? searchForStatic) { if ((object)type == null) { throw new ArgumentNullException("type"); } BindingFlags bindingFlags = BindingFlags.Default; if (searchForStatic.HasValue) { bindingFlags = (searchForStatic.Value ? BindingFlags.Instance : BindingFlags.Static); } return (from method in type.GetConstructors(allDeclared & ~bindingFlags) where (object)method.DeclaringType == type select method).ToList(); } public static List<MethodInfo> GetDeclaredMethods(Type type) { if ((object)type == null) { throw new ArgumentNullException("type"); } return type.GetMethods(allDeclared).ToList(); } public static List<PropertyInfo> GetDeclaredProperties(Type type) { if ((object)type == null) { throw new ArgumentNullException("type"); } return type.GetProperties(allDeclared).ToList(); } public static List<FieldInfo> GetDeclaredFields(Type type) { if ((object)type == null) { throw new ArgumentNullException("type"); } return type.GetFields(allDeclared).ToList(); } public static Type GetReturnedType(MethodBase methodOrConstructor) { if ((object)methodOrConstructor == null) { throw new ArgumentNullException("methodOrConstructor"); } if (methodOrConstructor is ConstructorInfo) { return typeof(void); } return ((MethodInfo)methodOrConstructor).ReturnType; } public static Type Inner(Type type, string name) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (name == null) { throw new ArgumentNullException("name"); } return FindIncludingBaseTypes(type, (Type t) => t.GetNestedType(name, all)); } public static Type FirstInner(Type type, Func<Type, bool> predicate) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } return type.GetNestedTypes(all).FirstOrDefault(predicate); } public static MethodInfo FirstMethod(Type type, Func<MethodInfo, bool> predicate) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } return type.GetMethods(allDeclared).FirstOrDefault(predicate); } public static ConstructorInfo FirstConstructor(Type type, Func<ConstructorInfo, bool> predicate) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } return type.GetConstructors(allDeclared).FirstOrDefault(predicate); } public static PropertyInfo FirstProperty(Type type, Func<PropertyInfo, bool> predicate) { if ((object)type == null) { throw new ArgumentNullException("type"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } return type.GetProperties(allDeclared).FirstOrDefault(predicate); } public static Type[] GetTypes(object[] parameters) { if (parameters == null) { return new Type[0]; } return parameters.Select((object p) => (p != null) ? p.GetType() : typeof(object)).ToArray(); } public static object[] ActualParameters(MethodBase method, object[] inputs) { if ((object)method == null) { throw new ArgumentNullException("method"); } if (inputs == null) { throw new ArgumentNullException("inputs"); } List<Type> inputTypes = inputs.Select((object obj) => obj?.GetType()).ToList(); return (from p in method.GetParameters() select p.ParameterType).Select(delegate(Type pType) { int num = inputTypes.FindIndex((Type inType) => inputTypes != null && pType.IsAssignableFrom(inType)); return (num >= 0) ? inputs[num] : GetDefaultValue(pType); }).ToArray(); } public static FieldRef<T, U> FieldRefAccess<T, U>(string fieldName) { return FieldRefAccess<T, U>(typeof(T).GetField(fieldName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic)); } public static FieldRef<T, U> FieldRefAccess<T, U>(FieldInfo fieldInfo) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } if (!typeof(U).IsAssignableFrom(fieldInfo.FieldType)) { throw new ArgumentException("FieldInfo type does not match FieldRefAccess return type."); } if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T)))) { throw new MissingFieldException(typeof(T).Name, fieldInfo.Name); } DynamicMethodDefinition val = new DynamicMethodDefinition("__refget_" + typeof(T).Name + "_fi_" + fieldInfo.Name, typeof(U).MakeByRefType(), new Type[1] { typeof(T) }); ILGenerator iLGenerator = val.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldflda, fieldInfo); iLGenerator.Emit(OpCodes.Ret); return Extensions.CreateDelegate<FieldRef<T, U>>((MethodBase)val.Generate()); } public static ref U FieldRefAccess<T, U>(T instance, string fieldName) { return ref FieldRefAccess<T, U>(fieldName)(instance); } public static FieldRef<object, F> FieldRefAccess<F>(Type type, string fieldName) { return FieldRefAccess<object, F>(Field(type, fieldName)); } public static ref F StaticFieldRefAccess<T, F>(string fieldName) { return ref StaticFieldRefAccess<F>(typeof(T), fieldName); } public static ref F StaticFieldRefAccess<T, F>(FieldInfo fieldInfo) { return ref StaticFieldRefAccess<F>(fieldInfo)(); } public static FieldRef<F> StaticFieldRefAccess<F>(FieldInfo fieldInfo) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } Type declaringType = fieldInfo.DeclaringType; DynamicMethodDefinition val = new DynamicMethodDefinition("__refget_" + declaringType.Name + "_static_fi_" + fieldInfo.Name, typeof(F).MakeByRefType(), new Type[0]); ILGenerator iLGenerator = val.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldsflda, fieldInfo); iLGenerator.Emit(OpCodes.Ret); return Extensions.CreateDelegate<FieldRef<F>>((MethodBase)val.Generate()); } public static ref F StaticFieldRefAccess<F>(Type type, string fieldName) { return ref StaticFieldRefAccess<F>(type.GetField(fieldName, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic))(); } public static MethodBase GetOutsideCaller() { StackFrame[] frames = new StackTrace(fNeedFileInfo: true).GetFrames(); for (int i = 0; i < frames.Length; i++) { Met
BepInEx/core/BepInEx.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.ConsoleUtil; using BepInEx.Logging; using BepInEx.Unix; using HarmonyLib; using HarmonyLib.Tools; using Microsoft.Win32.SafeHandles; using Mono.Cecil; using MonoMod.Utils; using UnityEngine; using UnityInjector.ConsoleUtil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BepInEx")] [assembly: AssemblyDescription("Unity plugin injection framework")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BepInEx")] [assembly: AssemblyCopyright("Copyright © Bepis 2018")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4ffba620-f5ed-47f9-b90c-dad1316fd9b9")] [assembly: InternalsVisibleTo("BepInEx.Preloader")] [assembly: InternalsVisibleTo("BepInExTests")] [assembly: AssemblyFileVersion("5.4.22.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.4.22.0")] [module: UnverifiableCode] namespace UnityEngine { internal sealed class UnityLogWriter { [MethodImpl(MethodImplOptions.InternalCall)] public static extern void WriteStringToUnityLogImpl(string s); [MethodImpl(MethodImplOptions.InternalCall)] public static extern void WriteStringToUnityLog(string s); } } namespace UnityInjector.ConsoleUtil { internal class ConsoleEncoding : Encoding { private byte[] _byteBuffer = new byte[256]; private char[] _charBuffer = new char[256]; private byte[] _zeroByte = new byte[0]; private char[] _zeroChar = new char[0]; private readonly uint _codePage; public override int CodePage => (int)_codePage; public static Encoding OutputEncoding => new ConsoleEncoding(ConsoleCodePage); public static uint ConsoleCodePage { get { return GetConsoleOutputCP(); } set { SetConsoleOutputCP(value); } } private void ExpandByteBuffer(int count) { if (_byteBuffer.Length < count) { _byteBuffer = new byte[count]; } } private void ExpandCharBuffer(int count) { if (_charBuffer.Length < count) { _charBuffer = new char[count]; } } private void ReadByteBuffer(byte[] bytes, int index, int count) { for (int i = 0; i < count; i++) { bytes[index + i] = _byteBuffer[i]; } } private void ReadCharBuffer(char[] chars, int index, int count) { for (int i = 0; i < count; i++) { chars[index + i] = _charBuffer[i]; } } private void WriteByteBuffer(byte[] bytes, int index, int count) { ExpandByteBuffer(count); for (int i = 0; i < count; i++) { _byteBuffer[i] = bytes[index + i]; } } private void WriteCharBuffer(char[] chars, int index, int count) { ExpandCharBuffer(count); for (int i = 0; i < count; i++) { _charBuffer[i] = chars[index + i]; } } public static uint GetActiveCodePage() { return GetACP(); } private ConsoleEncoding(uint codePage) { _codePage = codePage; } public static ConsoleEncoding GetEncoding(uint codePage) { return new ConsoleEncoding(codePage); } public override int GetByteCount(char[] chars, int index, int count) { WriteCharBuffer(chars, index, count); return WideCharToMultiByte(_codePage, 0u, _charBuffer, count, _zeroByte, 0, IntPtr.Zero, IntPtr.Zero); } public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { int byteCount = GetByteCount(chars, charIndex, charCount); WriteCharBuffer(chars, charIndex, charCount); ExpandByteBuffer(byteCount); int result = WideCharToMultiByte(_codePage, 0u, chars, charCount, _byteBuffer, byteCount, IntPtr.Zero, IntPtr.Zero); ReadByteBuffer(bytes, byteIndex, byteCount); return result; } public override int GetCharCount(byte[] bytes, int index, int count) { WriteByteBuffer(bytes, index, count); return MultiByteToWideChar(_codePage, 0u, bytes, count, _zeroChar, 0); } public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { int charCount = GetCharCount(bytes, byteIndex, byteCount); WriteByteBuffer(bytes, byteIndex, byteCount); ExpandCharBuffer(charCount); int result = MultiByteToWideChar(_codePage, 0u, bytes, byteCount, _charBuffer, charCount); ReadCharBuffer(chars, charIndex, charCount); return result; } public override int GetMaxByteCount(int charCount) { return charCount * 2; } public override int GetMaxCharCount(int byteCount) { return byteCount; } [DllImport("kernel32.dll")] private static extern uint GetConsoleOutputCP(); [DllImport("kernel32.dll")] private static extern uint GetACP(); [DllImport("kernel32.dll", SetLastError = true)] private static extern int MultiByteToWideChar(uint codePage, uint dwFlags, [In][MarshalAs(UnmanagedType.LPArray)] byte[] lpMultiByteStr, int cbMultiByte, [Out][MarshalAs(UnmanagedType.LPWStr)] char[] lpWideCharStr, int cchWideChar); [DllImport("kernel32.dll")] private static extern IntPtr SetConsoleOutputCP(uint codepage); [DllImport("kernel32.dll", SetLastError = true)] private static extern int WideCharToMultiByte(uint codePage, uint dwFlags, [In][MarshalAs(UnmanagedType.LPWStr)] char[] lpWideCharStr, int cchWideChar, [Out][MarshalAs(UnmanagedType.LPArray)] byte[] lpMultiByteStr, int cbMultiByte, IntPtr lpDefaultChar, IntPtr lpUsedDefaultChar); } internal class ConsoleWindow { [UnmanagedFunctionPointer(CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] private delegate bool SetForegroundWindowDelegate(IntPtr hWnd); [UnmanagedFunctionPointer(CallingConvention.Winapi)] private delegate IntPtr GetForegroundWindowDelegate(); [UnmanagedFunctionPointer(CallingConvention.Winapi)] private delegate IntPtr GetSystemMenuDelegate(IntPtr hwnd, bool bRevert); [UnmanagedFunctionPointer(CallingConvention.Winapi)] private delegate bool DeleteMenuDelegate(IntPtr hMenu, uint uPosition, uint uFlags); private const uint SC_CLOSE = 61536u; private const uint MF_BYCOMMAND = 0u; private const uint LOAD_LIBRARY_SEARCH_SYSTEM32 = 2048u; public static IntPtr ConsoleOutHandle; public static IntPtr OriginalStdoutHandle; private static bool methodsInited; private static SetForegroundWindowDelegate setForeground; private static GetForegroundWindowDelegate getForeground; private static GetSystemMenuDelegate getSystemMenu; private static DeleteMenuDelegate deleteMenu; public static bool IsAttached { get; private set; } public static string Title { set { if (IsAttached) { if (value == null) { throw new ArgumentNullException("value"); } if (value.Length > 24500) { throw new InvalidOperationException("Console title too long"); } if (!SetConsoleTitle(value)) { throw new InvalidOperationException("Console title invalid"); } } } } public static void Attach() { if (!IsAttached) { Initialize(); if (OriginalStdoutHandle == IntPtr.Zero) { OriginalStdoutHandle = GetStdHandle(-11); } IntPtr hWnd = getForeground(); GetConsoleWindow(); if (GetConsoleWindow() == IntPtr.Zero && !AllocConsole()) { throw new Exception("AllocConsole() failed"); } setForeground(hWnd); ConsoleOutHandle = CreateFile("CONOUT$", 3221225472u, 2, IntPtr.Zero, 3, 0, IntPtr.Zero); Kon.conOut = ConsoleOutHandle; if (!SetStdHandle(-11, ConsoleOutHandle)) { throw new Exception("SetStdHandle() failed"); } if (OriginalStdoutHandle != IntPtr.Zero && ConsoleManager.ConfigConsoleOutRedirectType.Value == ConsoleManager.ConsoleOutRedirectType.ConsoleOut) { CloseHandle(OriginalStdoutHandle); } IsAttached = true; } } public static void PreventClose() { if (IsAttached) { Initialize(); IntPtr consoleWindow = GetConsoleWindow(); IntPtr intPtr = getSystemMenu(consoleWindow, bRevert: false); if (intPtr != IntPtr.Zero) { deleteMenu(intPtr, 61536u, 0u); } } } public static void Detach() { if (IsAttached) { if (!CloseHandle(ConsoleOutHandle)) { throw new Exception("CloseHandle() failed"); } ConsoleOutHandle = IntPtr.Zero; if (!FreeConsole()) { throw new Exception("FreeConsole() failed"); } if (!SetStdHandle(-11, OriginalStdoutHandle)) { throw new Exception("SetStdHandle() failed"); } IsAttached = false; } } private static void Initialize() { if (!methodsInited) { methodsInited = true; IntPtr hModule = LoadLibraryEx("user32.dll", IntPtr.Zero, 2048u); setForeground = DynDll.AsDelegate<SetForegroundWindowDelegate>(GetProcAddress(hModule, "SetForegroundWindow")); getForeground = DynDll.AsDelegate<GetForegroundWindowDelegate>(GetProcAddress(hModule, "GetForegroundWindow")); getSystemMenu = DynDll.AsDelegate<GetSystemMenuDelegate>(GetProcAddress(hModule, "GetSystemMenu")); deleteMenu = DynDll.AsDelegate<DeleteMenuDelegate>(GetProcAddress(hModule, "DeleteMenu")); } } [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool AllocConsole(); [DllImport("kernel32.dll")] private static extern IntPtr GetConsoleWindow(); [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool CloseHandle(IntPtr handle); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CreateFile(string fileName, uint desiredAccess, int shareMode, IntPtr securityAttributes, int creationDisposition, int flagsAndAttributes, IntPtr templateFile); [DllImport("kernel32.dll")] private static extern bool FreeConsole(); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetStdHandle(int nStdHandle); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetStdHandle(int nStdHandle, IntPtr hConsoleOutput); [DllImport("kernel32.dll", BestFitMapping = true, CharSet = CharSet.Auto, SetLastError = true)] private static extern bool SetConsoleTitle(string title); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, uint dwFlags); } internal static class SafeConsole { private delegate ConsoleColor GetColorDelegate(); private delegate void SetColorDelegate(ConsoleColor value); private delegate string GetStringDelegate(); private delegate void SetStringDelegate(string value); private static GetColorDelegate _getBackgroundColor; private static SetColorDelegate _setBackgroundColor; private static GetColorDelegate _getForegroundColor; private static SetColorDelegate _setForegroundColor; private static GetStringDelegate _getTitle; private static SetStringDelegate _setTitle; public static bool BackgroundColorExists { get; private set; } public static ConsoleColor BackgroundColor { get { return _getBackgroundColor(); } set { _setBackgroundColor(value); } } public static bool ForegroundColorExists { get; private set; } public static ConsoleColor ForegroundColor { get { return _getForegroundColor(); } set { _setForegroundColor(value); } } public static bool TitleExists { get; private set; } public static string Title { get { return _getTitle(); } set { _setTitle(value); } } static SafeConsole() { InitColors(typeof(Console)); } private static void InitColors(Type tConsole) { MethodInfo method = tConsole.GetMethod("get_ForegroundColor", BindingFlags.Static | BindingFlags.Public); MethodInfo method2 = tConsole.GetMethod("set_ForegroundColor", BindingFlags.Static | BindingFlags.Public); MethodInfo method3 = tConsole.GetMethod("get_BackgroundColor", BindingFlags.Static | BindingFlags.Public); MethodInfo method4 = tConsole.GetMethod("set_BackgroundColor", BindingFlags.Static | BindingFlags.Public); MethodInfo method5 = tConsole.GetMethod("get_Title", BindingFlags.Static | BindingFlags.Public); MethodInfo method6 = tConsole.GetMethod("set_Title", BindingFlags.Static | BindingFlags.Public); _setForegroundColor = (((object)method2 != null) ? ((SetColorDelegate)Delegate.CreateDelegate(typeof(SetColorDelegate), method2)) : ((SetColorDelegate)delegate { })); _setBackgroundColor = (((object)method4 != null) ? ((SetColorDelegate)Delegate.CreateDelegate(typeof(SetColorDelegate), method4)) : ((SetColorDelegate)delegate { })); _getForegroundColor = (((object)method != null) ? ((GetColorDelegate)Delegate.CreateDelegate(typeof(GetColorDelegate), method)) : ((GetColorDelegate)(() => ConsoleColor.Gray))); _getBackgroundColor = (((object)method3 != null) ? ((GetColorDelegate)Delegate.CreateDelegate(typeof(GetColorDelegate), method3)) : ((GetColorDelegate)(() => ConsoleColor.Black))); _getTitle = (((object)method5 != null) ? ((GetStringDelegate)Delegate.CreateDelegate(typeof(GetStringDelegate), method5)) : ((GetStringDelegate)(() => string.Empty))); _setTitle = (((object)method6 != null) ? ((SetStringDelegate)Delegate.CreateDelegate(typeof(SetStringDelegate), method6)) : ((SetStringDelegate)delegate { })); BackgroundColorExists = _setBackgroundColor != null && _getBackgroundColor != null; ForegroundColorExists = _setForegroundColor != null && _getForegroundColor != null; TitleExists = _setTitle != null && _getTitle != null; } } } namespace BepInEx { public static class UnityInput { private static IInputSystem _current; public static IInputSystem Current { get { if (_current != null) { return _current; } try { try { Input.GetKeyDown((KeyCode)97); _current = new LegacyInputSystem(); Logger.LogDebug("[UnityInput] Using LegacyInputSystem"); } catch (InvalidOperationException) { _current = new NewInputSystem(); Logger.LogDebug("[UnityInput] Using NewInputSystem"); } } catch (Exception arg) { Logger.LogWarning($"[UnityInput] Failed to detect available input systems - {arg}"); _current = new NullInputSystem(); } return _current; } } public static bool LegacyInputSystemAvailable => Current is LegacyInputSystem; } public interface IInputSystem { Vector3 mousePosition { get; } Vector2 mouseScrollDelta { get; } bool mousePresent { get; } bool anyKey { get; } bool anyKeyDown { get; } IEnumerable<KeyCode> SupportedKeyCodes { get; } bool GetKey(string name); bool GetKey(KeyCode key); bool GetKeyDown(string name); bool GetKeyDown(KeyCode key); bool GetKeyUp(string name); bool GetKeyUp(KeyCode key); bool GetMouseButton(int button); bool GetMouseButtonDown(int button); bool GetMouseButtonUp(int button); void ResetInputAxes(); } internal class NewInputSystem : IInputSystem { private delegate bool GetButtonDelegate(KeyCode key); private delegate Vector2 GetMouseVectorDelegate(); private delegate bool GetMouseStateDelegate(); private static bool initialized; private static readonly Dictionary<KeyCode, int> keyCodeToIndex = new Dictionary<KeyCode, int>(); private static readonly Dictionary<string, string> keyToKeyCodeNameRemap = new Dictionary<string, string> { ["LeftCtrl"] = "LeftControl", ["RightCtrl"] = "RightControl", ["LeftMeta"] = "LeftApple", ["RightMeta"] = "RightApple", ["ContextMenu"] = "Menu", ["PrintScreen"] = "Print", ["Enter"] = "Return" }; private static GetButtonDelegate _getKey; private static GetButtonDelegate _getKeyDown; private static GetButtonDelegate _getKeyUp; private static GetButtonDelegate _getMouseButton; private static GetButtonDelegate _getMouseButtonDown; private static GetButtonDelegate _getMouseButtonUp; private static GetMouseVectorDelegate _getMousePosition; private static GetMouseVectorDelegate _getMouseScrollDelta; private static GetMouseStateDelegate _getMousePresent; private static GetMouseStateDelegate _getKeyboardAnyKeyIsPressed; private static GetMouseStateDelegate _getKeyboardAnyKeyWasPressedThisFrame; public Vector3 mousePosition => Vector2.op_Implicit(_getMousePosition()); public Vector2 mouseScrollDelta => _getMouseScrollDelta(); public bool mousePresent => _getMousePresent(); public bool anyKey { get { if (_getKeyboardAnyKeyIsPressed()) { return true; } if (!GetMouseButton(0) && !GetMouseButton(1) && !GetMouseButton(2) && !GetMouseButton(3)) { return GetMouseButton(4); } return true; } } public bool anyKeyDown { get { if (_getKeyboardAnyKeyWasPressedThisFrame()) { return true; } if (!GetMouseButtonDown(0) && !GetMouseButtonDown(1) && !GetMouseButtonDown(2) && !GetMouseButtonDown(3)) { return GetMouseButtonDown(4); } return true; } } public IEnumerable<KeyCode> SupportedKeyCodes => keyCodeToIndex.Keys.ToArray(); public NewInputSystem() { Init(); } private static void Init() { //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (initialized) { return; } Assembly assembly = Assembly.Load("Unity.InputSystem"); Type type = assembly.GetType("UnityEngine.InputSystem.Key"); foreach (object value3 in Enum.GetValues(type)) { string text = value3.ToString(); int value = (int)value3; string value2; if (text.StartsWith("Numpad")) { text = text.Replace("Numpad", "Keypad"); } else if (text.StartsWith("Digit")) { text = text.Replace("Digit", "Alpha"); } else if (keyToKeyCodeNameRemap.TryGetValue(text, out value2)) { text = value2; } if (TryEnumParse<KeyCode>(text, out var val)) { keyCodeToIndex[val] = value; } else { Logger.LogDebug("[UnityInput] Unknown key name: " + text + ", skipping remapping"); } } FieldInfo keyCodeToIndexField = AccessTools.Field(typeof(NewInputSystem), "keyCodeToIndex"); MethodInfo tryGetValueMethod = AccessTools.Method(typeof(Dictionary<KeyCode, int>), "TryGetValue", (Type[])null, (Type[])null); Type type2 = assembly.GetType("UnityEngine.InputSystem.Keyboard"); MethodInfo currentProperty = AccessTools.PropertyGetter(type2, "current"); MethodInfo indexer = AccessTools.Method(type2, "get_Item", new Type[1] { type }, (Type[])null); Type buttonControlType = assembly.GetType("UnityEngine.InputSystem.Controls.ButtonControl"); _getKey = GenerateKeyGetter("InputSystemGetKey", "isPressed"); _getKeyDown = GenerateKeyGetter("InputSystemGetKeyDown", "wasPressedThisFrame"); _getKeyUp = GenerateKeyGetter("InputSystemGetKeyUp", "wasReleasedThisFrame"); Type mouseType = assembly.GetType("UnityEngine.InputSystem.Mouse"); MethodInfo mouseCurrentProperty = AccessTools.PropertyGetter(mouseType, "current"); string[] source = new string[5] { "leftButton", "rightButton", "middleButton", "backButton", "forwardButton" }; MethodInfo[] buttonPropertyGetters = source.Select((string p) => AccessTools.PropertyGetter(mouseType, p)).ToArray(); _getMouseButton = GenerateMouseGetter("InputSystemGetMouseButton", "isPressed"); _getMouseButtonDown = GenerateMouseGetter("InputSystemGetMouseButtonDown", "wasPressedThisFrame"); _getMouseButtonUp = GenerateMouseGetter("InputSystemGetMouseButtonUp", "wasReleasedThisFrame"); _getMousePosition = GetPositionDelegate("InputSystemGetMousePosition", "position"); _getMouseScrollDelta = GetPositionDelegate("InputSystemGetMouseScrollDelta", "scroll"); DynamicMethodDefinition val2 = new DynamicMethodDefinition("InputSystemGetMouseEnabled", typeof(bool), Type.EmptyTypes); ILGenerator iLGenerator = val2.GetILGenerator(); iLGenerator.Emit(OpCodes.Call, mouseCurrentProperty); iLGenerator.Emit(OpCodes.Callvirt, AccessTools.PropertyGetter(mouseType, "enabled")); iLGenerator.Emit(OpCodes.Ret); _getMousePresent = Extensions.CreateDelegate<GetMouseStateDelegate>((MethodBase)val2.Generate()); MethodInfo anyKeyProperty = AccessTools.PropertyGetter(type2, "anyKey"); _getKeyboardAnyKeyIsPressed = GetAnyKeyDelegate("InputSystemGetKeyboardAnyKeyIsPressed", "isPressed"); _getKeyboardAnyKeyWasPressedThisFrame = GetAnyKeyDelegate("InputSystemGetKeyboardAnyKeyWasPressedThisFrame", "wasPressedThisFrame"); initialized = true; GetButtonDelegate GenerateKeyGetter(string name, string property) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) MethodInfo meth4 = AccessTools.PropertyGetter(buttonControlType, property); DynamicMethodDefinition val6 = new DynamicMethodDefinition(name, typeof(bool), new Type[1] { typeof(KeyCode) }); ILGenerator iLGenerator4 = val6.GetILGenerator(); LocalBuilder local = iLGenerator4.DeclareLocal(typeof(int)); Label label2 = iLGenerator4.DefineLabel(); iLGenerator4.Emit(OpCodes.Ldsfld, keyCodeToIndexField); iLGenerator4.Emit(OpCodes.Ldarg_0); iLGenerator4.Emit(OpCodes.Ldloca, local); iLGenerator4.Emit(OpCodes.Callvirt, tryGetValueMethod); iLGenerator4.Emit(OpCodes.Brfalse, label2); iLGenerator4.Emit(OpCodes.Call, currentProperty); iLGenerator4.Emit(OpCodes.Ldloc, local); iLGenerator4.Emit(OpCodes.Callvirt, indexer); iLGenerator4.Emit(OpCodes.Callvirt, meth4); iLGenerator4.Emit(OpCodes.Ret); iLGenerator4.MarkLabel(label2); iLGenerator4.Emit(OpCodes.Ldc_I4_0); iLGenerator4.Emit(OpCodes.Ret); return Extensions.CreateDelegate<GetButtonDelegate>((MethodBase)val6.Generate()); } GetButtonDelegate GenerateMouseGetter(string name, string property) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown MethodInfo meth3 = AccessTools.PropertyGetter(buttonControlType, property); DynamicMethodDefinition val5 = new DynamicMethodDefinition(name, typeof(bool), new Type[1] { typeof(KeyCode) }); ILGenerator il = val5.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, 323); il.Emit(OpCodes.Sub); Label[] array = buttonPropertyGetters.Select((MethodInfo _) => il.DefineLabel()).ToArray(); Label label = il.DefineLabel(); il.Emit(OpCodes.Switch, array); il.Emit(OpCodes.Br, label); for (int i = 0; i < array.Length; i++) { il.MarkLabel(array[i]); il.Emit(OpCodes.Call, mouseCurrentProperty); il.Emit(OpCodes.Callvirt, buttonPropertyGetters[i]); il.Emit(OpCodes.Callvirt, meth3); il.Emit(OpCodes.Ret); } il.MarkLabel(label); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ret); return Extensions.CreateDelegate<GetButtonDelegate>((MethodBase)val5.Generate()); } GetMouseStateDelegate GetAnyKeyDelegate(string name, string property) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) MethodInfo meth = AccessTools.PropertyGetter(buttonControlType, property); DynamicMethodDefinition val3 = new DynamicMethodDefinition(name, typeof(bool), Type.EmptyTypes); ILGenerator iLGenerator2 = val3.GetILGenerator(); iLGenerator2.Emit(OpCodes.Call, currentProperty); iLGenerator2.Emit(OpCodes.Callvirt, anyKeyProperty); iLGenerator2.Emit(OpCodes.Callvirt, meth); iLGenerator2.Emit(OpCodes.Ret); return Extensions.CreateDelegate<GetMouseStateDelegate>((MethodBase)val3.Generate()); } GetMouseVectorDelegate GetPositionDelegate(string name, string property) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) MethodInfo methodInfo = AccessTools.PropertyGetter(mouseType, property); MethodInfo meth2 = AccessTools.Method(methodInfo.ReturnType, "ReadValue", (Type[])null, (Type[])null); DynamicMethodDefinition val4 = new DynamicMethodDefinition(name, typeof(Vector2), Type.EmptyTypes); ILGenerator iLGenerator3 = val4.GetILGenerator(); iLGenerator3.Emit(OpCodes.Call, mouseCurrentProperty); iLGenerator3.Emit(OpCodes.Callvirt, methodInfo); iLGenerator3.Emit(OpCodes.Callvirt, meth2); iLGenerator3.Emit(OpCodes.Ret); return Extensions.CreateDelegate<GetMouseVectorDelegate>((MethodBase)val4.Generate()); } } public bool GetKey(string name) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _getKey(GetKeyCode(name)); } public bool GetKey(KeyCode key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return _getKey(key); } public bool GetKeyDown(string name) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _getKeyDown(GetKeyCode(name)); } public bool GetKeyDown(KeyCode key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return _getKeyDown(key); } public bool GetKeyUp(string name) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _getKeyUp(GetKeyCode(name)); } public bool GetKeyUp(KeyCode key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return _getKeyUp(key); } public bool GetMouseButton(int button) { return _getMouseButton((KeyCode)(323 + button)); } public bool GetMouseButtonDown(int button) { return _getMouseButtonDown((KeyCode)(323 + button)); } public bool GetMouseButtonUp(int button) { return _getMouseButtonUp((KeyCode)(323 + button)); } public void ResetInputAxes() { } private static KeyCode GetKeyCode(string name) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) return (KeyCode)Enum.Parse(typeof(KeyCode), name, ignoreCase: true); } private static bool TryEnumParse<T>(string name, out T val) { try { val = (T)Enum.Parse(typeof(T), name, ignoreCase: true); return true; } catch (Exception) { val = default(T); return false; } } } internal class LegacyInputSystem : IInputSystem { public Vector3 mousePosition => Input.mousePosition; public Vector2 mouseScrollDelta => Input.mouseScrollDelta; public bool mousePresent => Input.mousePresent; public bool anyKey => Input.anyKey; public bool anyKeyDown => Input.anyKeyDown; public IEnumerable<KeyCode> SupportedKeyCodes { get; } = (KeyCode[])Enum.GetValues(typeof(KeyCode)); public bool GetKey(string name) { return Input.GetKey(name); } public bool GetKey(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Input.GetKey(key); } public bool GetKeyDown(string name) { return Input.GetKeyDown(name); } public bool GetKeyDown(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Input.GetKeyDown(key); } public bool GetKeyUp(string name) { return Input.GetKeyUp(name); } public bool GetKeyUp(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Input.GetKeyUp(key); } public bool GetMouseButton(int button) { return Input.GetMouseButton(button); } public bool GetMouseButtonDown(int button) { return Input.GetMouseButtonDown(button); } public bool GetMouseButtonUp(int button) { return Input.GetMouseButtonUp(button); } public void ResetInputAxes() { Input.ResetInputAxes(); } } internal class NullInputSystem : IInputSystem { private static readonly KeyCode[] NoKeys = (KeyCode[])(object)new KeyCode[0]; public Vector3 mousePosition => Vector3.zero; public Vector2 mouseScrollDelta => Vector2.zero; public bool mousePresent => false; public bool anyKey => false; public bool anyKeyDown => false; public IEnumerable<KeyCode> SupportedKeyCodes => NoKeys; public bool GetKey(string name) { return false; } public bool GetKey(KeyCode key) { return false; } public bool GetKeyDown(string name) { return false; } public bool GetKeyDown(KeyCode key) { return false; } public bool GetKeyUp(string name) { return false; } public bool GetKeyUp(KeyCode key) { return false; } public bool GetMouseButton(int button) { return false; } public bool GetMouseButtonDown(int button) { return false; } public bool GetMouseButtonUp(int button) { return false; } public void ResetInputAxes() { } } internal static class ConsoleManager { public enum ConsoleOutRedirectType { [Description("Auto")] Auto, [Description("Console Out")] ConsoleOut, [Description("Standard Out")] StandardOut } private const uint SHIFT_JIS_CP = 932u; private static readonly bool? EnableConsoleArgOverride; private const string ENABLE_CONSOLE_ARG = "--enable-console"; public static readonly ConfigEntry<bool> ConfigConsoleEnabled; public static readonly ConfigEntry<bool> ConfigPreventClose; public static readonly ConfigEntry<bool> ConfigConsoleShiftJis; public static readonly ConfigEntry<ConsoleOutRedirectType> ConfigConsoleOutRedirectType; internal static IConsoleDriver Driver { get; set; } public static bool ConsoleActive => Driver?.ConsoleActive ?? false; public static TextWriter StandardOutStream => Driver?.StandardOut; public static TextWriter ConsoleStream => Driver?.ConsoleOut; public static bool ConsoleEnabled => EnableConsoleArgOverride ?? ConfigConsoleEnabled.Value; static ConsoleManager() { ConfigConsoleEnabled = ConfigFile.CoreConfig.Bind("Logging.Console", "Enabled", defaultValue: false, "Enables showing a console for log output."); ConfigPreventClose = ConfigFile.CoreConfig.Bind("Logging.Console", "PreventClose", defaultValue: false, "If enabled, will prevent closing the console (either by deleting the close button or in other platform-specific way)."); ConfigConsoleShiftJis = ConfigFile.CoreConfig.Bind("Logging.Console", "ShiftJisEncoding", defaultValue: false, "If true, console is set to the Shift-JIS encoding, otherwise UTF-8 encoding."); ConfigConsoleOutRedirectType = ConfigFile.CoreConfig.Bind("Logging.Console", "StandardOutType", ConsoleOutRedirectType.Auto, new StringBuilder().AppendLine("Hints console manager on what handle to assign as StandardOut. Possible values:").AppendLine("Auto - lets BepInEx decide how to redirect console output").AppendLine("ConsoleOut - prefer redirecting to console output; if possible, closes original standard output") .AppendLine("StandardOut - prefer redirecting to standard output; if possible, closes console out") .ToString()); try { string[] commandLineArgs = Environment.GetCommandLineArgs(); for (int i = 0; i < commandLineArgs.Length; i++) { if (commandLineArgs[i] == "--enable-console" && i + 1 < commandLineArgs.Length && bool.TryParse(commandLineArgs[i + 1], out var result)) { EnableConsoleArgOverride = result; } } } catch (Exception) { } } public static void Initialize(bool alreadyActive) { if (PlatformHelper.Is((Platform)8)) { Driver = new LinuxConsoleDriver(); } else if (PlatformHelper.Is((Platform)37)) { Driver = new WindowsConsoleDriver(); } Driver.Initialize(alreadyActive); } private static void DriverCheck() { if (Driver == null) { throw new InvalidOperationException("Driver has not been initialized"); } } public static void CreateConsole() { if (!ConsoleActive) { DriverCheck(); uint codepage = (ConfigConsoleShiftJis.Value ? 932u : ((uint)Encoding.UTF8.CodePage)); Driver.CreateConsole(codepage); if (ConfigPreventClose.Value) { Driver.PreventClose(); } } } public static void DetachConsole() { if (ConsoleActive) { DriverCheck(); Driver.DetachConsole(); } } public static void SetConsoleTitle(string title) { DriverCheck(); Driver.SetConsoleTitle(title); } public static void SetConsoleColor(ConsoleColor color) { DriverCheck(); Driver.SetConsoleColor(color); } } internal interface IConsoleDriver { TextWriter StandardOut { get; } TextWriter ConsoleOut { get; } bool ConsoleActive { get; } bool ConsoleIsExternal { get; } void PreventClose(); void Initialize(bool alreadyActive); void CreateConsole(uint codepage); void DetachConsole(); void SetConsoleColor(ConsoleColor color); void SetConsoleTitle(string title); } internal class WindowsConsoleDriver : IConsoleDriver { private static readonly ConstructorInfo FileStreamCtor = new ConstructorInfo[2] { AccessTools.Constructor(typeof(FileStream), new Type[2] { typeof(SafeFileHandle), typeof(FileAccess) }, false), AccessTools.Constructor(typeof(FileStream), new Type[2] { typeof(IntPtr), typeof(FileAccess) }, false) }.FirstOrDefault((ConstructorInfo m) => (object)m != null); public TextWriter StandardOut { get; private set; } public TextWriter ConsoleOut { get; private set; } public bool ConsoleActive { get; private set; } public bool ConsoleIsExternal => true; public void PreventClose() { ConsoleWindow.PreventClose(); } public void Initialize(bool alreadyActive) { ConsoleActive = alreadyActive; StandardOut = Console.Out; } private static FileStream OpenFileStream(IntPtr handle) { SafeFileHandle safeFileHandle = new SafeFileHandle(handle, ownsHandle: false); object[] args = AccessTools.ActualParameters((MethodBase)FileStreamCtor, new object[3] { safeFileHandle, safeFileHandle.DangerousGetHandle(), FileAccess.Write }); return (FileStream)Activator.CreateInstance(typeof(FileStream), args); } public void CreateConsole(uint codepage) { ConsoleWindow.Attach(); ConsoleEncoding.ConsoleCodePage = codepage; IntPtr outHandle = GetOutHandle(); if (outHandle == IntPtr.Zero) { StandardOut = TextWriter.Null; ConsoleOut = TextWriter.Null; return; } FileStream stream = OpenFileStream(outHandle); StandardOut = new StreamWriter(stream, Utility.UTF8NoBom) { AutoFlush = true }; FileStream stream2 = OpenFileStream(ConsoleWindow.ConsoleOutHandle); ConsoleOut = new StreamWriter(stream2, ConsoleEncoding.OutputEncoding) { AutoFlush = true }; ConsoleActive = true; } private IntPtr GetOutHandle() { switch (ConsoleManager.ConfigConsoleOutRedirectType.Value) { case ConsoleManager.ConsoleOutRedirectType.ConsoleOut: return ConsoleWindow.ConsoleOutHandle; case ConsoleManager.ConsoleOutRedirectType.StandardOut: return ConsoleWindow.OriginalStdoutHandle; default: if (!(ConsoleWindow.OriginalStdoutHandle != IntPtr.Zero)) { return ConsoleWindow.ConsoleOutHandle; } return ConsoleWindow.OriginalStdoutHandle; } } public void DetachConsole() { ConsoleWindow.Detach(); ConsoleOut.Close(); ConsoleOut = null; ConsoleActive = false; } public void SetConsoleColor(ConsoleColor color) { SafeConsole.ForegroundColor = color; Kon.ForegroundColor = color; } public void SetConsoleTitle(string title) { ConsoleWindow.Title = title; } } public class PluginInfo : ICacheable { public BepInPlugin Metadata { get; internal set; } public IEnumerable<BepInProcess> Processes { get; internal set; } public IEnumerable<BepInDependency> Dependencies { get; internal set; } public IEnumerable<BepInIncompatibility> Incompatibilities { get; internal set; } public string Location { get; internal set; } public BaseUnityPlugin Instance { get; internal set; } internal string TypeName { get; set; } internal Version TargettedBepInExVersion { get; set; } void ICacheable.Save(BinaryWriter bw) { bw.Write(TypeName); bw.Write(Metadata.GUID); bw.Write(Metadata.Name); bw.Write(Metadata.Version.ToString()); List<BepInProcess> list = Processes.ToList(); bw.Write(list.Count); foreach (BepInProcess item in list) { bw.Write(item.ProcessName); } List<BepInDependency> list2 = Dependencies.ToList(); bw.Write(list2.Count); foreach (BepInDependency item2 in list2) { ((ICacheable)item2).Save(bw); } List<BepInIncompatibility> list3 = Incompatibilities.ToList(); bw.Write(list3.Count); foreach (BepInIncompatibility item3 in list3) { ((ICacheable)item3).Save(bw); } bw.Write(TargettedBepInExVersion.ToString(4)); } void ICacheable.Load(BinaryReader br) { TypeName = br.ReadString(); Metadata = new BepInPlugin(br.ReadString(), br.ReadString(), br.ReadString()); int num = br.ReadInt32(); List<BepInProcess> list = new List<BepInProcess>(num); for (int i = 0; i < num; i++) { list.Add(new BepInProcess(br.ReadString())); } Processes = list; int num2 = br.ReadInt32(); List<BepInDependency> list2 = new List<BepInDependency>(num2); for (int j = 0; j < num2; j++) { BepInDependency bepInDependency = new BepInDependency(""); ((ICacheable)bepInDependency).Load(br); list2.Add(bepInDependency); } Dependencies = list2; int num3 = br.ReadInt32(); List<BepInIncompatibility> list3 = new List<BepInIncompatibility>(num3); for (int k = 0; k < num3; k++) { BepInIncompatibility bepInIncompatibility = new BepInIncompatibility(""); ((ICacheable)bepInIncompatibility).Load(br); list3.Add(bepInIncompatibility); } Incompatibilities = list3; TargettedBepInExVersion = new Version(br.ReadString()); } public override string ToString() { return $"{Metadata?.Name} {Metadata?.Version}"; } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class BepInPlugin : Attribute { public string GUID { get; protected set; } public string Name { get; protected set; } public Version Version { get; protected set; } public BepInPlugin(string GUID, string Name, string Version) { this.GUID = GUID; this.Name = Name; try { this.Version = new Version(Version); } catch { this.Version = null; } } internal static BepInPlugin FromCecilType(TypeDefinition td) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) CustomAttribute val = MetadataHelper.GetCustomAttributes<BepInPlugin>(td, inherit: false).FirstOrDefault(); if (val == null) { return null; } CustomAttributeArgument val2 = val.ConstructorArguments[0]; string gUID = (string)((CustomAttributeArgument)(ref val2)).Value; val2 = val.ConstructorArguments[1]; string name = (string)((CustomAttributeArgument)(ref val2)).Value; val2 = val.ConstructorArguments[2]; return new BepInPlugin(gUID, name, (string)((CustomAttributeArgument)(ref val2)).Value); } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class BepInDependency : Attribute, ICacheable { [Flags] public enum DependencyFlags { HardDependency = 1, SoftDependency = 2 } public string DependencyGUID { get; protected set; } public DependencyFlags Flags { get; protected set; } public Version MinimumVersion { get; protected set; } public BepInDependency(string DependencyGUID, DependencyFlags Flags = DependencyFlags.HardDependency) { this.DependencyGUID = DependencyGUID; this.Flags = Flags; MinimumVersion = new Version(); } public BepInDependency(string DependencyGUID, string MinimumDependencyVersion) : this(DependencyGUID) { MinimumVersion = new Version(MinimumDependencyVersion); } internal static IEnumerable<BepInDependency> FromCecilType(TypeDefinition td) { return MetadataHelper.GetCustomAttributes<BepInDependency>(td, inherit: true).Select(delegate(CustomAttribute customAttribute) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) CustomAttributeArgument val = customAttribute.ConstructorArguments[0]; string dependencyGUID = (string)((CustomAttributeArgument)(ref val)).Value; val = customAttribute.ConstructorArguments[1]; object value = ((CustomAttributeArgument)(ref val)).Value; return (value is string minimumDependencyVersion) ? new BepInDependency(dependencyGUID, minimumDependencyVersion) : new BepInDependency(dependencyGUID, (DependencyFlags)value); }).ToList(); } void ICacheable.Save(BinaryWriter bw) { bw.Write(DependencyGUID); bw.Write((int)Flags); bw.Write(MinimumVersion.ToString()); } void ICacheable.Load(BinaryReader br) { DependencyGUID = br.ReadString(); Flags = (DependencyFlags)br.ReadInt32(); MinimumVersion = new Version(br.ReadString()); } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class BepInIncompatibility : Attribute, ICacheable { public string IncompatibilityGUID { get; protected set; } public BepInIncompatibility(string IncompatibilityGUID) { this.IncompatibilityGUID = IncompatibilityGUID; } internal static IEnumerable<BepInIncompatibility> FromCecilType(TypeDefinition td) { return MetadataHelper.GetCustomAttributes<BepInIncompatibility>(td, inherit: true).Select(delegate(CustomAttribute customAttribute) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) CustomAttributeArgument val = customAttribute.ConstructorArguments[0]; return new BepInIncompatibility((string)((CustomAttributeArgument)(ref val)).Value); }).ToList(); } void ICacheable.Save(BinaryWriter bw) { bw.Write(IncompatibilityGUID); } void ICacheable.Load(BinaryReader br) { IncompatibilityGUID = br.ReadString(); } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class BepInProcess : Attribute { public string ProcessName { get; protected set; } public BepInProcess(string ProcessName) { this.ProcessName = ProcessName; } internal static List<BepInProcess> FromCecilType(TypeDefinition td) { return MetadataHelper.GetCustomAttributes<BepInProcess>(td, inherit: true).Select(delegate(CustomAttribute customAttribute) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) CustomAttributeArgument val = customAttribute.ConstructorArguments[0]; return new BepInProcess((string)((CustomAttributeArgument)(ref val)).Value); }).ToList(); } } public static class MetadataHelper { internal static IEnumerable<CustomAttribute> GetCustomAttributes<T>(TypeDefinition td, bool inherit) where T : Attribute { List<CustomAttribute> list = new List<CustomAttribute>(); Type type = typeof(T); TypeDefinition val = td; do { list.AddRange(((IEnumerable<CustomAttribute>)val.CustomAttributes).Where((CustomAttribute ca) => ((MemberReference)ca.AttributeType).FullName == type.FullName)); TypeReference baseType = val.BaseType; val = ((baseType != null) ? baseType.Resolve() : null); } while (inherit && ((val != null) ? ((MemberReference)val).FullName : null) != "System.Object"); return list; } public static BepInPlugin GetMetadata(Type pluginType) { object[] customAttributes = pluginType.GetCustomAttributes(typeof(BepInPlugin), inherit: false); if (customAttributes.Length == 0) { return null; } return (BepInPlugin)customAttributes[0]; } public static BepInPlugin GetMetadata(object plugin) { return GetMetadata(plugin.GetType()); } public static T[] GetAttributes<T>(Type pluginType) where T : Attribute { return (T[])pluginType.GetCustomAttributes(typeof(T), inherit: true); } public static IEnumerable<T> GetAttributes<T>(object plugin) where T : Attribute { return GetAttributes<T>(plugin.GetType()); } public static IEnumerable<BepInDependency> GetDependencies(Type plugin) { return plugin.GetCustomAttributes(typeof(BepInDependency), inherit: true).Cast<BepInDependency>(); } } internal class BuildInfoAttribute : Attribute { public string Info { get; } public BuildInfoAttribute(string info) { Info = info; } } public abstract class BaseUnityPlugin : MonoBehaviour { public PluginInfo Info { get; } protected ManualLogSource Logger { get; } public ConfigFile Config { get; } protected BaseUnityPlugin() { BepInPlugin metadata = MetadataHelper.GetMetadata(this); if (metadata == null) { throw new InvalidOperationException("Can't create an instance of " + ((object)this).GetType().FullName + " because it inherits from BaseUnityPlugin and the BepInPlugin attribute is missing."); } if (!Chainloader.IsEditor && Chainloader.PluginInfos.TryGetValue(metadata.GUID, out var value)) { Info = value; } else { Info = new PluginInfo { Metadata = metadata, Instance = this, Dependencies = MetadataHelper.GetDependencies(((object)this).GetType()), Processes = MetadataHelper.GetAttributes<BepInProcess>(((object)this).GetType()), Location = ((object)this).GetType().Assembly.Location }; } Logger = BepInEx.Logging.Logger.CreateLogSource(metadata.Name); string text = (Chainloader.IsEditor ? "." : Paths.ConfigPath); Config = new ConfigFile(Utility.CombinePaths(text, metadata.GUID + ".cfg"), saveOnInit: false, metadata); } } public static class Paths { public static string[] DllSearchPaths { get; private set; } public static string BepInExAssemblyDirectory { get; private set; } public static string BepInExAssemblyPath { get; private set; } public static string BepInExRootPath { get; private set; } public static string ExecutablePath { get; private set; } public static string GameRootPath { get; private set; } public static string ManagedPath { get; private set; } public static string ConfigPath { get; private set; } public static string BepInExConfigPath { get; private set; } public static string CachePath { get; private set; } public static string PatcherPluginPath { get; private set; } public static string PluginPath { get; private set; } public static string ProcessName { get; private set; } internal static void SetExecutablePath(string executablePath, string bepinRootPath = null, string managedPath = null, string[] dllSearchPath = null) { ExecutablePath = executablePath; ProcessName = Path.GetFileNameWithoutExtension(executablePath); GameRootPath = (PlatformHelper.Is((Platform)73) ? Utility.ParentDirectory(executablePath, 4) : Path.GetDirectoryName(executablePath)); ManagedPath = managedPath ?? Utility.CombinePaths(GameRootPath, ProcessName + "_Data", "Managed"); BepInExRootPath = bepinRootPath ?? Path.Combine(GameRootPath, "BepInEx"); ConfigPath = Path.Combine(BepInExRootPath, "config"); BepInExConfigPath = Path.Combine(ConfigPath, "BepInEx.cfg"); PluginPath = Path.Combine(BepInExRootPath, "plugins"); PatcherPluginPath = Path.Combine(BepInExRootPath, "patchers"); BepInExAssemblyDirectory = Path.Combine(BepInExRootPath, "core"); BepInExAssemblyPath = Path.Combine(BepInExAssemblyDirectory, Assembly.GetExecutingAssembly().GetName().Name + ".dll"); CachePath = Path.Combine(BepInExRootPath, "cache"); DllSearchPaths = (dllSearchPath ?? new string[0]).Concat(new string[1] { ManagedPath }).Distinct().ToArray(); } internal static void SetManagedPath(string managedPath) { if (managedPath != null) { ManagedPath = managedPath; } } internal static void SetPluginPath(string pluginPath) { PluginPath = Utility.CombinePaths(BepInExRootPath, pluginPath); } } public sealed class ThreadingHelper : MonoBehaviour, ISynchronizeInvoke { private sealed class InvokeResult : IAsyncResult { internal bool ExceptionThrown; public bool IsCompleted { get; private set; } public WaitHandle AsyncWaitHandle { get; } public object AsyncState { get; private set; } public bool CompletedSynchronously { get; private set; } public InvokeResult() { AsyncWaitHandle = new EventWaitHandle(initialState: false, EventResetMode.ManualReset); } public void Finish(object result, bool completedSynchronously) { AsyncState = result; CompletedSynchronously = completedSynchronously; IsCompleted = true; ((EventWaitHandle)AsyncWaitHandle).Set(); } } private readonly object _invokeLock = new object(); private Action _invokeList; private Thread _mainThread; public static ThreadingHelper Instance { get; private set; } public static ISynchronizeInvoke SynchronizingObject => Instance; public bool InvokeRequired { get { if (_mainThread != null) { return _mainThread != Thread.CurrentThread; } return true; } } internal static void Initialize() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown GameObject val = new GameObject("BepInEx_ThreadingHelper"); if (Chainloader.ConfigHideBepInExGOs.Value) { ((Object)val).hideFlags = (HideFlags)61; } Object.DontDestroyOnLoad((Object)(object)val); Instance = val.AddComponent<ThreadingHelper>(); } public void StartSyncInvoke(Action action) { if (action == null) { throw new ArgumentNullException("action"); } lock (_invokeLock) { _invokeList = (Action)Delegate.Combine(_invokeList, action); } } private void Update() { if (_mainThread == null) { _mainThread = Thread.CurrentThread; } if (_invokeList == null) { return; } Action invokeList; lock (_invokeLock) { invokeList = _invokeList; _invokeList = null; } foreach (Action item in invokeList.GetInvocationList().Cast<Action>()) { try { item(); } catch (Exception ex) { LogInvocationException(ex); } } } public void StartAsyncInvoke(Func<Action> action) { if (!ThreadPool.QueueUserWorkItem(DoWork)) { throw new NotSupportedException("Failed to queue the action on ThreadPool"); } void DoWork(object _) { try { Action action2 = action(); if (action2 != null) { StartSyncInvoke(action2); } } catch (Exception ex) { LogInvocationException(ex); } } } private static void LogInvocationException(Exception ex) { Logger.Log(LogLevel.Error, ex); if (ex.InnerException != null) { Logger.Log(LogLevel.Error, "INNER: " + ex.InnerException); } } IAsyncResult ISynchronizeInvoke.BeginInvoke(Delegate method, object[] args) { InvokeResult result = new InvokeResult(); if (!InvokeRequired) { result.Finish(Invoke(), completedSynchronously: true); } else { StartSyncInvoke(delegate { result.Finish(Invoke(), completedSynchronously: false); }); } return result; object Invoke() { try { return method.DynamicInvoke(args); } catch (Exception result2) { result.ExceptionThrown = true; return result2; } } } object ISynchronizeInvoke.EndInvoke(IAsyncResult result) { InvokeResult invokeResult = (InvokeResult)result; invokeResult.AsyncWaitHandle.WaitOne(); if (invokeResult.ExceptionThrown) { throw (Exception)invokeResult.AsyncState; } return invokeResult.AsyncState; } object ISynchronizeInvoke.Invoke(Delegate method, object[] args) { IAsyncResult result = ((ISynchronizeInvoke)this).BeginInvoke(method, args); return ((ISynchronizeInvoke)this).EndInvoke(result); } } public static class ThreadingExtensions { public static IEnumerable<TOut> RunParallel<TIn, TOut>(this IEnumerable<TIn> data, Func<TIn, TOut> work, int workerCount = -1) { foreach (TOut item in data.ToList().RunParallel(work)) { yield return item; } } public static IEnumerable<TOut> RunParallel<TIn, TOut>(this IList<TIn> data, Func<TIn, TOut> work, int workerCount = -1) { if (workerCount < 0) { workerCount = Mathf.Max(2, Environment.ProcessorCount); } else if (workerCount == 0) { throw new ArgumentException("Need at least 1 worker", "workerCount"); } int perThreadCount = Mathf.CeilToInt((float)data.Count / (float)workerCount); int doneCount = 0; object lockObj = new object(); ManualResetEvent are = new ManualResetEvent(initialState: false); IEnumerable<TOut> doneItems = null; Exception exceptionThrown = null; for (int i = 0; i < workerCount; i++) { int first = i * perThreadCount; int last = Mathf.Min(first + perThreadCount, data.Count); ThreadPool.QueueUserWorkItem(delegate { List<TOut> list = new List<TOut>(perThreadCount); try { for (int j = first; j < last; j++) { if (exceptionThrown != null) { break; } list.Add(work(data[j])); } } catch (Exception ex) { exceptionThrown = ex; } lock (lockObj) { IEnumerable<TOut> enumerable2; if (doneItems != null) { enumerable2 = list.Concat(doneItems); } else { IEnumerable<TOut> enumerable3 = list; enumerable2 = enumerable3; } doneItems = enumerable2; int num = doneCount; doneCount = num + 1; are.Set(); } }); } bool isDone; do { are.WaitOne(); IEnumerable<TOut> enumerable; lock (lockObj) { enumerable = doneItems; doneItems = null; isDone = doneCount == workerCount; } if (enumerable == null) { continue; } foreach (TOut item in enumerable) { yield return item; } } while (!isDone); if (exceptionThrown != null) { throw new TargetInvocationException("An exception was thrown inside one of the threads", exceptionThrown); } } } public static class Utility { private static bool? sreEnabled; public static bool CLRSupportsDynamicAssemblies => CheckSRE(); public static Encoding UTF8NoBom { get; } = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); private static bool CheckSRE() { if (sreEnabled.HasValue) { return sreEnabled.Value; } try { new CustomAttributeBuilder(null, new object[0]); } catch (PlatformNotSupportedException) { sreEnabled = false; return sreEnabled.Value; } catch (ArgumentNullException) { } sreEnabled = true; return sreEnabled.Value; } public static bool TryDo(Action action, out Exception exception) { exception = null; try { action(); return true; } catch (Exception ex) { exception = ex; return false; } } public static string CombinePaths(params string[] parts) { return parts.Aggregate(Path.Combine); } public static string ParentDirectory(string path, int levels = 1) { for (int i = 0; i < levels; i++) { path = Path.GetDirectoryName(path); } return path; } public static bool SafeParseBool(string input, bool defaultValue = false) { if (!bool.TryParse(input, out var result)) { return defaultValue; } return result; } public static string ConvertToWWWFormat(string path) { return "file://" + path.Replace('\\', '/'); } public static bool IsNullOrWhiteSpace(this string self) { return self?.All(char.IsWhiteSpace) ?? true; } public static IEnumerable<TNode> TopologicalSort<TNode>(IEnumerable<TNode> nodes, Func<TNode, IEnumerable<TNode>> dependencySelector) { List<TNode> sorted_list = new List<TNode>(); HashSet<TNode> visited = new HashSet<TNode>(); HashSet<TNode> sorted = new HashSet<TNode>(); foreach (TNode node in nodes) { Stack<TNode> stack2 = new Stack<TNode>(); if (!Visit(node, stack2)) { throw new Exception("Cyclic Dependency:\r\n" + stack2.Select((TNode x) => $" - {x}").Aggregate((string a, string b) => a + "\r\n" + b)); } } return sorted_list; bool Visit(TNode node, Stack<TNode> stack) { if (visited.Contains(node)) { if (!sorted.Contains(node)) { return false; } } else { visited.Add(node); stack.Push(node); foreach (TNode item in dependencySelector(node)) { if (!Visit(item, stack)) { return false; } } sorted.Add(node); sorted_list.Add(node); stack.Pop(); } return true; } } private static bool TryResolveDllAssembly<T>(AssemblyName assemblyName, string directory, Func<string, T> loader, out T assembly) where T : class { assembly = null; List<string> list = new List<string>(); list.Add(directory); list.AddRange(Directory.GetDirectories(directory, "*", SearchOption.AllDirectories)); foreach (string item in list) { string text = Path.Combine(item, assemblyName.Name + ".dll"); if (File.Exists(text)) { try { assembly = loader(text); } catch (Exception) { continue; } return true; } } return false; } public static bool IsSubtypeOf(this TypeDefinition self, Type td) { if (((MemberReference)self).FullName == td.FullName) { return true; } if (((MemberReference)self).FullName != "System.Object") { TypeReference baseType = self.BaseType; return ((baseType == null) ? null : baseType.Resolve()?.IsSubtypeOf(td)).GetValueOrDefault(); } return false; } public static bool TryResolveDllAssembly(AssemblyName assemblyName, string directory, out Assembly assembly) { return TryResolveDllAssembly(assemblyName, directory, (Func<string, Assembly>)Assembly.LoadFile, out assembly); } public static bool TryResolveDllAssembly(AssemblyName assemblyName, string directory, ReaderParameters readerParameters, out AssemblyDefinition assembly) { return TryResolveDllAssembly(assemblyName, directory, (Func<string, AssemblyDefinition>)((string s) => AssemblyDefinition.ReadAssembly(s, readerParameters)), out assembly); } public static bool TryOpenFileStream(string path, FileMode mode, out FileStream fileStream, FileAccess access = FileAccess.ReadWrite, FileShare share = FileShare.Read) { try { fileStream = new FileStream(path, mode, access, share); return true; } catch (IOException) { fileStream = null; return false; } } public static bool TryParseAssemblyName(string fullName, out AssemblyName assemblyName) { try { assemblyName = new AssemblyName(fullName); return true; } catch (Exception) { assemblyName = null; return false; } } public static IEnumerable<string> GetUniqueFilesInDirectories(IEnumerable<string> directories, string pattern = "*") { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); foreach (string directory in directories) { string[] files = Directory.GetFiles(directory, pattern); foreach (string text in files) { string fileName = Path.GetFileName(text); if (!dictionary.ContainsKey(fileName)) { dictionary[fileName] = text; } } } return dictionary.Values; } } } namespace BepInEx.Logging { public class DiskLogListener : ILogListener, IDisposable { public LogLevel DisplayedLogLevel { get; set; } public TextWriter LogWriter { get; protected set; } public Timer FlushTimer { get; protected set; } public bool WriteFromUnityLog { get; set; } public DiskLogListener(string localPath, LogLevel displayedLogLevel = LogLevel.Info, bool appendLog = false, bool includeUnityLog = false) { WriteFromUnityLog = includeUnityLog; DisplayedLogLevel = displayedLogLevel; int num = 1; FileStream fileStream; while (!Utility.TryOpenFileStream(Path.Combine(Paths.BepInExRootPath, localPath), appendLog ? FileMode.Append : FileMode.Create, out fileStream, FileAccess.Write)) { if (num == 5) { Logger.LogError("Couldn't open a log file for writing. Skipping log file creation"); return; } Logger.LogWarning("Couldn't open log file '" + localPath + "' for writing, trying another..."); localPath = $"LogOutput.log.{num++}"; } LogWriter = TextWriter.Synchronized(new StreamWriter(fileStream, Utility.UTF8NoBom)); FlushTimer = new Timer(delegate { LogWriter?.Flush(); }, null, 2000, 2000); } public void LogEvent(object sender, LogEventArgs eventArgs) { if ((WriteFromUnityLog || !(eventArgs.Source is UnityLogSource)) && (eventArgs.Level & DisplayedLogLevel) != 0) { LogWriter.WriteLine(eventArgs.ToString()); } } public void Dispose() { FlushTimer?.Dispose(); LogWriter?.Flush(); LogWriter?.Dispose(); } ~DiskLogListener() { Dispose(); } } internal class HarmonyLogSource : ILogSource, IDisposable { private static readonly ConfigEntry<LogChannel> LogChannels = ConfigFile.CoreConfig.Bind<LogChannel>("Harmony.Logger", "LogChannels", (LogChannel)24, "Specifies which Harmony log channels to listen to.\nNOTE: IL channel dumps the whole patch methods, use only when needed!"); private static readonly Dictionary<LogChannel, LogLevel> LevelMap = new Dictionary<LogChannel, LogLevel> { [(LogChannel)2] = LogLevel.Info, [(LogChannel)8] = LogLevel.Warning, [(LogChannel)16] = LogLevel.Error, [(LogChannel)4] = LogLevel.Debug }; public string SourceName { get; } = "HarmonyX"; public event EventHandler<LogEventArgs> LogEvent; public HarmonyLogSource() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) Logger.ChannelFilter = LogChannels.Value; Logger.MessageReceived += HandleHarmonyMessage; } private void HandleHarmonyMessage(object sender, LogEventArgs e) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (LevelMap.TryGetValue(e.LogChannel, out var value)) { this.LogEvent?.Invoke(this, new LogEventArgs(e.Message, value, this)); } } public void Dispose() { Logger.MessageReceived -= HandleHarmonyMessage; } } public class LogEventArgs : EventArgs { public object Data { get; protected set; } public LogLevel Level { get; protected set; } public ILogSource Source { get; protected set; } public LogEventArgs(object data, LogLevel level, ILogSource source) { Data = data; Level = level; Source = source; } public override string ToString() { return $"[{Level,-7}:{Source.SourceName,10}] {Data}"; } public string ToStringLine() { return ToString() + Environment.NewLine; } } public static class Logger { private sealed class LogSourceCollection : ThreadSafeCollection<ILogSource>, ICollection<ILogSource>, IEnumerable<ILogSource>, IEnumerable { public override void Add(ILogSource item) { if (item == null) { throw new ArgumentNullException("item", "Log sources cannot be null when added to the source list."); } lock (Lock) { item.LogEvent += InternalLogEvent; List<ILogSource> list = new List<ILogSource>(BaseList.Count + 1); list.AddRange(BaseList); list.Add(item); BaseList = list; } } public override void Clear() { if (base.Count == 0) { return; } lock (Lock) { for (int i = 0; i < BaseList.Count; i++) { BaseList[i].LogEvent -= InternalLogEvent; } BaseList = new List<ILogSource>(0); } } public override bool Remove(ILogSource item) { if (item == null) { return false; } lock (Lock) { bool num = base.Remove(item); if (num) { item.LogEvent -= InternalLogEvent; } return num; } } } private sealed class LogListenerCollection : ThreadSafeCollection<ILogListener> { public void SendLogEvent(object sender, LogEventArgs eventArgs) { List<ILogListener> baseList = BaseList; for (int i = 0; i < baseList.Count; i++) { baseList[i].LogEvent(sender, eventArgs); } } } private class ThreadSafeCollection<T> : ICollection<T>, IEnumerable<T>, IEnumerable where T : class { protected readonly object Lock = new object(); protected List<T> BaseList = new List<T>(0); public int Count => BaseList.Count; public bool IsReadOnly => false; public IEnumerator<T> GetEnumerator() { return BaseList.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return BaseList.GetEnumerator(); } public virtual void Add(T item) { if (item == null) { throw new ArgumentNullException("item", "item can't be null"); } lock (Lock) { List<T> list = new List<T>(BaseList.Count + 1); list.AddRange(BaseList); list.Add(item); BaseList = list; } } public virtual void Clear() { if (Count == 0) { return; } lock (Lock) { BaseList = new List<T>(0); } } public bool Contains(T item) { return BaseList.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { BaseList.CopyTo(array, arrayIndex); } public virtual bool Remove(T item) { if (item == null) { return false; } lock (Lock) { List<T> list = new List<T>(BaseList.Count); bool result = false; for (int i = 0; i < BaseList.Count; i++) { T val = BaseList[i]; if (val.Equals(item)) { result = true; } else { list.Add(val); } } BaseList = list; return result; } } } private static readonly LogListenerCollection _Listeners = new LogListenerCollection(); private static readonly ManualLogSource InternalLogSource = CreateLogSource("BepInEx"); private static bool internalLogsInitialized; public static ICollection<ILogListener> Listeners => _Listeners; public static ICollection<ILogSource> Sources { get; } = new LogSourceCollection(); internal static void InitializeInternalLoggers() { if (!internalLogsInitialized) { Sources.Add(new HarmonyLogSource()); internalLogsInitialized = true; } } internal static void InternalLogEvent(object sender, LogEventArgs eventArgs) { _Listeners.SendLogEvent(sender, eventArgs); } internal static void Log(LogLevel level, object data) { InternalLogSource.Log(level, data); } internal static void LogFatal(object data) { Log(LogLevel.Fatal, data); } internal static void LogError(object data) { Log(LogLevel.Error, data); } internal static void LogWarning(object data) { Log(LogLevel.Warning, data); } internal static void LogMessage(object data) { Log(LogLevel.Message, data); } internal static void LogInfo(object data) { Log(LogLevel.Info, data); } internal static void LogDebug(object data) { Log(LogLevel.Debug, data); } public static ManualLogSource CreateLogSource(string sourceName) { ManualLogSource manualLogSource = new ManualLogSource(sourceName); Sources.Add(manualLogSource); return manualLogSource; } } [Flags] public enum LogLevel { None = 0, Fatal = 1, Error = 2, Warning = 4, Message = 8, Info = 0x10, Debug = 0x20, All = 0x3F } public static class LogLevelExtensions { public static LogLevel GetHighestLevel(this LogLevel levels) { Array values = Enum.GetValues(typeof(LogLevel)); Array.Sort(values); foreach (LogLevel item in values) { if ((levels & item) != 0) { return item; } } return LogLevel.None; } public static ConsoleColor GetConsoleColor(this LogLevel level) { level = level.GetHighestLevel(); return level switch { LogLevel.Fatal => ConsoleColor.Red, LogLevel.Error => ConsoleColor.DarkRed, LogLevel.Warning => ConsoleColor.Yellow, LogLevel.Message => ConsoleColor.White, LogLevel.Debug => ConsoleColor.DarkGray, _ => ConsoleColor.Gray, }; } } public interface ILogListener : IDisposable { void LogEvent(object sender, LogEventArgs eventArgs); } public interface ILogSource : IDisposable { string SourceName { get; } event EventHandler<LogEventArgs> LogEvent; } public class ManualLogSource : ILogSource, IDisposable { public string SourceName { get; } public event EventHandler<LogEventArgs> LogEvent; public ManualLogSource(string sourceName) { SourceName = sourceName; } public void Log(LogLevel level, object data) { this.LogEvent?.Invoke(this, new LogEventArgs(data, level, this)); } public void LogFatal(object data) { Log(LogLevel.Fatal, data); } public void LogError(object data) { Log(LogLevel.Error, data); } public void LogWarning(object data) { Log(LogLevel.Warning, data); } public void LogMessage(object data) { Log(LogLevel.Message, data); } public void LogInfo(object data) { Log(LogLevel.Info, data); } public void LogDebug(object data) { Log(LogLevel.Debug, data); } public void Dispose() { } } public class TraceLogSource : TraceListener { private static TraceLogSource traceListener; public static bool IsListening { get; protected set; } protected ManualLogSource LogSource { get; } public static ILogSource CreateSource() { if (traceListener == null) { traceListener = new TraceLogSource(); Trace.Listeners.Add(traceListener); IsListening = true; } return traceListener.LogSource; } protected TraceLogSource() { LogSource = new ManualLogSource("Trace"); } public override void Write(string message) { LogSource.LogInfo(message); } public override void WriteLine(string message) { LogSource.LogInfo(message); } public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args) { TraceEvent(eventCache, source, eventType, id, string.Format(format, args)); } public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) { LogSource.Log(eventType switch { TraceEventType.Critical => LogLevel.Fatal, TraceEventType.Error => LogLevel.Error, TraceEventType.Warning => LogLevel.Warning, TraceEventType.Information => LogLevel.Info, _ => LogLevel.Debug, }, (message ?? "").Trim()); } } public class ConsoleLogListener : ILogListener, IDisposable { private static readonly ConfigEntry<LogLevel> ConfigConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind("Logging.Console", "LogLevels", LogLevel.Fatal | LogLevel.Error | LogLevel.Warning | LogLevel.Message | LogLevel.Info, "Which log levels to show in the console output."); internal bool WriteUnityLogs { get; set; } = true; public void LogEvent(object sender, LogEventArgs eventArgs) { if ((WriteUnityLogs || !(sender is UnityLogSource)) && (eventArgs.Level & ConfigConsoleDisplayedLevel.Value) != 0) { ConsoleManager.SetConsoleColor(eventArgs.Level.GetConsoleColor()); ConsoleManager.ConsoleStream?.Write(eventArgs.ToStringLine()); ConsoleManager.SetConsoleColor(ConsoleColor.Gray); } } public void Dispose() { } } public class UnityLogListener : ILogListener, IDisposable { internal static readonly Action<string> WriteStringToUnityLog; private ConfigEntry<bool> LogConsoleToUnity = ConfigFile.CoreConfig.Bind("Logging", "LogConsoleToUnityLog", defaultValue: false, new StringBuilder().AppendLine("If enabled, writes Standard Output messages to Unity log").AppendLine("NOTE: By default, Unity does so automatically. Only use this option if no console messages are visible in Unity log").ToString()); static UnityLogListener() { MethodInfo[] methods = typeof(UnityLogWriter).GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { try { methodInfo.Invoke(null, new object[1] { "" }); } catch { continue; } WriteStringToUnityLog = (Action<string>)Delegate.CreateDelegate(typeof(Action<string>), methodInfo); break; } if (WriteStringToUnityLog == null) { Logger.LogError("Unable to start Unity log writer"); } } public void LogEvent(object sender, LogEventArgs eventArgs) { if (!(eventArgs.Source is UnityLogSource) && (LogConsoleToUnity.Value || eventArgs.Source.SourceName != "Console")) { WriteStringToUnityLog?.Invoke(eventArgs.ToStringLine()); } } public void Dispose() { } } public class UnityLogSource : ILogSource, IDisposable { private bool disposed; public string SourceName { get; } = "Unity Log"; public event EventHandler<LogEventArgs> LogEvent; private static event EventHandler<LogEventArgs> InternalUnityLogMessage; public UnityLogSource() { InternalUnityLogMessage += UnityLogMessageHandler; } private void UnityLogMessageHandler(object sender, LogEventArgs eventArgs) { LogEventArgs e = new LogEventArgs(eventArgs.Data, eventArgs.Level, this); this.LogEvent?.Invoke(this, e); } public void Dispose() { if (!disposed) { InternalUnityLogMessage -= UnityLogMessageHandler; disposed = true; } } static UnityLogSource() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown LogCallback val = new LogCallback(OnUnityLogMessageReceived); EventInfo @event = typeof(Application).GetEvent("logMessageReceived", BindingFlags.Static | BindingFlags.Public); if ((object)@event != null) { @event.AddEventHandler(null, (Delegate?)(object)val); return; } typeof(Application).GetMethod("RegisterLogCallback", BindingFlags.Static | BindingFlags.Public).Invoke(null, new object[1] { val }); } private static void OnUnityLogMessageReceived(string message, string stackTrace, LogType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected I4, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 LogLevel level; switch ((int)type) { case 0: case 1: case 4: level = LogLevel.Error; break; case 2: level = LogLevel.Warning; break; default: level = LogLevel.Info; break; } if ((int)type == 4) { message = message + "\nStack trace:\n" + stackTrace; } UnityLogSource.InternalUnityLogMessage?.Invoke(null, new LogEventArgs(message, level, null)); } } } namespace BepInEx.Bootstrap { public static class Chainloader { private static readonly List<BaseUnityPlugin> _plugins = new List<BaseUnityPlugin>(); private static bool? isEditor; private static bool _loaded = false; private static bool _initialized = false; private static readonly string CurrentAssemblyName = Assembly.GetExecutingAssembly().GetName().Name; private static readonly Version CurrentAssemblyVersion = Assembly.GetExecutingAssembly().GetName().Version; internal static readonly ConfigEntry<bool> ConfigHideBepInExGOs = ConfigFile.CoreConfig.Bind("Chainloader", "HideManagerGameObject", defaultValue: false, new StringBuilder().AppendLine("If enabled, hides BepInEx Manager GameObject from Unity.").AppendLine("This can fix loading issues in some games that attempt to prevent BepInEx from being loaded.").AppendLine("Use this only if you know what this option means, as it can affect functionality of some older plugins.") .ToString()); private static readonly ConfigEntry<bool> ConfigUnityLogging = ConfigFile.CoreConfig.Bind("Logging", "UnityLogListening", defaultValue: true, "Enables showing unity log messages in the BepInEx logging system."); private static readonly ConfigEntry<bool> ConfigDiskWriteUnityLog = ConfigFile.CoreConfig.Bind("Logging.Disk", "WriteUnityLog", defaultValue: false, "Include unity log messages in log file output."); private static readonly ConfigEntry<bool> ConfigDiskAppend = ConfigFile.CoreConfig.Bind("Logging.Disk", "AppendLog", defaultValue: false, "Appends to the log file instead of overwriting, on game startup."); private static readonly ConfigEntry<bool> ConfigDiskLogging = ConfigFile.CoreConfig.Bind("Logging.Disk", "Enabled", defaultValue: true, "Enables writing log messages to disk."); private static readonly ConfigEntry<LogLevel> ConfigDiskConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind("Logging.Disk", "LogLevels", LogLevel.Fatal | LogLevel.Error | LogLevel.Warning | LogLevel.Message | LogLevel.Info, "Which log leves are saved to the disk log output."); public static Dictionary<string, PluginInfo> PluginInfos { get; } = new Dictionary<string, PluginInfo>(); private static string UnityVersion { [MethodImpl(MethodImplOptions.NoInlining)] get { return Application.unityVersion; } } private static bool IsHeadless { get { MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(Application), "isBatchMode"); if ((object)methodInfo != null) { return (bool)methodInfo.Invoke(null, null); } return SystemInfo.graphicsDeviceID == 0; } } internal static bool IsEditor { [MethodImpl(MethodImplOptions.NoInlining)] get { bool? flag = isEditor; if (!flag.HasValue) { bool? flag2 = (isEditor = Application.isEditor); return flag2.GetValueOrDefault(); } return flag.GetValueOrDefault(); } } [Obsolete("Use PluginInfos instead")] public static List<BaseUnityPlugin> Plugins { get { lock (_plugins) { _plugins.RemoveAll((BaseUnityPlugin x) => (Object)(object)x == (Object)null); return _plugins.ToList(); } } } public static List<string> DependencyErrors { get; } = new List<string>(); public static GameObject ManagerObject { get; private set; } private static Regex allowedGuidRegex { get; } = new Regex("^[a-zA-Z0-9\\._\\-]+$"); public static void Initialize(string gameExePath, bool startConsole = true, ICollection<LogEventArgs> preloaderLogEvents = null) { if (!_initialized) { ThreadingHelper.Initialize(); if (gameExePath != null) { Paths.SetExecutablePath(gameExePath); } if (ConsoleManager.ConsoleEnabled && startConsole) { ConsoleManager.CreateConsole(); Logger.Listeners.Add(new ConsoleLogListener()); } Logger.InitializeInternalLoggers(); if (ConfigDiskLogging.Value) { Logger.Listeners.Add(new DiskLogListener("LogOutput.log", ConfigDiskConsoleDisplayedLevel.Value, ConfigDiskAppend.Value, ConfigDiskWriteUnityLog.Value)); } if (!TraceLogSource.IsListening) { Logger.Sources.Add(TraceLogSource.CreateSource()); } ReplayPreloaderLogs(preloaderLogEvents); if (ConfigUnityLogging.Value) { Logger.Sources.Add(new UnityLogSource()); } if (!IsHeadless) { Logger.Listeners.Add(new UnityLogListener()); } else if (Logger.Listeners.FirstOrDefault((ILogListener l) => l is ConsoleLogListener) is ConsoleLogListener consoleLogListener) { consoleLogListener.WriteUnityLogs = false; } if (PlatformHelper.Is((Platform)8)) { Logger.LogInfo("Detected Unity version: v" + UnityVersion); } Logger.LogMessage("Chainloader ready"); _initialized = true; } } private static void ReplayPreloaderLogs(ICollection<LogEventArgs> preloaderLogEvents) { if (preloaderLogEvents == null) { return; } UnityLogListener item = new UnityLogListener(); Logger.Listeners.Add(item); ILogListener logListener = Logger.Listeners.FirstOrDefault((ILogListener logger) => logger is ConsoleLogListener); if (logListener != null) { Logger.Listeners.Remove(logListener); } ManualLogSource manualLogSource = Logger.CreateLogSource("Preloader"); foreach (LogEventArgs preloaderLogEvent in preloaderLogEvents) { Logger.InternalLogEvent(manualLogSource, preloaderLogEvent); } Logger.Sources.Remove(manualLogSource); Logger.Listeners.Remove(item); if (logListener != null) { Logger.Listeners.Add(logListener); } } public static PluginInfo ToPluginInfo(TypeDefinition type) { if (type.IsInterface || type.IsAbstract) { return null; } try { if (!type.IsSubtypeOf(typeof(BaseUnityPlugin))) { return null; } } catch (AssemblyResolutionException) { return null; } BepInPlugin bepInPlugin = BepInPlugin.FromCecilType(type); if (bepInPlugin == null) { Logger.LogWarning("Skipping over type [" + ((MemberReference)type).FullName + "] as no metadata attribute is specified"); return null; } if (string.IsNullOrEmpty(bepInPlugin.GUID) || !allowedGuidRegex.IsMatch(bepInPlugin.GUID)) { Logger.LogWarning("Skipping type [" + ((MemberReference)type).FullName + "] because its GUID [" + bepInPlugin.GUID + "] is of an illegal format."); return null; } if (bepInPlugin.Version == null) { Logger.LogWarning("Skipping type [" + ((MemberReference)type).FullName + "] because its version is invalid."); return null; } if (bepInPlugin.Name == null) { Logger.LogWarning("Skipping type [" + ((MemberReference)type).FullName + "] because its name is null."); return null; } List<BepInProcess> processes = BepInProcess.FromCecilType(type); IEnumerable<BepInDependency> dependencies = BepInDependency.FromCecilType(type); IEnumerable<BepInIncompatibility> incompatibilities = BepInIncompatibility.FromCecilType(type); AssemblyNameReference? obj = ((IEnumerable<AssemblyNameReference>)((MemberReference)type).Module.AssemblyReferences).FirstOrDefault((Func<AssemblyNameReference, bool>)((AssemblyNameReference reference) => reference.Name == "BepInEx")); Version targettedBepInExVersion = ((obj != null) ? obj.Version : null) ?? new Version(); return new PluginInfo { Metadata = bepInPlugin, Processes = processes, Dependencies = dependencies, Incompatibilities = incompatibilities, TypeName = ((MemberReference)type).FullName, TargettedBepInExVersion = targettedBepInExVersion }; } private static bool HasBepinPlugins(AssemblyDefinition ass) { if (((IEnumerable<AssemblyNameReference>)ass.MainModule.AssemblyReferences).All((AssemblyNameReference r) => r.Name != CurrentAssemblyName)) { return false; } if (ass.MainModule.GetTypeReferences().All((TypeReference r) => ((MemberReference)r).FullName != typeof(BepInPlugin).FullName)) { return false; } return true; } private static bool PluginTargetsWrongBepin(PluginInfo pluginInfo) { Version targettedBepInExVersion = pluginInfo.TargettedBepInExVersion; if (targettedBepInExVersion.Major != CurrentAssemblyVersion.Major) { return true; } if (targettedBepInExVersion.Minor > CurrentAssemblyVersion.Minor) { return true; } if (targettedBepInExVersion.Minor < CurrentAssemblyVersion.Minor) { return false; } return targettedBepInExVersion.Build > CurrentAssemblyVersion.Build; } public static void Start() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown if (_loaded) { return; } if (!_initialized) { throw new InvalidOperationException("BepInEx has not been initialized. Please call Chainloader.Initialize prior to starting the chainloader instance."); } if (!Directory.Exists(Paths.PluginPath)) { Directory.CreateDirectory(Paths.PluginPath); } if (!Directory.Exists(Paths.PatcherPluginPath)) { Directory.CreateDirectory(Paths.PatcherPluginPath); } try { PropertyInfo property = typeof(Application).GetProperty("productName", BindingFlags.Static | BindingFlags.Public); if (ConsoleManager.ConsoleActive) { ConsoleManager.SetConsoleTitle($"{CurrentAssemblyName} {CurrentAssemblyVersion} - {property?.GetValue(null, null) ?? Paths.ProcessName}"); } Logger.LogMessage("Chainloader started"); ManagerObject = new GameObject("BepInEx_Manager"); if (ConfigHideBepInExGOs.Value) { ((Object)ManagerObject).hideFlags = (HideFlags)61; } Object.DontDestroyOnLoad((Object)(object)ManagerObject); Dictionary<string, List<PluginInfo>> dictionary = TypeLoader.FindPluginTypes(Paths.PluginPath, ToPluginInfo, HasBepinPlugins, "chainloader"); foreach (KeyValuePair<string, List<PluginInfo>> item in dictionary) { foreach (PluginInfo item2 in item.Value) { item2.Location = item.Key; } } List<PluginInfo> list = dictionary.SelectMany((KeyValuePair<string, List<PluginInfo>> p) => p.Value).ToList(); Dictionary<string, Assembly> dictionary2 = new Dictionary<string, Assembly>(); Logger.LogInfo(string.Format("{0} plugin{1} to load", list.Count, (list.Count == 1) ? "" : "s")); SortedDictionary<string, IEnumerable<string>> dependencyDict = new SortedDictionary<string, IEnumerable<string>>(StringComparer.InvariantCultureIgnoreCase); Dictionary<string, PluginInfo> pluginsByGUID = new Dictionary<string, PluginInfo>(); foreach (IGrouping<string, PluginInfo> item3 in from info in list group info by info.Metadata.GUID) { PluginInfo pluginInfo = null; foreach (PluginInfo item4 in item3.OrderByDescending((PluginInfo x) => x.Metadata.Version)) { if (pluginInfo != null) { Logger.LogWarning($"Skipping [{item4}] because a newer version exists ({pluginInfo})"); continue; } List<BepInProcess> list2 = item4.Processes.ToList(); if (list2.Count != 0 && list2.All((BepInProcess x) => !string.Equals(x.ProcessName.Replace(".exe", ""), Paths.ProcessName, StringComparison.InvariantCultureIgnoreCase))) { Logger.LogWarning(string.Format("Skipping [{0}] because of process filters ({1})", item4, string.Join(", ", item4.Processes.Select((BepInProcess p) => p.ProcessName).ToArray()))); continue; } pluginInfo = item4; dependencyDict[item4.Metadata.GUID] = item4.Dependencies.Select((BepInDependency d) => d.DependencyGUID); pluginsByGUID[item4.Metadata.GUID] = item4; } } foreach (PluginInfo item5 in pluginsByGUID.Values.ToList()) { if (item5.Incompatibilities.Any((BepInIncompatibility incompatibility) => pluginsByGUID.ContainsKey(incompatibility.IncompatibilityGUID))) { pluginsByGUID.Remove(item5.Metadata.GUID); dependencyDict.Remove(item5.Metadata.GUID); string[] value = (from x in item5.Incompatibilities select x.IncompatibilityGUID into x where pluginsByGUID.ContainsKey(x) select x).ToArray(); string text = string.Format("Could not load [{0}] because it is incompatible with: {1}", item5, string.Join(", ", value)); DependencyErrors.Add(text); Logger.LogError(text); } else if (PluginTargetsWrongBepin(item5)) { string text2 = $"Plugin [{item5}] targets a wrong version of BepInEx ({item5.TargettedBepInExVersion}) and might not work until you update"; DependencyErrors.Add(text2); Logger.LogWarning(text2); } } string[] emptyDependencies = new string[0]; IEnumerable<string> value5; List<string> list3 = Utility.TopologicalSort(dependencyDict.Keys, (string x) => (!dependencyDict.TryGetValue(x, out value5)) ? emptyDependencies : value5).ToList(); HashSet<string> hashSet = new HashSet<string>(); Dictionary<string, Version> dictionary3 = new Dictionary<string, Version>(); foreach (string item6 in list3) { if (!pluginsByGUID.TryGetValue(item6, out var value2)) { continue; } bool flag = false; List<BepInDependency> list4 = new List<BepInDependency>(); foreach (BepInDependency dependency in value2.Dependencies) { if (!dictionary3.TryGetValue(dependency.DependencyGUID, out var value3) || value3 < dependency.MinimumVersion) { if (IsHardDependency(dependency)) { list4.Add(dependency); } } else if (hashSet.Contains(dependency.DependencyGUID) && IsHardDependency(dependency)) { flag = true; break; } } dictionary3.Add(item6, value2.Metadata.Version); if (flag) { string text3 = $"Skipping [{value2}] because it has a dependency that was not loaded. See previous errors for details."; DependencyErrors.Add(text3); Logger.LogWarning(text3); continue; } if (list4.Count != 0) { string text4 = string.Format("Could not load [{0}] because it has missing dependencies: {1}", value2, string.Join(", ", list4.Select((BepInDependency s) => (!IsEmptyVersion(s.MinimumVersion)) ? $"{s.DependencyGUID} (v{s.MinimumVersion} or newer)" : s.DependencyGUID).ToArray())); DependencyErrors.Add(text4); Logger.LogError(text4); hashSet.Add(item6); continue; } try { Logger.LogInfo($"Loading [{value2}]"); if (!dictionary2.TryGetValue(value2.Location, out var value4)) { value4 = (dictionary2[value2.Location] = Assembly.LoadFile(value2.Location)); } PluginInfos[item6] = value2; value2.Instance = (BaseUnityPlugin)(object)ManagerObject.AddComponent(value4.GetType(value2.TypeName)); _plugins.Add(value2.Instance); } catch (Exception ex) { hashSet.Add(item6); PluginInfos.Remove(item6); Logger.LogError($"Error loading [{value2}] : {ex.Message}"); if (ex is ReflectionTypeLoadException ex2) { Logger.LogDebug(TypeLoader.TypeLoadExceptionToString(ex2)); } else { Logger.LogDebug(ex); } } } } catch (Exception ex3) { try { ConsoleManager.CreateConsole(); } catch { } Logger.LogFatal("Error occurred starting the game"); Logger.LogFatal(ex3.ToString()); } Logger.LogMessage("Chainloader startup complete"); _loaded = true; static bool IsEmptyVersion(Version v) { if (v.Major == 0 && v.Minor == 0 && v.Build <= 0) { return v.Revision <= 0; } return false; } static bool IsHardDependency(BepInDependency dep) { return (dep.Flags & BepInDependency.DependencyFlags.HardDependency) != 0; } } } public interface ICacheable { void Save(BinaryWriter bw); void Load(BinaryReader br); } public class CachedAssembly<T> where T : ICacheable { public List<T> CacheItems { get; set; } public long Timestamp { get; set; } } public static class TypeLoader { public static readonly DefaultAssemblyResolver Resolver; public static readonly ReaderParameters ReaderParameters; [CompilerGenerated] private static AssemblyResolveEventHandler m_AssemblyResolve; private static readonly ConfigEntry<bool> EnableAssemblyCache; public static event AssemblyResolveEventHandler AssemblyResolve { [CompilerGenerated] add { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown AssemblyResolveEventHandler val = TypeLoader.m_AssemblyResolve; AssemblyResolveEventHandler val2; do { val2 = val; AssemblyResolveEventHandler value2 = (AssemblyResolveEventHandler)Delegate.Combine((Delegate?)(object)val2, (Delegate?)(object)value); val = Interlocked.CompareExchange(ref TypeLoader.m_AssemblyResolve, value2, val2); } while (val != val2); } [CompilerGenerated] remove { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown AssemblyResolveEventHandler val = TypeLoader.m_AssemblyResolve; AssemblyResolveEventHandler val2; do { val2 = val; AssemblyResolveEventHandler value2 = (AssemblyResolveEventHandler)Delegate.Remove((Delegate?)(object)val2, (Delegate?)(object)value); val = Interlocked.CompareExchange(ref TypeLoader.m_AssemblyResolve, value2, val2); } while (val != val2); } } static TypeLoader() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown EnableAssemblyCache = ConfigFile.CoreConfig.Bind("Caching", "EnableAssemblyCache", defaultValue: true, "Enable/disable assembly metadata cache\nEnabling this will speed up discovery of plugins and patchers by caching the metadata of all types BepInEx discovers."); Resolver = new DefaultAssemblyResolver(); ReaderParameters = new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)Resolver }; ((BaseAssemblyResolver)Resolver).ResolveFailure += (AssemblyResolveEventHandler)delegate(object sender, AssemblyNameReference reference) { if (!Utility.TryParseAssemblyName(reference.FullName, out var assemblyName)) { AssemblyResolveEventHandler assemblyResolve = TypeLoader.AssemblyResolve; if (assemblyResolve == null) { return null; } return assemblyResolve.Invoke(sender, reference); } foreach (string item in new string[3] { Paths.BepInExAssemblyDirectory, Paths.PluginPath, Paths.PatcherPluginPath }.Concat(Paths.DllSearchPaths)) { if (Utility.TryResolveDllAssembly(assemblyName, item, ReaderParameters, out var assembly)) { return assembly; } } AssemblyResolveEventHandler assemblyResolve2 = TypeLoader.AssemblyResolve; return (assemblyResolve2 == null) ? null : assemblyResolve2.Invoke(sender, reference); }; } public static Dictionary<string, List<T>> FindPluginTypes<T>(string directory, Func<TypeDefinition, T> typeSelector, Func<AssemblyDefinition, bool> assemblyFilter = null, string cacheName = null) where T : ICacheable, new() { Dictionary<string, List<T>> dictionary = new Dictionary<string, List<T>>(); Dictionary<string, CachedAssembly<T>> dictionary2 = null; if (cacheName != null) { dictionary2 = LoadAssemblyCache<T>(cacheName); } string[] files = Directory.GetFiles(Path.GetFullPath(directory), "*.dll", SearchOption.AllDirectories); foreach (string text in files) { try { if (dictionary2 != null && dictionary2.TryGetValue(text, out var value) && File.GetLastWriteTimeUtc(text).Ticks == value.Timestamp) { dictionary[text] = value.CacheItems; continue; } AssemblyDefinition val = AssemblyDefinition.ReadAssembly(text, ReaderParameters); if (assemblyFilter != null && !assemblyFilter(val)) { dictionary[text] = new List<T>(); val.Dispose(); continue; } List<T> value2 = (from t in ((IEnumerable<TypeDefinition>)val.MainModule.Types).Select(typeSelector) where t != null select t).ToList(); dictionary[text] = value2; val.Dispose(); } catch (BadImageFormatException ex) { Logger.LogDebug("Skipping loading " + text + " because it's not a valid .NET assembly. Full error: " + ex.Message); } catch (Exception ex2) { Logger.LogError(ex2.ToString()); } } if (cacheName != null) { SaveAssemblyCache(cacheName, dictionary); } return dictionary; } public static Dictionary<string, CachedAssembly<T>> LoadAssemblyCache<T>(string cacheName) where T : ICacheable, new() { if (!EnableAssemblyCache.Value) { return null; } Dictionary<string, CachedAssembly<T>> dictionary = new Dictionary<string, CachedAssembly<T>>(); try { string path = Path.Combine(Paths.CachePath, cacheName + "_typeloader.dat"); if (!File.Exists(path)) { return null; } using BinaryReader binaryReader = new BinaryReader(File.OpenRead(path)); int num = binaryReader.ReadInt32(); for (int i = 0; i < num; i++) { string key = binaryReader.ReadString(); long timestamp = binaryReader.ReadInt64(); int num2 = binaryReader.ReadInt32(); List<T> list = new List<T>(); for (int j = 0; j < num2; j++) { T item = new T(); item.Load(binaryReader); list.Add(item); } dictionary[key] = new CachedAssembly<T> { Timestamp = timestamp, CacheItems = list }; } } catch (Exception ex) { Logger.LogWarning("Failed to load cache \"" + cacheName + "\"; skipping loading cache. Reason: " + ex.Message + "."); } return dictionary; } public static void SaveAssemblyCache<T>(string cacheName, Dictionary<string, List<T>> entries) where T : ICacheable { if (!EnableAssemblyCache.Value) { return; } try { if (!Directory.Exists(Paths.CachePath)) { Directory.CreateDirectory(Paths.CachePath); } using BinaryWriter binaryWriter = new BinaryWriter(File.OpenWrite(Path.Combine(Paths.CachePath, cacheName + "_typeloader.dat"))); binaryWriter.Write(entries.Count); foreach (KeyValuePair<string, List<T>> entry in entries) { binaryWriter.Write(entry.Key); binaryWriter.Write(File.GetLastWriteTimeUtc(entry.Key).Ticks); binaryWriter.Write(entry.Value.Count); foreach (T item in entry.Value) { item.Save(binaryWriter); } } } catch (Exception ex) { Logger.LogWarning("Failed to save cache \"" + cacheName + "\"; skipping saving cache. Reason: " + ex.Message + "."); } } public static string TypeLoadExceptionToString(ReflectionTypeLoadException ex) { StringBuilder stringBuilder = new StringBuilder(); Exception[] loaderExceptions = ex.LoaderExceptions; foreach (Exception ex2 in loaderExceptions) { stringBuilder.AppendLine(ex2.Message); if (ex2 is FileNotFoundException ex3) { if (!string.IsNullOrEmpty(ex3.FusionLog)) { stringBuilder.AppendLine("Fusion Log:"); stringBuilder.AppendLine(ex3.FusionLog); } } else if (ex2 is FileLoadException ex4 && !string.IsNullOrEmpty(ex4.FusionLog)) { stringBuilder.AppendLine("Fusion Log:"); stringBuilder.AppendLine(ex4.FusionLog); } stringBuilder.AppendLine(); } return stringBuilder.ToString(); } } } namespace BepInEx.ConsoleUtil { internal class Kon { private struct CONSOLE_SCREEN_BUFFER_INFO { internal COORD dwSize; internal COORD dwCursorPosition; internal short wAttributes; internal SMALL_RECT srWindow; internal COORD dwMaximumWindowSize; } private struct COORD { internal short X; internal short Y; } private struct SMALL_RECT { internal short Left; internal short Top; internal short Right; internal short Bottom; } private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); internal static IntPtr conOut = IntPtr.Zero; public static ConsoleColor ForegroundColor { get { return GetConsoleColor(isBackground: false); } set { SetConsoleColor(isBackground: false, value); } } public static ConsoleColor BackgroundColor { get { return GetConsoleColor(isBackground: true); } set { SetConsoleColor(isBackground: true, value); } } [DllImport("kernel32.dll", SetLastError = true)] private static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, short attributes); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetStdHandle(int nStdHandle); private static short ConsoleColorToColorAttribute(sh
BepInEx/core/BepInEx.Harmony.dll
Decompiled 10 months agousing System; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using HarmonyLib; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BepInEx.Harmony")] [assembly: AssemblyDescription("Harmony wrapper for BepInEx")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BepInEx.Harmony")] [assembly: AssemblyCopyright("Copyright © Bepis 2019")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("54161cfe-ff42-4dde-b161-3a49545db5cd")] [assembly: AssemblyFileVersion("2.0.0.0")] [assembly: AssemblyVersion("2.0.0.0")] namespace BepInEx.Harmony; [AttributeUsage(AttributeTargets.Method)] [Obsolete("Use HarmonyLib.ParameterByRefAttribute directly", true)] public class ParameterByRefAttribute : ParameterByRefAttribute { public int[] ParameterIndices => ((ParameterByRefAttribute)this).ParameterIndices; public ParameterByRefAttribute(params int[] parameterIndices) : base(parameterIndices) { } } public static class HarmonyExtensions { [Obsolete("Use HarmonyLib.Harmony.PatchAll directly", true)] public static void PatchAll(this Harmony harmonyInstance, Type type) { HarmonyWrapper.PatchAll(type, harmonyInstance); } } public class HarmonyWrapper { [Obsolete("Use HarmonyLib.Harmony.CreateAndPatchAll or HarmonyLib.Harmony.PatchAll", true)] public static Harmony PatchAll(Type type, Harmony harmonyInstance = null) { if (harmonyInstance == null) { return Harmony.CreateAndPatchAll(type, (string)null); } harmonyInstance.PatchAll(type); return harmonyInstance; } [Obsolete("Use HarmonyLib.Harmony.CreateAndPatchAll", true)] public static Harmony PatchAll(Type type, string harmonyInstanceId) { return Harmony.CreateAndPatchAll(type, harmonyInstanceId); } [Obsolete("Use HarmonyLib.Harmony.CreateAndPatchAll or HarmonyLib.Harmony.PatchAll", true)] public static Harmony PatchAll(Assembly assembly, Harmony harmonyInstance = null) { return assembly.GetTypes().Aggregate(harmonyInstance, (Harmony current, Type type) => PatchAll(type, current)); } [Obsolete("Use HarmonyLib.Harmony.CreateAndPatchAll", true)] public static Harmony PatchAll(Assembly assembly, string harmonyInstanceId) { return Harmony.CreateAndPatchAll(assembly, harmonyInstanceId); } [Obsolete("Use HarmonyLib.Harmony.PatchAll with no arguments", true)] public static Harmony PatchAll(Harmony harmonyInstance = null) { return PatchAll(Assembly.GetCallingAssembly(), harmonyInstance); } [Obsolete("Use HarmonyLib.Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), ...)", true)] public static Harmony PatchAll(string harmonyInstanceId) { return PatchAll(Assembly.GetCallingAssembly(), harmonyInstanceId); } [Obsolete("Use HarmonyLib.Transpilers.EmitDelegate instead", true)] public static CodeInstruction EmitDelegate<T>(T action) where T : Delegate { return Transpilers.EmitDelegate<T>(action); } }
BepInEx/core/BepInEx.Preloader.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BepInEx.Preloader.Patching; using BepInEx.Preloader.RuntimeFixes; using HarmonyLib; using HarmonyXInterop; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.RuntimeDetour; using MonoMod.RuntimeDetour.Platforms; using MonoMod.Utils; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BepInEx.Preloader")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BepInEx.Preloader")] [assembly: AssemblyCopyright("Copyright © 2019")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f7abbe07-c02f-4f7c-bf6e-c6656bf588ca")] [assembly: AssemblyFileVersion("5.4.22.0")] [assembly: AssemblyVersion("5.4.22.0")] namespace BepInEx.Preloader { public static class EnvVars { public static string DOORSTOP_INVOKE_DLL_PATH { get; private set; } public static string DOORSTOP_MANAGED_FOLDER_DIR { get; private set; } public static string DOORSTOP_PROCESS_PATH { get; private set; } public static string[] DOORSTOP_DLL_SEARCH_DIRS { get; private set; } internal static void LoadVars() { DOORSTOP_INVOKE_DLL_PATH = Environment.GetEnvironmentVariable("DOORSTOP_INVOKE_DLL_PATH"); DOORSTOP_MANAGED_FOLDER_DIR = Environment.GetEnvironmentVariable("DOORSTOP_MANAGED_FOLDER_DIR"); DOORSTOP_PROCESS_PATH = Environment.GetEnvironmentVariable("DOORSTOP_PROCESS_PATH"); DOORSTOP_DLL_SEARCH_DIRS = Environment.GetEnvironmentVariable("DOORSTOP_DLL_SEARCH_DIRS")?.Split(new char[1] { Path.PathSeparator }) ?? new string[0]; } } internal static class PreloaderRunner { private static readonly string[] CriticalAssemblies = new string[7] { "Mono.Cecil.dll", "Mono.Cecil.Mdb.dll", "Mono.Cecil.Pdb.dll", "Mono.Cecil.Rocks.dll", "MonoMod.Utils.dll", "MonoMod.RuntimeDetour.dll", "0Harmony.dll" }; private static void LoadCriticalAssemblies() { string[] criticalAssemblies = CriticalAssemblies; foreach (string path in criticalAssemblies) { try { Assembly.LoadFile(Path.Combine(Paths.BepInExAssemblyDirectory, path)); } catch (Exception) { } } } public static void PreloaderPreMain() { PlatformUtils.SetPlatform(); string text = Utility.ParentDirectory(Path.GetFullPath(EnvVars.DOORSTOP_INVOKE_DLL_PATH), 2); Paths.SetExecutablePath(EnvVars.DOORSTOP_PROCESS_PATH, text, EnvVars.DOORSTOP_MANAGED_FOLDER_DIR, EnvVars.DOORSTOP_DLL_SEARCH_DIRS); LoadCriticalAssemblies(); AppDomain.CurrentDomain.AssemblyResolve += LocalResolve; AppDomain.CurrentDomain.AssemblyResolve -= Entrypoint.ResolveCurrentDirectory; PreloaderMain(); } private static void PreloaderMain() { if (Preloader.ConfigApplyRuntimePatches.Value) { XTermFix.Apply(); ConsoleSetOutFix.Apply(); } Preloader.Run(); } private static Assembly LocalResolve(object sender, ResolveEventArgs args) { AssemblyName assemblyName = default(AssemblyName); if (!Utility.TryParseAssemblyName(args.Name, ref assemblyName)) { return null; } AssemblyName assemblyName2 = default(AssemblyName); var source = (from a in AppDomain.CurrentDomain.GetAssemblies() select new { assembly = a, name = (Utility.TryParseAssemblyName(a.FullName, ref assemblyName2) ? assemblyName2 : null) } into a where a.name != null && a.name.Name == assemblyName.Name orderby a.name.Version descending select a).ToList(); Assembly assembly = (source.FirstOrDefault(a => a.name.Version == assemblyName.Version) ?? source.FirstOrDefault())?.assembly; if ((object)assembly != null) { return assembly; } if (Utility.TryResolveDllAssembly(assemblyName, Paths.BepInExAssemblyDirectory, ref assembly) || Utility.TryResolveDllAssembly(assemblyName, Paths.PatcherPluginPath, ref assembly) || Utility.TryResolveDllAssembly(assemblyName, Paths.PluginPath, ref assembly)) { return assembly; } return null; } } internal static class Entrypoint { private static string preloaderPath; public static void Main() { string text = $"preloader_{DateTime.Now:yyyyMMdd_HHmmss_fff}.log"; try { EnvVars.LoadVars(); text = Path.Combine(Path.GetDirectoryName(EnvVars.DOORSTOP_PROCESS_PATH) ?? ".", text); preloaderPath = Path.GetDirectoryName(Path.GetFullPath(EnvVars.DOORSTOP_INVOKE_DLL_PATH)); AppDomain.CurrentDomain.AssemblyResolve += ResolveCurrentDirectory; typeof(Entrypoint).Assembly.GetType("BepInEx.Preloader.PreloaderRunner")?.GetMethod("PreloaderPreMain")?.Invoke(null, null); } catch (Exception ex) { File.WriteAllText(text, ex.ToString()); } finally { AppDomain.CurrentDomain.AssemblyResolve -= ResolveCurrentDirectory; } } internal static Assembly ResolveCurrentDirectory(object sender, ResolveEventArgs args) { AssemblyName assemblyName = new AssemblyName(args.Name); try { return Assembly.LoadFile(Path.Combine(preloaderPath, assemblyName.Name + ".dll")); } catch (Exception) { return null; } } } internal static class PlatformUtils { [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct utsname_osx { private const int osx_utslen = 256; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string sysname; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string nodename; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string release; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string version; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string machine; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct utsname_linux { private const int linux_utslen = 65; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string sysname; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string nodename; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string release; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string version; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string machine; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 65)] public string domainname; } [DllImport("libc.so.6", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "uname")] private static extern IntPtr uname_linux(ref utsname_linux utsname); [DllImport("/usr/lib/libSystem.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "uname")] private static extern IntPtr uname_osx(ref utsname_osx utsname); public static void SetPlatform() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) Platform val = (Platform)17; PropertyInfo property = typeof(Environment).GetProperty("Platform", BindingFlags.Static | BindingFlags.NonPublic); string text = (((object)property == null) ? Environment.OSVersion.Platform.ToString() : property.GetValue(null, new object[0]).ToString()); text = text.ToLowerInvariant(); if (text.Contains("win")) { val = (Platform)37; } else if (text.Contains("mac") || text.Contains("osx")) { val = (Platform)73; } else if (text.Contains("lin") || text.Contains("unix")) { val = (Platform)137; } if (Is(val, (Platform)137) && Directory.Exists("/data") && File.Exists("/system/build.prop")) { val = (Platform)393; } else if (Is(val, (Platform)8) && Directory.Exists("/System/Library/AccessibilityBundles")) { val = (Platform)585; } MethodInfo methodInfo = typeof(Environment).GetProperty("Is64BitOperatingSystem")?.GetGetMethod(); val = (Platform)(((object)methodInfo == null) ? (val | ((IntPtr.Size >= 8) ? 2 : 0)) : (val | (((bool)methodInfo.Invoke(null, new object[0])) ? 2 : 0))); if ((Is(val, (Platform)73) || Is(val, (Platform)137)) && (object)Type.GetType("Mono.Runtime") != null) { IntPtr intPtr; string machine; if (Is(val, (Platform)73)) { utsname_osx utsname = default(utsname_osx); intPtr = uname_osx(ref utsname); machine = utsname.machine; } else { utsname_linux utsname2 = default(utsname_linux); intPtr = uname_linux(ref utsname2); machine = utsname2.machine; } if (intPtr == IntPtr.Zero && (machine.StartsWith("aarch") || machine.StartsWith("arm"))) { val = (Platform)(val | 0x10000); } } else { typeof(object).Module.GetPEKind(out var _, out var machine2); if (machine2 == ImageFileMachine.ARM) { val = (Platform)(val | 0x10000); } } PlatformHelper.Current = val; } private static bool Is(Platform current, Platform expected) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) return (Platform)(current & expected) == expected; } } internal static class Preloader { private enum MonoModBackend { [Description("Auto")] auto, [Description("DynamicMethod")] dynamicmethod, [Description("MethodBuilder")] methodbuilder, [Description("Cecil")] cecil } private static readonly ConfigEntry<string> ConfigEntrypointAssembly = ConfigFile.CoreConfig.Bind<string>("Preloader.Entrypoint", "Assembly", IsPostUnity2017 ? "UnityEngine.CoreModule.dll" : "UnityEngine.dll", "The local filename of the assembly to target."); private static readonly ConfigEntry<string> ConfigEntrypointType = ConfigFile.CoreConfig.Bind<string>("Preloader.Entrypoint", "Type", "Application", "The name of the type in the entrypoint assembly to search for the entrypoint method."); private static readonly ConfigEntry<string> ConfigEntrypointMethod = ConfigFile.CoreConfig.Bind<string>("Preloader.Entrypoint", "Method", ".cctor", "The name of the method in the specified entrypoint assembly and type to hook and load Chainloader from."); internal static readonly ConfigEntry<bool> ConfigApplyRuntimePatches = ConfigFile.CoreConfig.Bind<bool>("Preloader", "ApplyRuntimePatches", true, "Enables or disables runtime patches.\nThis should always be true, unless you cannot start the game due to a Harmony related issue (such as running .NET Standard runtime) or you know what you're doing."); private static readonly ConfigEntry<MonoModBackend> HarmonyBackend = ConfigFile.CoreConfig.Bind<MonoModBackend>("Preloader", "HarmonyBackend", MonoModBackend.auto, "Specifies which MonoMod backend to use for Harmony patches. Auto uses the best available backend.\nThis setting should only be used for development purposes (e.g. debugging in dnSpy). Other code might override this setting."); private static PreloaderConsoleListener PreloaderLog { get; set; } public static bool IsPostUnity2017 { get; } = File.Exists(Path.Combine(Paths.ManagedPath, "UnityEngine.CoreModule.dll")); public static void Run() { //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) try { InitializeHarmony(); HarmonyInteropFix.Apply(); ConsoleManager.Initialize(false); AllocateConsole(); Exception ex = default(Exception); Utility.TryDo((Action)delegate { if (ConfigApplyRuntimePatches.Value) { UnityPatches.Apply(); } }, ref ex); Logger.InitializeInternalLoggers(); Logger.Sources.Add(TraceLogSource.CreateSource()); PreloaderLog = new PreloaderConsoleListener(); Logger.Listeners.Add((ILogListener)(object)PreloaderLog); Version version = typeof(Paths).Assembly.GetName().Version; string text = $"BepInEx {version} - {Paths.ProcessName}"; if (ConsoleManager.ConsoleActive) { ConsoleManager.SetConsoleTitle(text); } Logger.LogMessage((object)$"{text} ({File.GetLastWriteTime(Paths.ExecutablePath)})"); object[] customAttributes = typeof(BuildInfoAttribute).Assembly.GetCustomAttributes(typeof(BuildInfoAttribute), inherit: false); if (customAttributes.Length != 0) { Logger.LogMessage((object)((BuildInfoAttribute)customAttributes[0]).Info); } Logger.LogInfo((object)("Running under Unity v" + GetUnityVersion())); Logger.LogInfo((object)$"CLR runtime version: {Environment.Version}"); Logger.LogInfo((object)$"Supports SRE: {Utility.CLRSupportsDynamicAssemblies}"); Logger.LogInfo((object)$"System platform: {PlatformHelper.Current}"); if (ex != null) { Logger.LogWarning((object)("Failed to apply runtime patches for Mono. See more info in the output log. Error message: " + ex.Message)); } Logger.LogMessage((object)"Preloader started"); AssemblyPatcher.AddPatcher(new PatcherPlugin { TargetDLLs = () => new string[1] { ConfigEntrypointAssembly.Value }, Patcher = PatchEntrypoint, TypeName = "BepInEx.Chainloader" }); Logger.Log((LogLevel)16, (object)$"Loaded 1 patcher method from [BepInEx.Preloader {version}]"); AssemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath); Logger.LogInfo((object)string.Format("{0} patcher plugin{1} loaded", AssemblyPatcher.PatcherPlugins.Count, (AssemblyPatcher.PatcherPlugins.Count == 1) ? "" : "s")); AssemblyPatcher.PatchAndLoad(Paths.DllSearchPaths); AssemblyPatcher.DisposePatchers(); Logger.LogMessage((object)"Preloader finished"); Logger.Listeners.Remove((ILogListener)(object)PreloaderLog); PreloaderLog.Dispose(); } catch (Exception ex2) { try { Logger.LogFatal((object)"Could not run preloader!"); Logger.LogFatal((object)ex2); if (!ConsoleManager.ConsoleActive) { AllocateConsole(); Console.Write(PreloaderLog); } } catch { } string text2 = string.Empty; try { text2 = string.Join("\r\n", PreloaderConsoleListener.LogEvents.Select((LogEventArgs x) => ((object)x).ToString()).ToArray()); text2 += "\r\n"; PreloaderLog?.Dispose(); PreloaderLog = null; } catch { } File.WriteAllText(Path.Combine(Paths.GameRootPath, $"preloader_{DateTime.Now:yyyyMMdd_HHmmss_fff}.log"), text2 + ex2); } } public static void PatchEntrypoint(ref AssemblyDefinition assembly) { //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) if (((IEnumerable<AssemblyNameReference>)assembly.MainModule.AssemblyReferences).Any((AssemblyNameReference x) => x.Name.Contains("BepInEx"))) { throw new Exception("BepInEx has been detected to be patched! Please unpatch before using a patchless variant!"); } string entrypointType = ConfigEntrypointType.Value; string entrypointMethod = ConfigEntrypointMethod.Value; bool flag = Utility.IsNullOrWhiteSpace(entrypointMethod) || entrypointMethod == ".cctor"; TypeDefinition val = ((IEnumerable<TypeDefinition>)assembly.MainModule.Types).FirstOrDefault((Func<TypeDefinition, bool>)((TypeDefinition x) => ((MemberReference)x).Name == entrypointType)); if (val == null) { throw new Exception("The entrypoint type is invalid! Please check your config/BepInEx.cfg file"); } AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(Paths.BepInExAssemblyPath); try { MethodDefinition val3 = ((IEnumerable<MethodDefinition>)((IEnumerable<TypeDefinition>)val2.MainModule.Types).First((TypeDefinition x) => ((MemberReference)x).Name == "Chainloader").Methods).First((MethodDefinition x) => ((MemberReference)x).Name == "Initialize"); MethodDefinition val4 = ((IEnumerable<MethodDefinition>)((IEnumerable<TypeDefinition>)val2.MainModule.Types).First((TypeDefinition x) => ((MemberReference)x).Name == "Chainloader").Methods).First((MethodDefinition x) => ((MemberReference)x).Name == "Start"); MethodReference val5 = assembly.MainModule.ImportReference((MethodReference)(object)val3); MethodReference val6 = assembly.MainModule.ImportReference((MethodReference)(object)val4); List<MethodDefinition> list = new List<MethodDefinition>(); if (flag) { MethodDefinition val7 = ((IEnumerable<MethodDefinition>)val.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => m.IsConstructor && m.IsStatic)); if (val7 == null) { val7 = new MethodDefinition(".cctor", (MethodAttributes)6289, assembly.MainModule.ImportReference(typeof(void))); val.Methods.Add(val7); ILProcessor iLProcessor = val7.Body.GetILProcessor(); iLProcessor.Append(iLProcessor.Create(OpCodes.Ret)); } list.Add(val7); } else { list.AddRange(((IEnumerable<MethodDefinition>)val.Methods).Where((MethodDefinition x) => ((MemberReference)x).Name == entrypointMethod)); } if (!list.Any()) { throw new Exception("The entrypoint method is invalid! Please check your config.ini"); } foreach (MethodDefinition item in list) { ILProcessor iLProcessor2 = item.Body.GetILProcessor(); Instruction val8 = ((IEnumerable<Instruction>)iLProcessor2.Body.Instructions).First(); iLProcessor2.InsertBefore(val8, iLProcessor2.Create(OpCodes.Ldnull)); iLProcessor2.InsertBefore(val8, iLProcessor2.Create(OpCodes.Ldc_I4_0)); iLProcessor2.InsertBefore(val8, iLProcessor2.Create(OpCodes.Call, assembly.MainModule.ImportReference((MethodBase)AccessTools.PropertyGetter(typeof(PreloaderConsoleListener), "LogEvents")))); iLProcessor2.InsertBefore(val8, iLProcessor2.Create(OpCodes.Call, val5)); iLProcessor2.InsertBefore(val8, iLProcessor2.Create(OpCodes.Call, val6)); } } finally { ((IDisposable)val2)?.Dispose(); } } public static void AllocateConsole() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!ConsoleManager.ConsoleEnabled) { return; } try { ConsoleManager.CreateConsole(); Logger.Listeners.Add((ILogListener)new ConsoleLogListener()); } catch (Exception ex) { Logger.LogError((object)"Failed to allocate console!"); Logger.LogError((object)ex); } } public static string GetUnityVersion() { if (PlatformHelper.Is((Platform)37)) { return FileVersionInfo.GetVersionInfo(Paths.ExecutablePath).FileVersion; } return "Unknown (" + (IsPostUnity2017 ? "post" : "pre") + "-2017)"; } private static void InitializeHarmony() { switch (HarmonyBackend.Value) { case MonoModBackend.dynamicmethod: case MonoModBackend.methodbuilder: case MonoModBackend.cecil: Environment.SetEnvironmentVariable("MONOMOD_DMD_TYPE", HarmonyBackend.Value.ToString()); break; default: throw new ArgumentOutOfRangeException("HarmonyBackend", HarmonyBackend.Value, "Unknown backend"); case MonoModBackend.auto: break; } } } public class PreloaderConsoleListener : ILogListener, IDisposable { private static readonly ConfigEntry<LogLevel> ConfigConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind<LogLevel>("Logging.Console", "LogLevels", (LogLevel)31, "Which log levels to show in the console output."); public static List<LogEventArgs> LogEvents { get; } = new List<LogEventArgs>(); public void LogEvent(object sender, LogEventArgs eventArgs) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if ((eventArgs.Level & ConfigConsoleDisplayedLevel.Value) != 0) { LogEvents.Add(eventArgs); } } public void Dispose() { } } } namespace BepInEx.Preloader.RuntimeFixes { internal static class ConsoleSetOutFix { private static LoggedTextWriter loggedTextWriter; internal static ManualLogSource ConsoleLogSource = Logger.CreateLogSource("Console"); public static void Apply() { loggedTextWriter = new LoggedTextWriter { Parent = Console.Out }; Console.SetOut(loggedTextWriter); Harmony.CreateAndPatchAll(typeof(ConsoleSetOutFix), (string)null); } [HarmonyPatch(typeof(Console), "SetOut")] [HarmonyPrefix] private static bool OnSetOut(TextWriter newOut) { loggedTextWriter.Parent = newOut; return false; } } internal class LoggedTextWriter : TextWriter { public override Encoding Encoding { get; } = Encoding.UTF8; public TextWriter Parent { get; set; } public override void Flush() { Parent.Flush(); } public override void Write(string value) { ConsoleSetOutFix.ConsoleLogSource.LogInfo((object)value); Parent.Write(value); } public override void WriteLine(string value) { ConsoleSetOutFix.ConsoleLogSource.LogInfo((object)value); Parent.WriteLine(value); } } internal static class HarmonyInteropFix { public static void Apply() { HarmonyInterop.Initialize(Paths.CachePath); Harmony.CreateAndPatchAll(typeof(HarmonyInteropFix), "org.bepinex.fixes.harmonyinterop"); } [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(Assembly), "LoadFile", new Type[] { typeof(string) })] private static Assembly LoadFile(string path) { return null; } [HarmonyPatch(typeof(Assembly), "LoadFile", new Type[] { typeof(string) })] [HarmonyPatch(typeof(Assembly), "LoadFrom", new Type[] { typeof(string) })] [HarmonyPrefix] private static bool OnAssemblyLoad(ref Assembly __result, string __0) { HarmonyInterop.TryShim(__0, Paths.GameRootPath, (Action<string>)Logger.LogWarning, TypeLoader.ReaderParameters); __result = LoadFile(__0); return true; } } internal static class TraceFix { private static Type TraceImplType; private static object ListenersSyncRoot; private static TraceListenerCollection Listeners; private static PropertyInfo prop_AutoFlush; private static bool AutoFlush => (bool)prop_AutoFlush.GetValue(null, null); public static void ApplyFix() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown TraceImplType = AppDomain.CurrentDomain.GetAssemblies().First((Assembly x) => x.GetName().Name == "System").GetTypes() .FirstOrDefault((Type x) => x.Name == "TraceImpl"); if ((object)TraceImplType != null) { ListenersSyncRoot = AccessTools.Property(TraceImplType, "ListenersSyncRoot").GetValue(null, null); Listeners = (TraceListenerCollection)AccessTools.Property(TraceImplType, "Listeners").GetValue(null, null); prop_AutoFlush = AccessTools.Property(TraceImplType, "AutoFlush"); new Harmony("com.bepis.bepinex.tracefix").Patch((MethodBase)typeof(Trace).GetMethod("DoTrace", BindingFlags.Static | BindingFlags.NonPublic), new HarmonyMethod(typeof(TraceFix).GetMethod("DoTraceReplacement", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static bool DoTraceReplacement(string kind, Assembly report, string message) { string source = string.Empty; try { source = report.GetName().Name; } catch (MethodAccessException) { } TraceEventType eventType = (TraceEventType)Enum.Parse(typeof(TraceEventType), kind); lock (ListenersSyncRoot) { foreach (TraceListener listener in Listeners) { listener.TraceEvent(new TraceEventCache(), source, eventType, 0, message); if (AutoFlush) { listener.Flush(); } } } return false; } } internal static class UnityPatches { private static Harmony HarmonyInstance { get; set; } public static Dictionary<string, string> AssemblyLocations { get; } = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); public static void Apply() { HarmonyInstance = Harmony.CreateAndPatchAll(typeof(UnityPatches), (string)null); try { TraceFix.ApplyFix(); } catch { } } [HarmonyPostfix] [HarmonyPatch(/*Could not decode attribute arguments.*/)] public static void GetLocation(ref string __result, Assembly __instance) { if (AssemblyLocations.TryGetValue(__instance.FullName, out var value)) { __result = value; } } [HarmonyPostfix] [HarmonyPatch(/*Could not decode attribute arguments.*/)] public static void GetCodeBase(ref string __result, Assembly __instance) { if (AssemblyLocations.TryGetValue(__instance.FullName, out var value)) { __result = "file://" + value.Replace('\\', '/'); } } } internal static class XTermFix { public static int intOffset; public static void Apply() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown if (!PlatformHelper.Is((Platform)37) && (object)typeof(Console).Assembly.GetType("System.ConsoleDriver") != null && (object)AccessTools.Method("System.TermInfoReader:DetermineVersion", (Type[])null, (Type[])null) == null) { DetourHelper.Native = (IDetourNativePlatform)new DetourNativeX86Platform(); Harmony val = new Harmony("com.bepinex.xtermfix"); val.Patch((MethodBase)AccessTools.Method("System.TermInfoReader:ReadHeader", (Type[])null, (Type[])null), new HarmonyMethod(typeof(XTermFix), "ReadHeaderPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method("System.TermInfoReader:Get", new Type[1] { AccessTools.TypeByName("System.TermInfoNumbers") }, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(XTermFix), "GetTermInfoNumbersTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method("System.TermInfoReader:Get", new Type[1] { AccessTools.TypeByName("System.TermInfoStrings") }, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(XTermFix), "GetTermInfoStringsTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method("System.TermInfoReader:GetStringBytes", new Type[1] { AccessTools.TypeByName("System.TermInfoStrings") }, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(XTermFix), "GetTermInfoStringsTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); DetourHelper.Native = null; } } public static int GetInt32(byte[] buffer, int offset) { byte num = buffer[offset]; int num2 = buffer[offset + 1]; int num3 = buffer[offset + 2]; int num4 = buffer[offset + 3]; return num | (num2 << 8) | (num3 << 16) | (num4 << 24); } public static short GetInt16(byte[] buffer, int offset) { byte num = buffer[offset]; int num2 = buffer[offset + 1]; return (short)(num | (num2 << 8)); } public static int GetInteger(byte[] buffer, int offset) { if (intOffset != 2) { return GetInt32(buffer, offset); } return GetInt16(buffer, offset); } public static void DetermineVersion(short magic) { switch (magic) { case 282: intOffset = 2; break; case 542: intOffset = 4; break; default: throw new Exception($"Unknown xterm header format: {magic}"); } } public static bool ReadHeaderPrefix(byte[] buffer, ref int position, ref short ___boolSize, ref short ___numSize, ref short ___strOffsets) { short @int = GetInt16(buffer, position); position += 2; DetermineVersion(@int); position += 2; ___boolSize = GetInt16(buffer, position); position += 2; ___numSize = GetInt16(buffer, position); position += 2; ___strOffsets = GetInt16(buffer, position); position += 2; position += 2; return false; } public static IEnumerable<CodeInstruction> GetTermInfoNumbersTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); list[31] = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(XTermFix), "intOffset")); list[36] = new CodeInstruction(OpCodes.Nop, (object)null); list[39] = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(XTermFix), "GetInteger", (Type[])null, (Type[])null)); return list; } public static IEnumerable<CodeInstruction> GetTermInfoStringsTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); list[32] = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(XTermFix), "intOffset")); return list; } } } namespace BepInEx.Preloader.Patching { public delegate void AssemblyPatcherDelegate(ref AssemblyDefinition assembly); public static class AssemblyPatcher { private const BindingFlags ALL = BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static readonly string DumpedAssembliesPath = Utility.CombinePaths(new string[3] { Paths.BepInExRootPath, "DumpedAssemblies", Paths.ProcessName }); private static readonly Dictionary<string, string> DumpedAssemblyPaths = new Dictionary<string, string>(); private static readonly ConfigEntry<bool> ConfigDumpAssemblies = ConfigFile.CoreConfig.Bind<bool>("Preloader", "DumpAssemblies", false, "If enabled, BepInEx will save patched assemblies into BepInEx/DumpedAssemblies.\nThis can be used by developers to inspect and debug preloader patchers."); private static readonly ConfigEntry<bool> ConfigLoadDumpedAssemblies = ConfigFile.CoreConfig.Bind<bool>("Preloader", "LoadDumpedAssemblies", false, "If enabled, BepInEx will load patched assemblies from BepInEx/DumpedAssemblies instead of memory.\nThis can be used to be able to load patched assemblies into debuggers like dnSpy.\nIf set to true, will override DumpAssemblies."); private static readonly ConfigEntry<bool> ConfigBreakBeforeLoadAssemblies = ConfigFile.CoreConfig.Bind<bool>("Preloader", "BreakBeforeLoadAssemblies", false, "If enabled, BepInEx will call Debugger.Break() once before loading patched assemblies.\nThis can be used with debuggers like dnSpy to install breakpoints into patched assemblies before they are loaded."); public static List<PatcherPlugin> PatcherPlugins { get; } = new List<PatcherPlugin>(); private static IEnumerable<PatcherPlugin> PatcherPluginsSafe => PatcherPlugins.ToList(); public static void AddPatcher(PatcherPlugin patcher) { PatcherPlugins.Add(patcher); } private static T CreateDelegate<T>(MethodInfo method) where T : class { if ((object)method == null) { return null; } return Delegate.CreateDelegate(typeof(T), method) as T; } private static PatcherPlugin ToPatcherPlugin(TypeDefinition type) { if (type.IsInterface || (type.IsAbstract && !type.IsSealed)) { return null; } MethodDefinition val = ((IEnumerable<MethodDefinition>)type.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name.Equals("get_TargetDLLs", StringComparison.InvariantCultureIgnoreCase) && m.IsPublic && m.IsStatic)); if (val == null || ((MemberReference)((MethodReference)val).ReturnType).FullName != "System.Collections.Generic.IEnumerable`1<System.String>") { return null; } if (((IEnumerable<MethodDefinition>)type.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name.Equals("Patch") && m.IsPublic && m.IsStatic && ((MemberReference)((MethodReference)m).ReturnType).FullName == "System.Void" && ((MethodReference)m).Parameters.Count == 1 && (((MemberReference)((ParameterReference)((MethodReference)m).Parameters[0]).ParameterType).FullName == "Mono.Cecil.AssemblyDefinition&" || ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[0]).ParameterType).FullName == "Mono.Cecil.AssemblyDefinition"))) == null) { return null; } return new PatcherPlugin { TypeName = ((MemberReference)type).FullName }; } public static void AddPatchersFromDirectory(string directory) { if (!Directory.Exists(directory)) { return; } SortedDictionary<string, PatcherPlugin> sortedDictionary = new SortedDictionary<string, PatcherPlugin>(); foreach (KeyValuePair<string, List<PatcherPlugin>> item in TypeLoader.FindPluginTypes<PatcherPlugin>(directory, (Func<TypeDefinition, PatcherPlugin>)ToPatcherPlugin, (Func<AssemblyDefinition, bool>)null, (string)null)) { string key = item.Key; List<PatcherPlugin> value = item.Value; if (value.Count == 0) { continue; } Assembly assembly = Assembly.LoadFile(key); foreach (PatcherPlugin item2 in value) { try { Type type = assembly.GetType(item2.TypeName); MethodInfo[] methods = type.GetMethods(BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); item2.Initializer = CreateDelegate<Action>(methods.FirstOrDefault((MethodInfo m) => m.Name.Equals("Initialize", StringComparison.InvariantCultureIgnoreCase) && m.GetParameters().Length == 0 && (object)m.ReturnType == typeof(void))); item2.Finalizer = CreateDelegate<Action>(methods.FirstOrDefault((MethodInfo m) => m.Name.Equals("Finish", StringComparison.InvariantCultureIgnoreCase) && m.GetParameters().Length == 0 && (object)m.ReturnType == typeof(void))); item2.TargetDLLs = CreateDelegate<Func<IEnumerable<string>>>(type.GetProperty("TargetDLLs", BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetGetMethod()); MethodInfo patcher = methods.FirstOrDefault((MethodInfo m) => m.Name.Equals("Patch", StringComparison.CurrentCultureIgnoreCase) && (object)m.ReturnType == typeof(void) && m.GetParameters().Length == 1 && ((object)m.GetParameters()[0].ParameterType == typeof(AssemblyDefinition) || (object)m.GetParameters()[0].ParameterType == typeof(AssemblyDefinition).MakeByRefType())); item2.Patcher = delegate(ref AssemblyDefinition pAss) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown object[] array = new object[1] { pAss }; patcher.Invoke(null, array); pAss = (AssemblyDefinition)array[0]; }; sortedDictionary.Add(assembly.GetName().Name + "/" + type.FullName, item2); } catch (Exception ex) { Logger.LogError((object)("Failed to load patcher [" + item2.TypeName + "]: " + ex.Message)); if (ex is ReflectionTypeLoadException ex2) { Logger.LogDebug((object)TypeLoader.TypeLoadExceptionToString(ex2)); } else { Logger.LogDebug((object)ex.ToString()); } } } AssemblyName name = assembly.GetName(); Logger.Log((LogLevel)(value.Any() ? 16 : 32), (object)string.Format("Loaded {0} patcher method{1} from [{2} {3}]", value.Count, (value.Count == 1) ? "" : "s", name.Name, name.Version)); } foreach (KeyValuePair<string, PatcherPlugin> item3 in sortedDictionary) { AddPatcher(item3.Value); } } private static void InitializePatchers() { foreach (PatcherPlugin item in PatcherPluginsSafe) { try { item.Initializer?.Invoke(); } catch (Exception arg) { Logger.LogError((object)$"Failed to run Initializer of {item.TypeName}: {arg}"); } } } private static void FinalizePatching() { foreach (PatcherPlugin item in PatcherPluginsSafe) { try { item.Finalizer?.Invoke(); } catch (Exception arg) { Logger.LogError((object)$"Failed to run Finalizer of {item.TypeName}: {arg}"); } } } public static void DisposePatchers() { PatcherPlugins.Clear(); } private static string GetAssemblyName(string fullName) { AssemblyName assemblyName = default(AssemblyName); if (!Utility.TryParseAssemblyName(fullName, ref assemblyName)) { return fullName; } return assemblyName.Name; } public static void PatchAndLoad(params string[] directories) { Dictionary<string, AssemblyDefinition> dictionary = new Dictionary<string, AssemblyDefinition>(StringComparer.InvariantCultureIgnoreCase); foreach (string uniqueFilesInDirectory in Utility.GetUniqueFilesInDirectories((IEnumerable<string>)directories, "*.dll")) { AssemblyDefinition val; try { val = AssemblyDefinition.ReadAssembly(uniqueFilesInDirectory); } catch (BadImageFormatException) { continue; } if (((AssemblyNameReference)val.Name).Name == "System" || ((AssemblyNameReference)val.Name).Name == "mscorlib") { val.Dispose(); continue; } if (UnityPatches.AssemblyLocations.ContainsKey(val.FullName)) { Logger.LogWarning((object)("Tried to load duplicate assembly " + Path.GetFileName(uniqueFilesInDirectory) + " from Managed folder! Skipping...")); continue; } dictionary.Add(Path.GetFileName(uniqueFilesInDirectory), val); UnityPatches.AssemblyLocations.Add(val.FullName, Path.GetFullPath(uniqueFilesInDirectory)); } InitializePatchers(); HashSet<string> patchedAssemblies = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); Dictionary<string, string> dictionary2 = new Dictionary<string, string>(); HashSet<string> hashSet = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); foreach (PatcherPlugin item in PatcherPluginsSafe) { foreach (string item2 in item.TargetDLLs()) { if (!dictionary.TryGetValue(item2, out var value) || hashSet.Contains(item2)) { continue; } Logger.LogInfo((object)("Patching [" + ((AssemblyNameReference)value.Name).Name + "] with [" + item.TypeName + "]")); try { item.Patcher?.Invoke(ref value); } catch (Exception arg) { Logger.LogError((object)$"Failed to run [{item.TypeName}] when patching [{((AssemblyNameReference)value.Name).Name}]. This assembly will not be patched. Error: {arg}"); patchedAssemblies.Remove(item2); hashSet.Add(item2); continue; } dictionary[item2] = value; patchedAssemblies.Add(item2); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { string assemblyName = GetAssemblyName(assemblies[i].FullName); if (!dictionary2.ContainsKey(assemblyName)) { dictionary2[assemblyName] = item.TypeName; } } } } HashSet<string> patchedAssemblyNames = new HashSet<string>(from kv in dictionary where patchedAssemblies.Contains(kv.Key) select ((AssemblyNameReference)kv.Value.Name).Name, StringComparer.InvariantCultureIgnoreCase); List<KeyValuePair<string, string>> list = dictionary2.Where((KeyValuePair<string, string> kv) => patchedAssemblyNames.Contains(kv.Key)).ToList(); if (list.Count != 0) { Logger.LogWarning((object)new StringBuilder().AppendLine("The following assemblies have been loaded too early and will not be patched by preloader:").AppendLine(string.Join(Environment.NewLine, list.Select((KeyValuePair<string, string> kv) => "* [" + kv.Key + "] (first loaded by [" + kv.Value + "])").ToArray())).AppendLine("Expect unexpected behavior and issues with plugins and patchers not being loaded.") .ToString()); } DumpedAssemblyPaths.Clear(); if (ConfigDumpAssemblies.Value || ConfigLoadDumpedAssemblies.Value) { if (!Directory.Exists(DumpedAssembliesPath)) { Directory.CreateDirectory(DumpedAssembliesPath); } FileStream fileStream = default(FileStream); foreach (KeyValuePair<string, AssemblyDefinition> item3 in dictionary) { string key = item3.Key; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(key); string extension = Path.GetExtension(key); AssemblyDefinition value2 = item3.Value; if (!patchedAssemblies.Contains(key)) { continue; } int num = 0; string text2; while (true) { string text = ((num > 0) ? $"_{num}" : ""); text2 = Path.Combine(DumpedAssembliesPath, fileNameWithoutExtension + text + extension); if (Utility.TryOpenFileStream(text2, FileMode.Create, ref fileStream, FileAccess.ReadWrite, FileShare.Read)) { break; } num++; } value2.Write((Stream)fileStream); fileStream.Dispose(); DumpedAssemblyPaths[key] = text2; } } if (ConfigBreakBeforeLoadAssemblies.Value) { Logger.LogInfo((object)("BepInEx is about load the following assemblies:\n" + string.Join("\n", patchedAssemblies.ToArray()))); Logger.LogInfo((object)("The assemblies were dumped into " + DumpedAssembliesPath)); Logger.LogInfo((object)"Load any assemblies into the debugger, set breakpoints and continue execution."); Debugger.Break(); } foreach (KeyValuePair<string, AssemblyDefinition> item4 in dictionary) { string key2 = item4.Key; AssemblyDefinition value3 = item4.Value; if (patchedAssemblies.Contains(key2)) { Load(value3, key2); } value3.Dispose(); } FinalizePatching(); } public static void Load(AssemblyDefinition assembly, string filename) { if (ConfigLoadDumpedAssemblies.Value && DumpedAssemblyPaths.TryGetValue(filename, out var value)) { Assembly.LoadFile(value); return; } using MemoryStream memoryStream = new MemoryStream(); assembly.Write((Stream)memoryStream); Assembly.Load(memoryStream.ToArray()); } } public class PatcherPlugin : ICacheable { public Func<IEnumerable<string>> TargetDLLs { get; set; } public Action Initializer { get; set; } public Action Finalizer { get; set; } public AssemblyPatcherDelegate Patcher { get; set; } public string TypeName { get; set; } = string.Empty; public void Save(BinaryWriter bw) { bw.Write(TypeName); } public void Load(BinaryReader br) { TypeName = br.ReadString(); } } }
BepInEx/core/HarmonyXInterop.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using HarmonyLib; using HarmonyLib.Public.Patching; using HarmonyLib.Tools; using Mono.Cecil; using MonoMod.Utils; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("HarmonyXInterop")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HarmonyXInterop")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("160F7FE0-288D-435C-9E7E-497D3E0DE3A6")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace HarmonyXInterop; internal static class DMDUtil { public static MethodInfo GenerateWith<T>(this DynamicMethodDefinition dmd, object context = null) where T : DMDGenerator<T>, new() { return DMDGenerator<T>.Generate(dmd, context); } } public static class HarmonyInterop { private const string BACKUP_PATH = "BepInEx_Shim_Backup"; private static Version maxAvailableShimVersion; private static readonly SortedDictionary<Version, string> Assemblies = new SortedDictionary<Version, string>(); private static readonly HashSet<string> InteropAssemblyNames = new HashSet<string>(); private static readonly Func<MethodBase, PatchInfo, MethodInfo> UpdateWrapper = AccessTools.MethodDelegate<Func<MethodBase, PatchInfo, MethodInfo>>(AccessTools.Method(typeof(HarmonyManipulator).Assembly.GetType("HarmonyLib.PatchFunctions"), "UpdateWrapper", (Type[])null, (Type[])null), (object)null, true); private static readonly Action<LogChannel, Func<string>, bool> HarmonyLog = AccessTools.MethodDelegate<Action<LogChannel, Func<string>, bool>>(AccessTools.Method(typeof(Logger), "Log", (Type[])null, (Type[])null), (object)null, true); private static readonly Action<LogChannel, string, bool> HarmonyLogText = AccessTools.MethodDelegate<Action<LogChannel, string, bool>>(AccessTools.Method(typeof(Logger), "LogText", (Type[])null, (Type[])null), (object)null, true); private static readonly Dictionary<string, long> shimCache = new Dictionary<string, long>(); private static BinaryWriter cacheWriter; public static void Log(int channel, Func<string> message) { HarmonyLog((LogChannel)channel, message, arg3: false); } public static void LogText(int channel, string message) { HarmonyLogText((LogChannel)channel, message, arg3: false); } public static void Initialize(string cachePath) { Directory.CreateDirectory(cachePath); string path = Path.Combine(cachePath, "harmony_interop_cache.dat"); string[] files = Directory.GetFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "0Harmony*.dll", SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { AssemblyDefinition val = AssemblyDefinition.ReadAssembly(files[i]); try { if (((AssemblyNameReference)val.Name).Name != "0Harmony") { Assemblies.Add(((AssemblyNameReference)val.Name).Version, ((AssemblyNameReference)val.Name).Name); InteropAssemblyNames.Add(((AssemblyNameReference)val.Name).Name); } } finally { ((IDisposable)val)?.Dispose(); } } maxAvailableShimVersion = Assemblies.LastOrDefault().Key; if (File.Exists(path)) { try { using BinaryReader binaryReader = new BinaryReader(File.OpenRead(path)); while (true) { string key = binaryReader.ReadString(); long value = binaryReader.ReadInt64(); shimCache[key] = value; } } catch (Exception) { } } try { cacheWriter = new BinaryWriter(File.Create(path)); foreach (KeyValuePair<string, long> item in shimCache) { cacheWriter.Write(item.Key); cacheWriter.Write(item.Value); } cacheWriter.Flush(); } catch (IOException) { } } public static byte[] TryShim(string path, string gameRootDirectory, Action<string> logMessage = null, ReaderParameters readerParameters = null) { HashSet<string> hashSet = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); List<string> deps; byte[] result = TryShimInternal(path, gameRootDirectory, logMessage, readerParameters, out deps); foreach (string item in deps) { hashSet.Add(item); } while (hashSet.Count != 0) { string text = hashSet.First(); TryShimInternal(text, gameRootDirectory, logMessage, readerParameters, out deps); foreach (string item2 in deps) { hashSet.Add(item2); } hashSet.Remove(text); } return result; } private static bool NeedsShimming(string path, out long lastWriteTime, Action<string> logMessage = null) { lastWriteTime = 0L; try { if (!File.Exists(path)) { return false; } } catch (Exception arg) { logMessage?.Invoke($"Failed to read path {path}: {arg}"); return false; } lastWriteTime = File.GetLastWriteTimeUtc(path).Ticks; if (shimCache.TryGetValue(path, out var value)) { return value != lastWriteTime; } return true; } private static byte[] TryShimInternal(string path, string gameRootDirectory, Action<string> logMessage, ReaderParameters readerParameters, out List<string> deps) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) deps = new List<string>(); if (!NeedsShimming(path, out var lastWriteTime, logMessage)) { return null; } byte[] result = null; try { string dir = Path.GetDirectoryName(path); byte[] array; try { array = File.ReadAllBytes(path); } catch (Exception) { return null; } using MemoryStream memoryStream = new MemoryStream(array); AssemblyDefinition val = AssemblyDefinition.ReadAssembly((Stream)memoryStream, (ReaderParameters)(((object)readerParameters) ?? ((object)new ReaderParameters()))); try { deps.AddRange(from a in (IEnumerable<AssemblyNameReference>)val.MainModule.AssemblyReferences select Path.Combine(dir, a.Name + ".dll") into p where NeedsShimming(p, out var _, logMessage) select p); AssemblyNameReference harmonyRef = ((IEnumerable<AssemblyNameReference>)val.MainModule.AssemblyReferences).FirstOrDefault((Func<AssemblyNameReference, bool>)((AssemblyNameReference a) => a.Name.StartsWith("0Harmony") && !InteropAssemblyNames.Contains(a.Name))); if (harmonyRef != null) { KeyValuePair<Version, string> keyValuePair = Assemblies.LastOrDefault((KeyValuePair<Version, string> kv) => VersionMatches(kv.Key, harmonyRef.Version)); if (keyValuePair.Value != null) { logMessage?.Invoke("Shimming " + path + " to use older version of Harmony (" + keyValuePair.Value + "). Please update the plugin if possible."); harmonyRef.Name = keyValuePair.Value; using MemoryStream memoryStream2 = new MemoryStream(); val.Write((Stream)memoryStream2); try { string path2 = Path.Combine(gameRootDirectory, "BepInEx_Shim_Backup"); string directoryName = Path.GetDirectoryName(Path.GetFullPath(path).Substring(gameRootDirectory.Length + 1)); string text = Path.Combine(path2, directoryName); Directory.CreateDirectory(text); File.WriteAllBytes(Path.Combine(text, Path.GetFileName(path)), array); File.WriteAllBytes(path, memoryStream2.ToArray()); lastWriteTime = File.GetLastWriteTimeUtc(path).Ticks; } catch (IOException) { lastWriteTime = 0L; } result = memoryStream2.ToArray(); } } shimCache[path] = lastWriteTime; if (cacheWriter != null) { cacheWriter.Write(path); cacheWriter.Write(lastWriteTime); cacheWriter.Flush(); } } finally { ((IDisposable)val)?.Dispose(); } } catch (Exception arg) { logMessage?.Invoke($"Failed to shim {path}: {arg}"); } return result; static bool VersionMatches(Version cmpV, Version refV) { if (maxAvailableShimVersion != null && refV <= maxAvailableShimVersion && cmpV.Major == refV.Major && cmpV.Minor == refV.Minor) { return cmpV <= refV; } return false; } } public static void ApplyPatch(MethodBase target, PatchInfoWrapper add, PatchInfoWrapper remove) { PatchInfo val = PatchManager.ToPatchInfo(target); lock (val) { val.prefixes = Sync(add.prefixes, remove.prefixes, val.prefixes); val.postfixes = Sync(add.postfixes, remove.postfixes, val.postfixes); val.transpilers = Sync(WrapTranspilers(add.transpilers), WrapTranspilers(remove.transpilers), val.transpilers); val.finalizers = Sync(add.finalizers, remove.finalizers, val.finalizers); } UpdateWrapper(target, val); static PatchMethod[] WrapTranspilers(PatchMethod[] transpilers) { return transpilers.Select((PatchMethod p) => new PatchMethod { after = p.after, before = p.before, method = TranspilerInterop.WrapInterop(p.method), owner = p.owner, priority = p.priority }).ToArray(); } } private static Patch[] Sync(PatchMethod[] add, PatchMethod[] remove, Patch[] current) { if (add.Length == 0 && remove.Length == 0) { return current; } current = current.Where((Patch p) => !remove.Any((PatchMethod r) => (object)r.method == p.PatchMethod && r.owner == p.owner)).ToArray(); int initialIndex = current.Length; return current.Concat(add.Where((PatchMethod method) => method != null).Select((Func<PatchMethod, int, Patch>)((PatchMethod method, int i) => new Patch(method.ToHarmonyMethod(), i + initialIndex, method.owner)))).ToArray(); } } public class PatchInfoWrapper { public PatchMethod[] finalizers; public PatchMethod[] postfixes; public PatchMethod[] prefixes; public PatchMethod[] transpilers; } public class PatchMethod { public string[] after; public string[] before; public MethodInfo method; public string owner; public int priority = -1; public HarmonyMethod ToHarmonyMethod() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown return new HarmonyMethod { after = after, before = before, method = method, priority = priority }; } } public class PatchMethodComparer : IEqualityComparer<PatchMethod> { public static PatchMethodComparer Instance { get; } = new PatchMethodComparer(); public bool Equals(PatchMethod x, PatchMethod y) { if (x == y) { return true; } if (x == null) { return false; } if (y == null) { return false; } if ((object)x.GetType() != y.GetType()) { return false; } if (object.Equals(x.method, y.method)) { return x.owner == y.owner; } return false; } public int GetHashCode(PatchMethod obj) { return ((((object)obj.method != null) ? obj.method.GetHashCode() : 0) * 397) ^ ((obj.owner != null) ? obj.owner.GetHashCode() : 0); } } internal static class TranspilerInterop { private static readonly Dictionary<OpCode, OpCode> AllJumpCodes = new Dictionary<OpCode, OpCode> { { OpCodes.Beq_S, OpCodes.Beq }, { OpCodes.Bge_S, OpCodes.Bge }, { OpCodes.Bge_Un_S, OpCodes.Bge_Un }, { OpCodes.Bgt_S, OpCodes.Bgt }, { OpCodes.Bgt_Un_S, OpCodes.Bgt_Un }, { OpCodes.Ble_S, OpCodes.Ble }, { OpCodes.Ble_Un_S, OpCodes.Ble_Un }, { OpCodes.Blt_S, OpCodes.Blt }, { OpCodes.Blt_Un_S, OpCodes.Blt_Un }, { OpCodes.Bne_Un_S, OpCodes.Bne_Un }, { OpCodes.Brfalse_S, OpCodes.Brfalse }, { OpCodes.Brtrue_S, OpCodes.Brtrue }, { OpCodes.Br_S, OpCodes.Br }, { OpCodes.Leave_S, OpCodes.Leave } }; private static readonly Dictionary<MethodInfo, MethodInfo> Wrappers = new Dictionary<MethodInfo, MethodInfo>(); private static readonly MethodInfo ResolveToken = AccessTools.Method(typeof(MethodBase), "GetMethodFromHandle", new Type[1] { typeof(RuntimeMethodHandle) }, (Type[])null); private static readonly MethodInfo ApplyTranspilerMethod = AccessTools.Method(typeof(TranspilerInterop), "ApplyTranspiler", (Type[])null, (Type[])null); public static MethodInfo WrapInterop(MethodInfo transpiler) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown lock (Wrappers) { if (Wrappers.TryGetValue(transpiler, out var value)) { return value; } } DynamicMethodDefinition val = new DynamicMethodDefinition("TranspilerWrapper<" + Extensions.GetID((MethodBase)transpiler, (string)null, (string)null, true, false, true) + ">", typeof(IEnumerable<CodeInstruction>), new Type[3] { typeof(IEnumerable<CodeInstruction>), typeof(ILGenerator), typeof(MethodBase) }); try { ILGenerator iLGenerator = val.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldtoken, transpiler); iLGenerator.Emit(OpCodes.Call, ResolveToken); iLGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo)); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Ldarg_2); iLGenerator.Emit(OpCodes.Call, ApplyTranspilerMethod); iLGenerator.Emit(OpCodes.Ret); MethodInfo methodInfo = val.GenerateWith<DMDCecilGenerator>((object)null); lock (Wrappers) { Wrappers[transpiler] = methodInfo; } return methodInfo; } finally { ((IDisposable)val)?.Dispose(); } } private static IEnumerable<CodeInstruction> ApplyTranspiler(MethodInfo transpiler, IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase method) { Dictionary<object, Dictionary<string, object>> unassignedValues; IEnumerable enumerable = ConvertToGeneralInstructions(transpiler, instructions, out unassignedValues); List<object> originalInstructions = null; if (unassignedValues != null) { originalInstructions = instructions.Cast<object>().ToList(); } List<object> transpilerCallParameters = GetTranspilerCallParameters(generator, transpiler, method, enumerable); if (transpiler.Invoke(null, transpilerCallParameters.ToArray()) is IEnumerable enumerable2) { enumerable = enumerable2; } if (unassignedValues != null) { enumerable = ConvertToOurInstructions(enumerable, typeof(CodeInstruction), originalInstructions, unassignedValues); } return (enumerable as List<CodeInstruction>) ?? enumerable.Cast<CodeInstruction>().ToList(); } private static OpCode ReplaceShortJumps(OpCode opcode) { using (IEnumerator<KeyValuePair<OpCode, OpCode>> enumerator = AllJumpCodes.Where((KeyValuePair<OpCode, OpCode> pair) => opcode == pair.Key).GetEnumerator()) { if (enumerator.MoveNext()) { return enumerator.Current.Value; } } return opcode; } private static object ConvertInstruction(Type type, object instruction, out Dictionary<string, object> unassigned) { Dictionary<string, object> nonExisting = new Dictionary<string, object>(); object result = AccessTools.MakeDeepCopy(instruction, type, (Func<string, Traverse, Traverse, object>)delegate(string namePath, Traverse trvSrc, Traverse trvDest) { object value = trvSrc.GetValue(); if (trvDest.FieldExists()) { if (!(namePath == "opcode")) { return value; } return ReplaceShortJumps((OpCode)value); } nonExisting[namePath] = value; return null; }, ""); unassigned = nonExisting; return result; } private static bool ShouldAddExceptionInfo(object op, int opIndex, List<object> originalInstructions, List<object> newInstructions, Dictionary<object, Dictionary<string, object>> unassignedValues) { int num = originalInstructions.IndexOf(op); if (num == -1) { return false; } if (!unassignedValues.TryGetValue(op, out var unassigned)) { return false; } if (!unassigned.TryGetValue("blocks", out var blocksObject)) { return false; } List<ExceptionBlock> blocks = blocksObject as List<ExceptionBlock>; if (newInstructions.Count((object instr) => instr == op) <= 1) { return true; } ExceptionBlock val = ((IEnumerable<ExceptionBlock>)blocks).FirstOrDefault((Func<ExceptionBlock, bool>)((ExceptionBlock block) => (int)block.blockType != 5)); ExceptionBlock val2 = ((IEnumerable<ExceptionBlock>)blocks).FirstOrDefault((Func<ExceptionBlock, bool>)((ExceptionBlock block) => (int)block.blockType == 5)); if (val != null && val2 == null) { object obj = originalInstructions.Skip(num + 1).FirstOrDefault(delegate(object instr) { if (!unassignedValues.TryGetValue(instr, out unassigned)) { return false; } if (!unassigned.TryGetValue("blocks", out blocksObject)) { return false; } blocks = blocksObject as List<ExceptionBlock>; return blocks.Any(); }); if (obj != null) { int num2 = num + 1; int num3 = num2 + originalInstructions.Skip(num2).ToList().IndexOf(obj) - 1; IEnumerable<object> first = originalInstructions.GetRange(num2, num3 - num2).Intersect(newInstructions); obj = newInstructions.Skip(opIndex + 1).FirstOrDefault(delegate(object instr) { if (!unassignedValues.TryGetValue(instr, out unassigned)) { return false; } if (!unassigned.TryGetValue("blocks", out blocksObject)) { return false; } blocks = blocksObject as List<ExceptionBlock>; return blocks.Any(); }); if (obj != null) { num2 = opIndex + 1; num3 = num2 + newInstructions.Skip(opIndex + 1).ToList().IndexOf(obj) - 1; List<object> range = newInstructions.GetRange(num2, num3 - num2); return !first.Except(range).ToList().Any(); } } } if (val == null && val2 != null) { object obj2 = originalInstructions.GetRange(0, num).LastOrDefault(delegate(object instr) { if (!unassignedValues.TryGetValue(instr, out unassigned)) { return false; } if (!unassigned.TryGetValue("blocks", out blocksObject)) { return false; } blocks = blocksObject as List<ExceptionBlock>; return blocks.Any(); }); if (obj2 == null) { return true; } int num4 = originalInstructions.GetRange(0, num).LastIndexOf(obj2); int num5 = num; IEnumerable<object> first2 = originalInstructions.GetRange(num4, num5 - num4).Intersect(newInstructions); obj2 = newInstructions.GetRange(0, opIndex).LastOrDefault(delegate(object instr) { if (!unassignedValues.TryGetValue(instr, out unassigned)) { return false; } if (!unassigned.TryGetValue("blocks", out blocksObject)) { return false; } blocks = blocksObject as List<ExceptionBlock>; return blocks.Any(); }); if (obj2 == null) { return true; } num4 = newInstructions.GetRange(0, opIndex).LastIndexOf(obj2); num5 = opIndex; List<object> range2 = newInstructions.GetRange(num4, num5 - num4); return !first2.Except(range2).Any(); } return true; } private static IEnumerable ConvertInstructionsAndUnassignedValues(Type type, IEnumerable enumerable, out Dictionary<object, Dictionary<string, object>> unassignedValues) { Assembly assembly = type.GetGenericTypeDefinition().Assembly; Type? type2 = assembly.GetType(typeof(List<>).FullName); Type type3 = type.GetGenericArguments()[0]; Type type4 = type2.MakeGenericType(type3); object obj = Activator.CreateInstance(assembly.GetType(type4.FullName)); MethodInfo method = obj.GetType().GetMethod("Add"); unassignedValues = new Dictionary<object, Dictionary<string, object>>(); foreach (object item in enumerable) { Dictionary<string, object> unassigned; object obj2 = ConvertInstruction(type3, item, out unassigned); unassignedValues.Add(obj2, unassigned); method.Invoke(obj, new object[1] { obj2 }); } return obj as IEnumerable; } private static IEnumerable ConvertToOurInstructions(IEnumerable instructions, Type codeInstructionType, List<object> originalInstructions, Dictionary<object, Dictionary<string, object>> unassignedValues) { List<object> newInstructions = instructions.Cast<object>().ToList(); int index = -1; foreach (object item in newInstructions) { index++; object obj = AccessTools.MakeDeepCopy(item, codeInstructionType, (Func<string, Traverse, Traverse, object>)null, ""); if (unassignedValues.TryGetValue(item, out var value)) { bool addExceptionInfo = ShouldAddExceptionInfo(item, index, originalInstructions, newInstructions, unassignedValues); Traverse val = Traverse.Create(obj); foreach (KeyValuePair<string, object> item2 in value.Where((KeyValuePair<string, object> field) => addExceptionInfo || field.Key != "blocks")) { val.Field(item2.Key).SetValue(item2.Value); } } yield return obj; } } private static bool IsCodeInstructionsParameter(Type type) { if (type.IsGenericType) { return type.GetGenericTypeDefinition().Name.StartsWith("IEnumerable", StringComparison.Ordinal); } return false; } private static IEnumerable ConvertToGeneralInstructions(MethodInfo transpiler, IEnumerable enumerable, out Dictionary<object, Dictionary<string, object>> unassignedValues) { Type type = (from p in transpiler.GetParameters() select p.ParameterType).FirstOrDefault((Type t) => IsCodeInstructionsParameter(t)); if ((object)type == null) { unassignedValues = new Dictionary<object, Dictionary<string, object>>(); return enumerable; } if ((object)type != typeof(IEnumerable<CodeInstruction>)) { return ConvertInstructionsAndUnassignedValues(type, enumerable, out unassignedValues); } unassignedValues = null; return (enumerable as IList<CodeInstruction>) ?? ((enumerable as IEnumerable<CodeInstruction>) ?? enumerable.Cast<CodeInstruction>()).ToList(); } private static List<object> GetTranspilerCallParameters(ILGenerator generator, MethodInfo transpiler, MethodBase method, IEnumerable instructions) { List<object> parameter = new List<object>(); CollectionExtensions.Do<Type>(from param in transpiler.GetParameters() select param.ParameterType, (Action<Type>)delegate(Type type) { if (type.IsAssignableFrom(typeof(ILGenerator))) { parameter.Add(generator); } else if (type.IsAssignableFrom(typeof(MethodBase))) { parameter.Add(method); } else if (IsCodeInstructionsParameter(type)) { parameter.Add(instructions); } }); return parameter; } }
BepInEx/core/Mono.Cecil.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security.Cryptography; using System.Text; using System.Threading; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; using Mono.Cecil.PE; using Mono.Collections.Generic; using Mono.Security.Cryptography; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyProduct("Mono.Cecil")] [assembly: AssemblyCopyright("Copyright © 2008 - 2018 Jb Evain")] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("0.10.4.0")] [assembly: AssemblyInformationalVersion("0.10.4.0")] [assembly: AssemblyTitle("Mono.Cecil")] [assembly: Guid("fd225bb4-fa53-44b2-a6db-85f5e48dcb54")] [assembly: InternalsVisibleTo("Mono.Cecil.Pdb, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b5c9f7f04346c324a3176f8d3ee823bbf2d60efdbc35f86fd9e65ea3e6cd11bcdcba3a353e55133c8ac5c4caaba581b2c6dfff2cc2d0edc43959ddb86b973300a479a82419ef489c3225f1fe429a708507bd515835160e10bc743d20ca33ab9570cfd68d479fcf0bc797a763bec5d1000f0159ef619e709d915975e87beebaf")] [assembly: InternalsVisibleTo("Mono.Cecil.Mdb, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b5c9f7f04346c324a3176f8d3ee823bbf2d60efdbc35f86fd9e65ea3e6cd11bcdcba3a353e55133c8ac5c4caaba581b2c6dfff2cc2d0edc43959ddb86b973300a479a82419ef489c3225f1fe429a708507bd515835160e10bc743d20ca33ab9570cfd68d479fcf0bc797a763bec5d1000f0159ef619e709d915975e87beebaf")] [assembly: InternalsVisibleTo("Mono.Cecil.Rocks, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b5c9f7f04346c324a3176f8d3ee823bbf2d60efdbc35f86fd9e65ea3e6cd11bcdcba3a353e55133c8ac5c4caaba581b2c6dfff2cc2d0edc43959ddb86b973300a479a82419ef489c3225f1fe429a708507bd515835160e10bc743d20ca33ab9570cfd68d479fcf0bc797a763bec5d1000f0159ef619e709d915975e87beebaf")] [assembly: InternalsVisibleTo("Mono.Cecil.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b5c9f7f04346c324a3176f8d3ee823bbf2d60efdbc35f86fd9e65ea3e6cd11bcdcba3a353e55133c8ac5c4caaba581b2c6dfff2cc2d0edc43959ddb86b973300a479a82419ef489c3225f1fe429a708507bd515835160e10bc743d20ca33ab9570cfd68d479fcf0bc797a763bec5d1000f0159ef619e709d915975e87beebaf")] [assembly: AssemblyVersion("0.10.4.0")] internal static class Consts { public const string AssemblyName = "Mono.Cecil"; public const string PublicKey = "00240000048000009400000006020000002400005253413100040000010001002b5c9f7f04346c324a3176f8d3ee823bbf2d60efdbc35f86fd9e65ea3e6cd11bcdcba3a353e55133c8ac5c4caaba581b2c6dfff2cc2d0edc43959ddb86b973300a479a82419ef489c3225f1fe429a708507bd515835160e10bc743d20ca33ab9570cfd68d479fcf0bc797a763bec5d1000f0159ef619e709d915975e87beebaf"; } namespace Mono { internal static class Disposable { public static Disposable<T> Owned<T>(T value) where T : class, IDisposable { return new Disposable<T>(value, owned: true); } public static Disposable<T> NotOwned<T>(T value) where T : class, IDisposable { return new Disposable<T>(value, owned: false); } } internal struct Disposable<T> : IDisposable where T : class, IDisposable { internal readonly T value; private readonly bool owned; public Disposable(T value, bool owned) { this.value = value; this.owned = owned; } public void Dispose() { if (value != null && owned) { value.Dispose(); } } } internal static class Empty<T> { public static readonly T[] Array = new T[0]; } internal class ArgumentNullOrEmptyException : ArgumentException { public ArgumentNullOrEmptyException(string paramName) : base("Argument null or empty", paramName) { } } internal class MergeSort<T> { private readonly T[] elements; private readonly T[] buffer; private readonly IComparer<T> comparer; private MergeSort(T[] elements, IComparer<T> comparer) { this.elements = elements; buffer = new T[elements.Length]; Array.Copy(this.elements, buffer, elements.Length); this.comparer = comparer; } public static void Sort(T[] source, IComparer<T> comparer) { Sort(source, 0, source.Length, comparer); } public static void Sort(T[] source, int start, int length, IComparer<T> comparer) { new MergeSort<T>(source, comparer).Sort(start, length); } private void Sort(int start, int length) { TopDownSplitMerge(buffer, elements, start, length); } private void TopDownSplitMerge(T[] a, T[] b, int start, int end) { if (end - start >= 2) { int num = (end + start) / 2; TopDownSplitMerge(b, a, start, num); TopDownSplitMerge(b, a, num, end); TopDownMerge(a, b, start, num, end); } } private void TopDownMerge(T[] a, T[] b, int start, int middle, int end) { int num = start; int num2 = middle; for (int i = start; i < end; i++) { if (num < middle && (num2 >= end || comparer.Compare(a[num], a[num2]) <= 0)) { b[i] = a[num++]; } else { b[i] = a[num2++]; } } } } internal static class TypeExtensions { public static TypeCode GetTypeCode(this Type type) { return Type.GetTypeCode(type); } public static Assembly Assembly(this Type type) { return type.Assembly; } public static MethodBase DeclaringMethod(this Type type) { return type.DeclaringMethod; } public static Type[] GetGenericArguments(this Type type) { return type.GetGenericArguments(); } public static bool IsGenericType(this Type type) { return type.IsGenericType; } public static bool IsGenericTypeDefinition(this Type type) { return type.IsGenericTypeDefinition; } public static bool IsValueType(this Type type) { return type.IsValueType; } } } namespace Mono.Security.Cryptography { internal static class CryptoConvert { private static int ToInt32LE(byte[] bytes, int offset) { return (bytes[offset + 3] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 1] << 8) | bytes[offset]; } private static uint ToUInt32LE(byte[] bytes, int offset) { return (uint)((bytes[offset + 3] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 1] << 8) | bytes[offset]); } private static byte[] Trim(byte[] array) { for (int i = 0; i < array.Length; i++) { if (array[i] != 0) { byte[] array2 = new byte[array.Length - i]; Buffer.BlockCopy(array, i, array2, 0, array2.Length); return array2; } } return null; } private static RSA FromCapiPrivateKeyBlob(byte[] blob, int offset) { RSAParameters parameters = default(RSAParameters); try { if (blob[offset] != 7 || blob[offset + 1] != 2 || blob[offset + 2] != 0 || blob[offset + 3] != 0 || ToUInt32LE(blob, offset + 8) != 843141970) { throw new CryptographicException("Invalid blob header"); } int num = ToInt32LE(blob, offset + 12); byte[] array = new byte[4]; Buffer.BlockCopy(blob, offset + 16, array, 0, 4); Array.Reverse((Array)array); parameters.Exponent = Trim(array); int num2 = offset + 20; int num3 = num >> 3; parameters.Modulus = new byte[num3]; Buffer.BlockCopy(blob, num2, parameters.Modulus, 0, num3); Array.Reverse((Array)parameters.Modulus); num2 += num3; int num4 = num3 >> 1; parameters.P = new byte[num4]; Buffer.BlockCopy(blob, num2, parameters.P, 0, num4); Array.Reverse((Array)parameters.P); num2 += num4; parameters.Q = new byte[num4]; Buffer.BlockCopy(blob, num2, parameters.Q, 0, num4); Array.Reverse((Array)parameters.Q); num2 += num4; parameters.DP = new byte[num4]; Buffer.BlockCopy(blob, num2, parameters.DP, 0, num4); Array.Reverse((Array)parameters.DP); num2 += num4; parameters.DQ = new byte[num4]; Buffer.BlockCopy(blob, num2, parameters.DQ, 0, num4); Array.Reverse((Array)parameters.DQ); num2 += num4; parameters.InverseQ = new byte[num4]; Buffer.BlockCopy(blob, num2, parameters.InverseQ, 0, num4); Array.Reverse((Array)parameters.InverseQ); num2 += num4; parameters.D = new byte[num3]; if (num2 + num3 + offset <= blob.Length) { Buffer.BlockCopy(blob, num2, parameters.D, 0, num3); Array.Reverse((Array)parameters.D); } } catch (Exception inner) { throw new CryptographicException("Invalid blob.", inner); } RSA rSA = null; try { rSA = RSA.Create(); rSA.ImportParameters(parameters); } catch (CryptographicException) { bool flag = false; try { rSA = new RSACryptoServiceProvider(new CspParameters { Flags = CspProviderFlags.UseMachineKeyStore }); rSA.ImportParameters(parameters); } catch { flag = true; } if (flag) { throw; } } return rSA; } private static RSA FromCapiPublicKeyBlob(byte[] blob, int offset) { try { if (blob[offset] != 6 || blob[offset + 1] != 2 || blob[offset + 2] != 0 || blob[offset + 3] != 0 || ToUInt32LE(blob, offset + 8) != 826364754) { throw new CryptographicException("Invalid blob header"); } int num = ToInt32LE(blob, offset + 12); RSAParameters parameters = new RSAParameters { Exponent = new byte[3] }; parameters.Exponent[0] = blob[offset + 18]; parameters.Exponent[1] = blob[offset + 17]; parameters.Exponent[2] = blob[offset + 16]; int srcOffset = offset + 20; int num2 = num >> 3; parameters.Modulus = new byte[num2]; Buffer.BlockCopy(blob, srcOffset, parameters.Modulus, 0, num2); Array.Reverse((Array)parameters.Modulus); RSA rSA = null; try { rSA = RSA.Create(); rSA.ImportParameters(parameters); } catch (CryptographicException) { rSA = new RSACryptoServiceProvider(new CspParameters { Flags = CspProviderFlags.UseMachineKeyStore }); rSA.ImportParameters(parameters); } return rSA; } catch (Exception inner) { throw new CryptographicException("Invalid blob.", inner); } } public static RSA FromCapiKeyBlob(byte[] blob) { return FromCapiKeyBlob(blob, 0); } public static RSA FromCapiKeyBlob(byte[] blob, int offset) { if (blob == null) { throw new ArgumentNullException("blob"); } if (offset >= blob.Length) { throw new ArgumentException("blob is too small."); } switch (blob[offset]) { case 0: if (blob[offset + 12] == 6) { return FromCapiPublicKeyBlob(blob, offset + 12); } break; case 6: return FromCapiPublicKeyBlob(blob, offset); case 7: return FromCapiPrivateKeyBlob(blob, offset); } throw new CryptographicException("Unknown blob format."); } } } namespace Mono.Collections.Generic { public class Collection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IList, ICollection { public struct Enumerator : IEnumerator<T>, IDisposable, IEnumerator { private Collection<T> collection; private T current; private int next; private readonly int version; public T Current => current; object IEnumerator.Current { get { CheckState(); if (next <= 0) { throw new InvalidOperationException(); } return current; } } internal Enumerator(Collection<T> collection) { this = default(Enumerator); this.collection = collection; version = collection.version; } public bool MoveNext() { CheckState(); if (next < 0) { return false; } if (next < collection.size) { current = collection.items[next++]; return true; } next = -1; return false; } public void Reset() { CheckState(); next = 0; } private void CheckState() { if (collection == null) { throw new ObjectDisposedException(GetType().FullName); } if (version != collection.version) { throw new InvalidOperationException(); } } public void Dispose() { collection = null; } } internal T[] items; internal int size; private int version; public int Count => size; public T this[int index] { get { if (index >= size) { throw new ArgumentOutOfRangeException(); } return items[index]; } set { CheckIndex(index); if (index == size) { throw new ArgumentOutOfRangeException(); } OnSet(value, index); items[index] = value; } } public int Capacity { get { return items.Length; } set { if (value < 0 || value < size) { throw new ArgumentOutOfRangeException(); } Resize(value); } } bool ICollection<T>.IsReadOnly => false; bool IList.IsFixedSize => false; bool IList.IsReadOnly => false; object IList.this[int index] { get { return this[index]; } set { CheckIndex(index); try { this[index] = (T)value; return; } catch (InvalidCastException) { } catch (NullReferenceException) { } throw new ArgumentException(); } } int ICollection.Count => Count; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; public Collection() { items = Empty<T>.Array; } public Collection(int capacity) { if (capacity < 0) { throw new ArgumentOutOfRangeException(); } items = new T[capacity]; } public Collection(ICollection<T> items) { if (items == null) { throw new ArgumentNullException("items"); } this.items = new T[items.Count]; items.CopyTo(this.items, 0); size = this.items.Length; } public void Add(T item) { if (size == items.Length) { Grow(1); } OnAdd(item, size); items[size++] = item; version++; } public bool Contains(T item) { return IndexOf(item) != -1; } public int IndexOf(T item) { return Array.IndexOf(items, item, 0, size); } public void Insert(int index, T item) { CheckIndex(index); if (size == items.Length) { Grow(1); } OnInsert(item, index); Shift(index, 1); items[index] = item; version++; } public void RemoveAt(int index) { if (index < 0 || index >= size) { throw new ArgumentOutOfRangeException(); } T item = items[index]; OnRemove(item, index); Shift(index, -1); version++; } public bool Remove(T item) { int num = IndexOf(item); if (num == -1) { return false; } OnRemove(item, num); Shift(num, -1); version++; return true; } public void Clear() { OnClear(); Array.Clear(items, 0, size); size = 0; version++; } public void CopyTo(T[] array, int arrayIndex) { Array.Copy(items, 0, array, arrayIndex, size); } public T[] ToArray() { T[] array = new T[size]; Array.Copy(items, 0, array, 0, size); return array; } private void CheckIndex(int index) { if (index < 0 || index > size) { throw new ArgumentOutOfRangeException(); } } private void Shift(int start, int delta) { if (delta < 0) { start -= delta; } if (start < size) { Array.Copy(items, start, items, start + delta, size - start); } size += delta; if (delta < 0) { Array.Clear(items, size, -delta); } } protected virtual void OnAdd(T item, int index) { } protected virtual void OnInsert(T item, int index) { } protected virtual void OnSet(T item, int index) { } protected virtual void OnRemove(T item, int index) { } protected virtual void OnClear() { } internal virtual void Grow(int desired) { int num = size + desired; if (num > items.Length) { num = Math.Max(Math.Max(items.Length * 2, 4), num); Resize(num); } } protected void Resize(int new_size) { if (new_size != size) { if (new_size < size) { throw new ArgumentOutOfRangeException(); } items = items.Resize(new_size); } } int IList.Add(object value) { try { Add((T)value); return size - 1; } catch (InvalidCastException) { } catch (NullReferenceException) { } throw new ArgumentException(); } void IList.Clear() { Clear(); } bool IList.Contains(object value) { return ((IList)this).IndexOf(value) > -1; } int IList.IndexOf(object value) { try { return IndexOf((T)value); } catch (InvalidCastException) { } catch (NullReferenceException) { } return -1; } void IList.Insert(int index, object value) { CheckIndex(index); try { Insert(index, (T)value); return; } catch (InvalidCastException) { } catch (NullReferenceException) { } throw new ArgumentException(); } void IList.Remove(object value) { try { Remove((T)value); } catch (InvalidCastException) { } catch (NullReferenceException) { } } void IList.RemoveAt(int index) { RemoveAt(index); } void ICollection.CopyTo(Array array, int index) { Array.Copy(items, 0, array, index, size); } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(this); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(this); } } public sealed class ReadOnlyCollection<T> : Collection<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IList, ICollection { private static ReadOnlyCollection<T> empty; public static ReadOnlyCollection<T> Empty => empty ?? (empty = new ReadOnlyCollection<T>()); bool ICollection<T>.IsReadOnly => true; bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; private ReadOnlyCollection() { } public ReadOnlyCollection(T[] array) { if (array == null) { throw new ArgumentNullException(); } Initialize(array, array.Length); } public ReadOnlyCollection(Collection<T> collection) { if (collection == null) { throw new ArgumentNullException(); } Initialize(collection.items, collection.size); } private void Initialize(T[] items, int size) { base.items = new T[size]; Array.Copy(items, 0, base.items, 0, size); base.size = size; } internal override void Grow(int desired) { throw new InvalidOperationException(); } protected override void OnAdd(T item, int index) { throw new InvalidOperationException(); } protected override void OnClear() { throw new InvalidOperationException(); } protected override void OnInsert(T item, int index) { throw new InvalidOperationException(); } protected override void OnRemove(T item, int index) { throw new InvalidOperationException(); } protected override void OnSet(T item, int index) { throw new InvalidOperationException(); } } } namespace Mono.Cecil { internal static class Mixin { public enum Argument { name, fileName, fullName, stream, type, method, field, parameters, module, modifierType, eventType, fieldType, declaringType, returnType, propertyType, interfaceType } public static Version ZeroVersion = new Version(0, 0, 0, 0); public const int NotResolvedMarker = -2; public const int NoDataMarker = -1; internal static object NoValue = new object(); internal static object NotResolved = new object(); public const string mscorlib = "mscorlib"; public const string system_runtime = "System.Runtime"; public const string system_private_corelib = "System.Private.CoreLib"; public const string netstandard = "netstandard"; public const int TableCount = 58; public const int CodedIndexCount = 14; public static bool IsNullOrEmpty<T>(this T[] self) { if (self != null) { return self.Length == 0; } return true; } public static bool IsNullOrEmpty<T>(this Collection<T> self) { if (self != null) { return self.size == 0; } return true; } public static T[] Resize<T>(this T[] self, int length) { Array.Resize(ref self, length); return self; } public static T[] Add<T>(this T[] self, T item) { if (self == null) { self = new T[1] { item }; return self; } self = self.Resize(self.Length + 1); self[^1] = item; return self; } public static Version CheckVersion(Version version) { if (version == null) { return ZeroVersion; } if (version.Build == -1) { return new Version(version.Major, version.Minor, 0, 0); } if (version.Revision == -1) { return new Version(version.Major, version.Minor, version.Build, 0); } return version; } public static bool TryGetUniqueDocument(this MethodDebugInformation info, out Document document) { document = info.SequencePoints[0].Document; for (int i = 1; i < info.SequencePoints.Count; i++) { if (info.SequencePoints[i].Document != document) { return false; } } return true; } public static void ResolveConstant(this IConstantProvider self, ref object constant, ModuleDefinition module) { if (module == null) { constant = NoValue; return; } lock (module.SyncRoot) { if (constant != NotResolved) { return; } if (module.HasImage()) { constant = module.Read(self, (IConstantProvider provider, MetadataReader reader) => reader.ReadConstant(provider)); } else { constant = NoValue; } } } public static bool GetHasCustomAttributes(this ICustomAttributeProvider self, ModuleDefinition module) { if (module.HasImage()) { return module.Read(self, (ICustomAttributeProvider provider, MetadataReader reader) => reader.HasCustomAttributes(provider)); } return false; } public static Collection<CustomAttribute> GetCustomAttributes(this ICustomAttributeProvider self, ref Collection<CustomAttribute> variable, ModuleDefinition module) { if (!module.HasImage()) { return variable = new Collection<CustomAttribute>(); } return module.Read(ref variable, self, (ICustomAttributeProvider provider, MetadataReader reader) => reader.ReadCustomAttributes(provider)); } public static bool ContainsGenericParameter(this IGenericInstance self) { Collection<TypeReference> genericArguments = self.GenericArguments; for (int i = 0; i < genericArguments.Count; i++) { if (genericArguments[i].ContainsGenericParameter) { return true; } } return false; } public static void GenericInstanceFullName(this IGenericInstance self, StringBuilder builder) { builder.Append("<"); Collection<TypeReference> genericArguments = self.GenericArguments; for (int i = 0; i < genericArguments.Count; i++) { if (i > 0) { builder.Append(","); } builder.Append(genericArguments[i].FullName); } builder.Append(">"); } public static bool GetHasGenericParameters(this IGenericParameterProvider self, ModuleDefinition module) { if (module.HasImage()) { return module.Read(self, (IGenericParameterProvider provider, MetadataReader reader) => reader.HasGenericParameters(provider)); } return false; } public static Collection<GenericParameter> GetGenericParameters(this IGenericParameterProvider self, ref Collection<GenericParameter> collection, ModuleDefinition module) { if (!module.HasImage()) { return collection = new GenericParameterCollection(self); } return module.Read(ref collection, self, (IGenericParameterProvider provider, MetadataReader reader) => reader.ReadGenericParameters(provider)); } public static bool GetHasMarshalInfo(this IMarshalInfoProvider self, ModuleDefinition module) { if (module.HasImage()) { return module.Read(self, (IMarshalInfoProvider provider, MetadataReader reader) => reader.HasMarshalInfo(provider)); } return false; } public static MarshalInfo GetMarshalInfo(this IMarshalInfoProvider self, ref MarshalInfo variable, ModuleDefinition module) { if (!module.HasImage()) { return null; } return module.Read(ref variable, self, (IMarshalInfoProvider provider, MetadataReader reader) => reader.ReadMarshalInfo(provider)); } public static bool GetAttributes(this uint self, uint attributes) { return (self & attributes) != 0; } public static uint SetAttributes(this uint self, uint attributes, bool value) { if (value) { return self | attributes; } return self & ~attributes; } public static bool GetMaskedAttributes(this uint self, uint mask, uint attributes) { return (self & mask) == attributes; } public static uint SetMaskedAttributes(this uint self, uint mask, uint attributes, bool value) { if (value) { self &= ~mask; return self | attributes; } return self & ~(mask & attributes); } public static bool GetAttributes(this ushort self, ushort attributes) { return (self & attributes) != 0; } public static ushort SetAttributes(this ushort self, ushort attributes, bool value) { if (value) { return (ushort)(self | attributes); } return (ushort)(self & ~attributes); } public static bool GetMaskedAttributes(this ushort self, ushort mask, uint attributes) { return (self & mask) == attributes; } public static ushort SetMaskedAttributes(this ushort self, ushort mask, uint attributes, bool value) { if (value) { self = (ushort)(self & ~mask); return (ushort)(self | attributes); } return (ushort)(self & ~(mask & attributes)); } public static bool HasImplicitThis(this IMethodSignature self) { if (self.HasThis) { return !self.ExplicitThis; } return false; } public static void MethodSignatureFullName(this IMethodSignature self, StringBuilder builder) { builder.Append("("); if (self.HasParameters) { Collection<ParameterDefinition> parameters = self.Parameters; for (int i = 0; i < parameters.Count; i++) { ParameterDefinition parameterDefinition = parameters[i]; if (i > 0) { builder.Append(","); } if (parameterDefinition.ParameterType.IsSentinel) { builder.Append("...,"); } builder.Append(parameterDefinition.ParameterType.FullName); } } builder.Append(")"); } public static void CheckModule(ModuleDefinition module) { if (module == null) { throw new ArgumentNullException(Argument.module.ToString()); } } public static bool TryGetAssemblyNameReference(this ModuleDefinition module, AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference) { Collection<AssemblyNameReference> assemblyReferences = module.AssemblyReferences; for (int i = 0; i < assemblyReferences.Count; i++) { AssemblyNameReference assemblyNameReference = assemblyReferences[i]; if (Equals(name_reference, assemblyNameReference)) { assembly_reference = assemblyNameReference; return true; } } assembly_reference = null; return false; } private static bool Equals(byte[] a, byte[] b) { if (a == b) { return true; } if (a == null) { return false; } if (a.Length != b.Length) { return false; } for (int i = 0; i < a.Length; i++) { if (a[i] != b[i]) { return false; } } return true; } private static bool Equals<T>(T a, T b) where T : class, IEquatable<T> { if (a == b) { return true; } return a?.Equals(b) ?? false; } private static bool Equals(AssemblyNameReference a, AssemblyNameReference b) { if (a == b) { return true; } if (a.Name != b.Name) { return false; } if (!Equals(a.Version, b.Version)) { return false; } if (a.Culture != b.Culture) { return false; } if (!Equals(a.PublicKeyToken, b.PublicKeyToken)) { return false; } return true; } public static ParameterDefinition GetParameter(this Mono.Cecil.Cil.MethodBody self, int index) { MethodDefinition method = self.method; if (method.HasThis) { if (index == 0) { return self.ThisParameter; } index--; } Collection<ParameterDefinition> parameters = method.Parameters; if (index < 0 || index >= parameters.size) { return null; } return parameters[index]; } public static VariableDefinition GetVariable(this Mono.Cecil.Cil.MethodBody self, int index) { Collection<VariableDefinition> variables = self.Variables; if (index < 0 || index >= variables.size) { return null; } return variables[index]; } public static bool GetSemantics(this MethodDefinition self, MethodSemanticsAttributes semantics) { return (self.SemanticsAttributes & semantics) != 0; } public static void SetSemantics(this MethodDefinition self, MethodSemanticsAttributes semantics, bool value) { if (value) { self.SemanticsAttributes |= semantics; } else { self.SemanticsAttributes &= (MethodSemanticsAttributes)(ushort)(~(int)semantics); } } public static bool IsVarArg(this IMethodSignature self) { return self.CallingConvention == MethodCallingConvention.VarArg; } public static int GetSentinelPosition(this IMethodSignature self) { if (!self.HasParameters) { return -1; } Collection<ParameterDefinition> parameters = self.Parameters; for (int i = 0; i < parameters.Count; i++) { if (parameters[i].ParameterType.IsSentinel) { return i; } } return -1; } public static void CheckName(object name) { if (name == null) { throw new ArgumentNullException(Argument.name.ToString()); } } public static void CheckName(string name) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullOrEmptyException(Argument.name.ToString()); } } public static void CheckFileName(string fileName) { if (string.IsNullOrEmpty(fileName)) { throw new ArgumentNullOrEmptyException(Argument.fileName.ToString()); } } public static void CheckFullName(string fullName) { if (string.IsNullOrEmpty(fullName)) { throw new ArgumentNullOrEmptyException(Argument.fullName.ToString()); } } public static void CheckStream(object stream) { if (stream == null) { throw new ArgumentNullException(Argument.stream.ToString()); } } public static void CheckWriteSeek(Stream stream) { if (!stream.CanWrite || !stream.CanSeek) { throw new ArgumentException("Stream must be writable and seekable."); } } public static void CheckReadSeek(Stream stream) { if (!stream.CanRead || !stream.CanSeek) { throw new ArgumentException("Stream must be readable and seekable."); } } public static void CheckType(object type) { if (type == null) { throw new ArgumentNullException(Argument.type.ToString()); } } public static void CheckType(object type, Argument argument) { if (type == null) { throw new ArgumentNullException(argument.ToString()); } } public static void CheckField(object field) { if (field == null) { throw new ArgumentNullException(Argument.field.ToString()); } } public static void CheckMethod(object method) { if (method == null) { throw new ArgumentNullException(Argument.method.ToString()); } } public static void CheckParameters(object parameters) { if (parameters == null) { throw new ArgumentNullException(Argument.parameters.ToString()); } } public static uint GetTimestamp() { return (uint)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; } public static bool HasImage(this ModuleDefinition self) { return self?.HasImage ?? false; } public static string GetFileName(this Stream self) { if (!(self is FileStream fileStream)) { return string.Empty; } return Path.GetFullPath(fileStream.Name); } public static void CopyTo(this Stream self, Stream target) { byte[] array = new byte[8192]; int count; while ((count = self.Read(array, 0, array.Length)) > 0) { target.Write(array, 0, count); } } public static TargetRuntime ParseRuntime(this string self) { if (string.IsNullOrEmpty(self)) { return TargetRuntime.Net_4_0; } switch (self[1]) { case '1': if (self[3] != '0') { return TargetRuntime.Net_1_1; } return TargetRuntime.Net_1_0; case '2': return TargetRuntime.Net_2_0; default: return TargetRuntime.Net_4_0; } } public static string RuntimeVersionString(this TargetRuntime runtime) { return runtime switch { TargetRuntime.Net_1_0 => "v1.0.3705", TargetRuntime.Net_1_1 => "v1.1.4322", TargetRuntime.Net_2_0 => "v2.0.50727", _ => "v4.0.30319", }; } public static bool IsWindowsMetadata(this ModuleDefinition module) { return module.MetadataKind != MetadataKind.Ecma335; } public static byte[] ReadAll(this Stream self) { MemoryStream memoryStream = new MemoryStream((int)self.Length); byte[] array = new byte[1024]; int count; while ((count = self.Read(array, 0, array.Length)) != 0) { memoryStream.Write(array, 0, count); } return memoryStream.ToArray(); } public static void Read(object o) { } public static bool GetHasSecurityDeclarations(this ISecurityDeclarationProvider self, ModuleDefinition module) { if (module.HasImage()) { return module.Read(self, (ISecurityDeclarationProvider provider, MetadataReader reader) => reader.HasSecurityDeclarations(provider)); } return false; } public static Collection<SecurityDeclaration> GetSecurityDeclarations(this ISecurityDeclarationProvider self, ref Collection<SecurityDeclaration> variable, ModuleDefinition module) { if (!module.HasImage()) { return variable = new Collection<SecurityDeclaration>(); } return module.Read(ref variable, self, (ISecurityDeclarationProvider provider, MetadataReader reader) => reader.ReadSecurityDeclarations(provider)); } public static TypeReference GetEnumUnderlyingType(this TypeDefinition self) { Collection<FieldDefinition> fields = self.Fields; for (int i = 0; i < fields.Count; i++) { FieldDefinition fieldDefinition = fields[i]; if (!fieldDefinition.IsStatic) { return fieldDefinition.FieldType; } } throw new ArgumentException(); } public static TypeDefinition GetNestedType(this TypeDefinition self, string fullname) { if (!self.HasNestedTypes) { return null; } Collection<TypeDefinition> nestedTypes = self.NestedTypes; for (int i = 0; i < nestedTypes.Count; i++) { TypeDefinition typeDefinition = nestedTypes[i]; if (typeDefinition.TypeFullName() == fullname) { return typeDefinition; } } return null; } public static bool IsPrimitive(this ElementType self) { switch (self) { case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.I: case ElementType.U: return true; default: return false; } } public static string TypeFullName(this TypeReference self) { if (!string.IsNullOrEmpty(self.Namespace)) { return self.Namespace + "." + self.Name; } return self.Name; } public static bool IsTypeOf(this TypeReference self, string @namespace, string name) { if (self.Name == name) { return self.Namespace == @namespace; } return false; } public static bool IsTypeSpecification(this TypeReference type) { switch (type.etype) { case ElementType.Ptr: case ElementType.ByRef: case ElementType.Var: case ElementType.Array: case ElementType.GenericInst: case ElementType.FnPtr: case ElementType.SzArray: case ElementType.MVar: case ElementType.CModReqD: case ElementType.CModOpt: case ElementType.Sentinel: case ElementType.Pinned: return true; default: return false; } } public static TypeDefinition CheckedResolve(this TypeReference self) { return self.Resolve() ?? throw new ResolutionException(self); } public static bool TryGetCoreLibraryReference(this ModuleDefinition module, out AssemblyNameReference reference) { Collection<AssemblyNameReference> assemblyReferences = module.AssemblyReferences; for (int i = 0; i < assemblyReferences.Count; i++) { reference = assemblyReferences[i]; if (IsCoreLibrary(reference)) { return true; } } reference = null; return false; } public static bool IsCoreLibrary(this ModuleDefinition module) { if (module.Assembly == null) { return false; } if (!IsCoreLibrary(module.Assembly.Name)) { return false; } if (module.HasImage && module.Read(module, (ModuleDefinition m, MetadataReader reader) => reader.image.GetTableLength(Table.AssemblyRef) > 0)) { return false; } return true; } public static void KnownValueType(this TypeReference type) { if (!type.IsDefinition) { type.IsValueType = true; } } private static bool IsCoreLibrary(AssemblyNameReference reference) { string name = reference.Name; switch (name) { default: return name == "netstandard"; case "mscorlib": case "System.Runtime": case "System.Private.CoreLib": return true; } } public static ImageDebugHeaderEntry GetCodeViewEntry(this ImageDebugHeader header) { return header.GetEntry(ImageDebugType.CodeView); } public static ImageDebugHeaderEntry GetDeterministicEntry(this ImageDebugHeader header) { return header.GetEntry(ImageDebugType.Deterministic); } public static ImageDebugHeader AddDeterministicEntry(this ImageDebugHeader header) { ImageDebugDirectory directory = default(ImageDebugDirectory); directory.Type = ImageDebugType.Deterministic; ImageDebugHeaderEntry imageDebugHeaderEntry = new ImageDebugHeaderEntry(directory, Empty<byte>.Array); if (header == null) { return new ImageDebugHeader(imageDebugHeaderEntry); } ImageDebugHeaderEntry[] array = new ImageDebugHeaderEntry[header.Entries.Length + 1]; Array.Copy(header.Entries, array, header.Entries.Length); array[^1] = imageDebugHeaderEntry; return new ImageDebugHeader(array); } public static ImageDebugHeaderEntry GetEmbeddedPortablePdbEntry(this ImageDebugHeader header) { return header.GetEntry(ImageDebugType.EmbeddedPortablePdb); } private static ImageDebugHeaderEntry GetEntry(this ImageDebugHeader header, ImageDebugType type) { if (!header.HasEntries) { return null; } for (int i = 0; i < header.Entries.Length; i++) { ImageDebugHeaderEntry imageDebugHeaderEntry = header.Entries[i]; if (imageDebugHeaderEntry.Directory.Type == type) { return imageDebugHeaderEntry; } } return null; } public static string GetPdbFileName(string assemblyFileName) { return Path.ChangeExtension(assemblyFileName, ".pdb"); } public static string GetMdbFileName(string assemblyFileName) { return assemblyFileName + ".mdb"; } public static bool IsPortablePdb(string fileName) { using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); return IsPortablePdb(stream); } public static bool IsPortablePdb(Stream stream) { if (stream.Length < 4) { return false; } long position = stream.Position; try { return new BinaryReader(stream).ReadUInt32() == 1112167234; } finally { stream.Position = position; } } public static uint ReadCompressedUInt32(this byte[] data, ref int position) { uint result; if ((data[position] & 0x80) == 0) { result = data[position]; position++; } else if ((data[position] & 0x40) == 0) { result = (uint)((data[position] & -129) << 8); result |= data[position + 1]; position += 2; } else { result = (uint)((data[position] & -193) << 24); result |= (uint)(data[position + 1] << 16); result |= (uint)(data[position + 2] << 8); result |= data[position + 3]; position += 4; } return result; } public static MetadataToken GetMetadataToken(this CodedIndex self, uint data) { uint rid; TokenType type; switch (self) { case CodedIndex.TypeDefOrRef: rid = data >> 2; switch (data & 3) { case 0u: break; case 1u: goto IL_006d; case 2u: goto IL_0078; default: goto end_IL_0001; } type = TokenType.TypeDef; goto IL_05b3; case CodedIndex.HasConstant: rid = data >> 2; switch (data & 3) { case 0u: break; case 1u: goto IL_00ad; case 2u: goto IL_00b8; default: goto end_IL_0001; } type = TokenType.Field; goto IL_05b3; case CodedIndex.HasCustomAttribute: rid = data >> 5; switch (data & 0x1F) { case 0u: break; case 1u: goto IL_013a; case 2u: goto IL_0145; case 3u: goto IL_0150; case 4u: goto IL_015b; case 5u: goto IL_0166; case 6u: goto IL_0171; case 7u: goto IL_017c; case 8u: goto IL_0183; case 9u: goto IL_018e; case 10u: goto IL_0199; case 11u: goto IL_01a4; case 12u: goto IL_01af; case 13u: goto IL_01ba; case 14u: goto IL_01c5; case 15u: goto IL_01d0; case 16u: goto IL_01db; case 17u: goto IL_01e6; case 18u: goto IL_01f1; case 19u: goto IL_01fc; case 20u: goto IL_0207; case 21u: goto IL_0212; default: goto end_IL_0001; } type = TokenType.Method; goto IL_05b3; case CodedIndex.HasFieldMarshal: { rid = data >> 1; uint num = data & 1u; if (num != 0) { if (num != 1) { break; } type = TokenType.Param; } else { type = TokenType.Field; } goto IL_05b3; } case CodedIndex.HasDeclSecurity: rid = data >> 2; switch (data & 3) { case 0u: break; case 1u: goto IL_0271; case 2u: goto IL_027c; default: goto end_IL_0001; } type = TokenType.TypeDef; goto IL_05b3; case CodedIndex.MemberRefParent: rid = data >> 3; switch (data & 7) { case 0u: break; case 1u: goto IL_02b9; case 2u: goto IL_02c4; case 3u: goto IL_02cf; case 4u: goto IL_02da; default: goto end_IL_0001; } type = TokenType.TypeDef; goto IL_05b3; case CodedIndex.HasSemantics: { rid = data >> 1; uint num = data & 1u; if (num != 0) { if (num != 1) { break; } type = TokenType.Property; } else { type = TokenType.Event; } goto IL_05b3; } case CodedIndex.MethodDefOrRef: { rid = data >> 1; uint num = data & 1u; if (num != 0) { if (num != 1) { break; } type = TokenType.MemberRef; } else { type = TokenType.Method; } goto IL_05b3; } case CodedIndex.MemberForwarded: { rid = data >> 1; uint num = data & 1u; if (num != 0) { if (num != 1) { break; } type = TokenType.Method; } else { type = TokenType.Field; } goto IL_05b3; } case CodedIndex.Implementation: rid = data >> 2; switch (data & 3) { case 0u: break; case 1u: goto IL_038d; case 2u: goto IL_0398; default: goto end_IL_0001; } type = TokenType.File; goto IL_05b3; case CodedIndex.CustomAttributeType: { rid = data >> 3; uint num = data & 7u; if (num != 2) { if (num != 3) { break; } type = TokenType.MemberRef; } else { type = TokenType.Method; } goto IL_05b3; } case CodedIndex.ResolutionScope: rid = data >> 2; switch (data & 3) { case 0u: break; case 1u: goto IL_03f8; case 2u: goto IL_0403; case 3u: goto IL_040e; default: goto end_IL_0001; } type = TokenType.Module; goto IL_05b3; case CodedIndex.TypeOrMethodDef: { rid = data >> 1; uint num = data & 1u; if (num != 0) { if (num != 1) { break; } type = TokenType.Method; } else { type = TokenType.TypeDef; } goto IL_05b3; } case CodedIndex.HasCustomDebugInformation: { rid = data >> 5; switch (data & 0x1F) { case 0u: break; case 1u: goto IL_04ce; case 2u: goto IL_04d9; case 3u: goto IL_04e4; case 4u: goto IL_04ef; case 5u: goto IL_04fa; case 6u: goto IL_0505; case 7u: goto IL_0510; case 8u: goto IL_0517; case 9u: goto IL_0522; case 10u: goto IL_052d; case 11u: goto IL_0535; case 12u: goto IL_053d; case 13u: goto IL_0545; case 14u: goto IL_054d; case 15u: goto IL_0555; case 16u: goto IL_055d; case 17u: goto IL_0565; case 18u: goto IL_056d; case 19u: goto IL_0575; case 20u: goto IL_057d; case 21u: goto IL_0585; case 22u: goto IL_058d; case 23u: goto IL_0595; case 24u: goto IL_059d; case 25u: goto IL_05a5; case 26u: goto IL_05ad; default: goto end_IL_0001; } type = TokenType.Method; goto IL_05b3; } IL_05ad: type = TokenType.ImportScope; goto IL_05b3; IL_05a5: type = TokenType.LocalConstant; goto IL_05b3; IL_059d: type = TokenType.LocalVariable; goto IL_05b3; IL_0595: type = TokenType.LocalScope; goto IL_05b3; IL_058d: type = TokenType.Document; goto IL_05b3; IL_0585: type = TokenType.MethodSpec; goto IL_05b3; IL_057d: type = TokenType.GenericParamConstraint; goto IL_05b3; IL_0575: type = TokenType.GenericParam; goto IL_05b3; IL_056d: type = TokenType.ManifestResource; goto IL_05b3; IL_0565: type = TokenType.ExportedType; goto IL_05b3; IL_055d: type = TokenType.File; goto IL_05b3; IL_0555: type = TokenType.AssemblyRef; goto IL_05b3; IL_054d: type = TokenType.Assembly; goto IL_05b3; IL_0545: type = TokenType.TypeSpec; goto IL_05b3; IL_053d: type = TokenType.ModuleRef; goto IL_05b3; IL_0535: type = TokenType.Signature; goto IL_05b3; IL_052d: type = TokenType.Event; goto IL_05b3; IL_0522: type = TokenType.Property; goto IL_05b3; IL_0517: type = TokenType.Permission; goto IL_05b3; IL_0510: type = TokenType.Module; goto IL_05b3; IL_0505: type = TokenType.MemberRef; goto IL_05b3; IL_04fa: type = TokenType.InterfaceImpl; goto IL_05b3; IL_04ef: type = TokenType.Param; goto IL_05b3; IL_04e4: type = TokenType.TypeDef; goto IL_05b3; IL_04d9: type = TokenType.TypeRef; goto IL_05b3; IL_04ce: type = TokenType.Field; goto IL_05b3; IL_01db: type = TokenType.File; goto IL_05b3; IL_01d0: type = TokenType.AssemblyRef; goto IL_05b3; IL_01ba: type = TokenType.TypeSpec; goto IL_05b3; IL_01c5: type = TokenType.Assembly; goto IL_05b3; IL_040e: type = TokenType.TypeRef; goto IL_05b3; IL_0403: type = TokenType.AssemblyRef; goto IL_05b3; IL_03f8: type = TokenType.ModuleRef; goto IL_05b3; IL_01af: type = TokenType.ModuleRef; goto IL_05b3; IL_01a4: type = TokenType.Signature; goto IL_05b3; IL_018e: type = TokenType.Property; goto IL_05b3; IL_0199: type = TokenType.Event; goto IL_05b3; IL_0398: type = TokenType.ExportedType; goto IL_05b3; IL_038d: type = TokenType.AssemblyRef; goto IL_05b3; IL_0183: type = TokenType.Permission; goto IL_05b3; IL_017c: type = TokenType.Module; goto IL_05b3; IL_0166: type = TokenType.InterfaceImpl; goto IL_05b3; IL_0171: type = TokenType.MemberRef; goto IL_05b3; IL_015b: type = TokenType.Param; goto IL_05b3; IL_0145: type = TokenType.TypeRef; goto IL_05b3; IL_0150: type = TokenType.TypeDef; goto IL_05b3; IL_013a: type = TokenType.Field; goto IL_05b3; IL_006d: type = TokenType.TypeRef; goto IL_05b3; IL_02da: type = TokenType.TypeSpec; goto IL_05b3; IL_02cf: type = TokenType.Method; goto IL_05b3; IL_02c4: type = TokenType.ModuleRef; goto IL_05b3; IL_02b9: type = TokenType.TypeRef; goto IL_05b3; IL_00b8: type = TokenType.Property; goto IL_05b3; IL_027c: type = TokenType.Assembly; goto IL_05b3; IL_0271: type = TokenType.Method; goto IL_05b3; IL_00ad: type = TokenType.Param; goto IL_05b3; IL_05b3: return new MetadataToken(type, rid); IL_0078: type = TokenType.TypeSpec; goto IL_05b3; IL_0212: type = TokenType.MethodSpec; goto IL_05b3; IL_0207: type = TokenType.GenericParamConstraint; goto IL_05b3; IL_01fc: type = TokenType.GenericParam; goto IL_05b3; IL_01f1: type = TokenType.ManifestResource; goto IL_05b3; IL_01e6: type = TokenType.ExportedType; goto IL_05b3; end_IL_0001: break; } return MetadataToken.Zero; } public static uint CompressMetadataToken(this CodedIndex self, MetadataToken token) { uint result = 0u; if (token.RID == 0) { return result; } switch (self) { case CodedIndex.TypeDefOrRef: result = token.RID << 2; switch (token.TokenType) { case TokenType.TypeDef: return result | 0u; case TokenType.TypeRef: return result | 1u; case TokenType.TypeSpec: return result | 2u; } break; case CodedIndex.HasConstant: result = token.RID << 2; switch (token.TokenType) { case TokenType.Field: return result | 0u; case TokenType.Param: return result | 1u; case TokenType.Property: return result | 2u; } break; case CodedIndex.HasCustomAttribute: result = token.RID << 5; switch (token.TokenType) { case TokenType.Method: return result | 0u; case TokenType.Field: return result | 1u; case TokenType.TypeRef: return result | 2u; case TokenType.TypeDef: return result | 3u; case TokenType.Param: return result | 4u; case TokenType.InterfaceImpl: return result | 5u; case TokenType.MemberRef: return result | 6u; case TokenType.Module: return result | 7u; case TokenType.Permission: return result | 8u; case TokenType.Property: return result | 9u; case TokenType.Event: return result | 0xAu; case TokenType.Signature: return result | 0xBu; case TokenType.ModuleRef: return result | 0xCu; case TokenType.TypeSpec: return result | 0xDu; case TokenType.Assembly: return result | 0xEu; case TokenType.AssemblyRef: return result | 0xFu; case TokenType.File: return result | 0x10u; case TokenType.ExportedType: return result | 0x11u; case TokenType.ManifestResource: return result | 0x12u; case TokenType.GenericParam: return result | 0x13u; case TokenType.GenericParamConstraint: return result | 0x14u; case TokenType.MethodSpec: return result | 0x15u; } break; case CodedIndex.HasFieldMarshal: result = token.RID << 1; switch (token.TokenType) { case TokenType.Field: return result | 0u; case TokenType.Param: return result | 1u; } break; case CodedIndex.HasDeclSecurity: result = token.RID << 2; switch (token.TokenType) { case TokenType.TypeDef: return result | 0u; case TokenType.Method: return result | 1u; case TokenType.Assembly: return result | 2u; } break; case CodedIndex.MemberRefParent: result = token.RID << 3; switch (token.TokenType) { case TokenType.TypeDef: return result | 0u; case TokenType.TypeRef: return result | 1u; case TokenType.ModuleRef: return result | 2u; case TokenType.Method: return result | 3u; case TokenType.TypeSpec: return result | 4u; } break; case CodedIndex.HasSemantics: result = token.RID << 1; switch (token.TokenType) { case TokenType.Event: return result | 0u; case TokenType.Property: return result | 1u; } break; case CodedIndex.MethodDefOrRef: result = token.RID << 1; switch (token.TokenType) { case TokenType.Method: return result | 0u; case TokenType.MemberRef: return result | 1u; } break; case CodedIndex.MemberForwarded: result = token.RID << 1; switch (token.TokenType) { case TokenType.Field: return result | 0u; case TokenType.Method: return result | 1u; } break; case CodedIndex.Implementation: result = token.RID << 2; switch (token.TokenType) { case TokenType.File: return result | 0u; case TokenType.AssemblyRef: return result | 1u; case TokenType.ExportedType: return result | 2u; } break; case CodedIndex.CustomAttributeType: result = token.RID << 3; switch (token.TokenType) { case TokenType.Method: return result | 2u; case TokenType.MemberRef: return result | 3u; } break; case CodedIndex.ResolutionScope: result = token.RID << 2; switch (token.TokenType) { case TokenType.Module: return result | 0u; case TokenType.ModuleRef: return result | 1u; case TokenType.AssemblyRef: return result | 2u; case TokenType.TypeRef: return result | 3u; } break; case CodedIndex.TypeOrMethodDef: result = token.RID << 1; switch (token.TokenType) { case TokenType.TypeDef: return result | 0u; case TokenType.Method: return result | 1u; } break; case CodedIndex.HasCustomDebugInformation: result = token.RID << 5; switch (token.TokenType) { case TokenType.Method: return result | 0u; case TokenType.Field: return result | 1u; case TokenType.TypeRef: return result | 2u; case TokenType.TypeDef: return result | 3u; case TokenType.Param: return result | 4u; case TokenType.InterfaceImpl: return result | 5u; case TokenType.MemberRef: return result | 6u; case TokenType.Module: return result | 7u; case TokenType.Permission: return result | 8u; case TokenType.Property: return result | 9u; case TokenType.Event: return result | 0xAu; case TokenType.Signature: return result | 0xBu; case TokenType.ModuleRef: return result | 0xCu; case TokenType.TypeSpec: return result | 0xDu; case TokenType.Assembly: return result | 0xEu; case TokenType.AssemblyRef: return result | 0xFu; case TokenType.File: return result | 0x10u; case TokenType.ExportedType: return result | 0x11u; case TokenType.ManifestResource: return result | 0x12u; case TokenType.GenericParam: return result | 0x13u; case TokenType.GenericParamConstraint: return result | 0x14u; case TokenType.MethodSpec: return result | 0x15u; case TokenType.Document: return result | 0x16u; case TokenType.LocalScope: return result | 0x17u; case TokenType.LocalVariable: return result | 0x18u; case TokenType.LocalConstant: return result | 0x19u; case TokenType.ImportScope: return result | 0x1Au; } break; } throw new ArgumentException(); } public static int GetSize(this CodedIndex self, Func<Table, int> counter) { int num; Table[] array; switch (self) { case CodedIndex.TypeDefOrRef: num = 2; array = new Table[3] { Table.TypeDef, Table.TypeRef, Table.TypeSpec }; break; case CodedIndex.HasConstant: num = 2; array = new Table[3] { Table.Field, Table.Param, Table.Property }; break; case CodedIndex.HasCustomAttribute: num = 5; array = new Table[22] { Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec }; break; case CodedIndex.HasFieldMarshal: num = 1; array = new Table[2] { Table.Field, Table.Param }; break; case CodedIndex.HasDeclSecurity: num = 2; array = new Table[3] { Table.TypeDef, Table.Method, Table.Assembly }; break; case CodedIndex.MemberRefParent: num = 3; array = new Table[5] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec }; break; case CodedIndex.HasSemantics: num = 1; array = new Table[2] { Table.Event, Table.Property }; break; case CodedIndex.MethodDefOrRef: num = 1; array = new Table[2] { Table.Method, Table.MemberRef }; break; case CodedIndex.MemberForwarded: num = 1; array = new Table[2] { Table.Field, Table.Method }; break; case CodedIndex.Implementation: num = 2; array = new Table[3] { Table.File, Table.AssemblyRef, Table.ExportedType }; break; case CodedIndex.CustomAttributeType: num = 3; array = new Table[2] { Table.Method, Table.MemberRef }; break; case CodedIndex.ResolutionScope: num = 2; array = new Table[4] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef }; break; case CodedIndex.TypeOrMethodDef: num = 1; array = new Table[2] { Table.TypeDef, Table.Method }; break; case CodedIndex.HasCustomDebugInformation: num = 5; array = new Table[27] { Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec, Table.Document, Table.LocalScope, Table.LocalVariable, Table.LocalConstant, Table.ImportScope }; break; default: throw new ArgumentException(); } int num2 = 0; for (int i = 0; i < array.Length; i++) { num2 = Math.Max(counter(array[i]), num2); } if (num2 >= 1 << 16 - num) { return 4; } return 2; } public static RSA CreateRSA(this StrongNameKeyPair key_pair) { if (!TryGetKeyContainer(key_pair, out var key, out var key_container)) { return CryptoConvert.FromCapiKeyBlob(key); } return new RSACryptoServiceProvider(new CspParameters { Flags = CspProviderFlags.UseMachineKeyStore, KeyContainerName = key_container, KeyNumber = 2 }); } private static bool TryGetKeyContainer(ISerializable key_pair, out byte[] key, out string key_container) { SerializationInfo serializationInfo = new SerializationInfo(typeof(StrongNameKeyPair), new FormatterConverter()); key_pair.GetObjectData(serializationInfo, default(StreamingContext)); key = (byte[])serializationInfo.GetValue("_keyPairArray", typeof(byte[])); key_container = serializationInfo.GetString("_keyPairContainer"); return key_container != null; } } public struct ArrayDimension { private int? lower_bound; private int? upper_bound; public int? LowerBound { get { return lower_bound; } set { lower_bound = value; } } public int? UpperBound { get { return upper_bound; } set { upper_bound = value; } } public bool IsSized { get { if (!lower_bound.HasValue) { return upper_bound.HasValue; } return true; } } public ArrayDimension(int? lowerBound, int? upperBound) { lower_bound = lowerBound; upper_bound = upperBound; } public override string ToString() { if (IsSized) { return lower_bound + "..." + upper_bound; } return string.Empty; } } public sealed class ArrayType : TypeSpecification { private Collection<ArrayDimension> dimensions; public Collection<ArrayDimension> Dimensions { get { if (dimensions != null) { return dimensions; } dimensions = new Collection<ArrayDimension>(); dimensions.Add(default(ArrayDimension)); return dimensions; } } public int Rank { get { if (dimensions != null) { return dimensions.Count; } return 1; } } public bool IsVector { get { if (dimensions == null) { return true; } if (dimensions.Count > 1) { return false; } return !dimensions[0].IsSized; } } public override bool IsValueType { get { return false; } set { throw new InvalidOperationException(); } } public override string Name => base.Name + Suffix; public override string FullName => base.FullName + Suffix; private string Suffix { get { if (IsVector) { return "[]"; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("["); for (int i = 0; i < dimensions.Count; i++) { if (i > 0) { stringBuilder.Append(","); } stringBuilder.Append(dimensions[i].ToString()); } stringBuilder.Append("]"); return stringBuilder.ToString(); } } public override bool IsArray => true; public ArrayType(TypeReference type) : base(type) { Mixin.CheckType(type); etype = Mono.Cecil.Metadata.ElementType.Array; } public ArrayType(TypeReference type, int rank) : this(type) { Mixin.CheckType(type); if (rank != 1) { dimensions = new Collection<ArrayDimension>(rank); for (int i = 0; i < rank; i++) { dimensions.Add(default(ArrayDimension)); } etype = Mono.Cecil.Metadata.ElementType.Array; } } } public sealed class AssemblyDefinition : ICustomAttributeProvider, IMetadataTokenProvider, ISecurityDeclarationProvider, IDisposable { private AssemblyNameDefinition name; internal ModuleDefinition main_module; private Collection<ModuleDefinition> modules; private Collection<CustomAttribute> custom_attributes; private Collection<SecurityDeclaration> security_declarations; public AssemblyNameDefinition Name { get { return name; } set { name = value; } } public string FullName { get { if (name == null) { return string.Empty; } return name.FullName; } } public MetadataToken MetadataToken { get { return new MetadataToken(TokenType.Assembly, 1); } set { } } public Collection<ModuleDefinition> Modules { get { if (modules != null) { return modules; } if (main_module.HasImage) { return main_module.Read(ref modules, this, (AssemblyDefinition _, MetadataReader reader) => reader.ReadModules()); } return modules = new Collection<ModuleDefinition>(1) { main_module }; } } public ModuleDefinition MainModule => main_module; public MethodDefinition EntryPoint { get { return main_module.EntryPoint; } set { main_module.EntryPoint = value; } } public bool HasCustomAttributes { get { if (custom_attributes != null) { return custom_attributes.Count > 0; } return this.GetHasCustomAttributes(main_module); } } public Collection<CustomAttribute> CustomAttributes => custom_attributes ?? this.GetCustomAttributes(ref custom_attributes, main_module); public bool HasSecurityDeclarations { get { if (security_declarations != null) { return security_declarations.Count > 0; } return this.GetHasSecurityDeclarations(main_module); } } public Collection<SecurityDeclaration> SecurityDeclarations => security_declarations ?? this.GetSecurityDeclarations(ref security_declarations, main_module); internal AssemblyDefinition() { } public void Dispose() { if (modules == null) { main_module.Dispose(); return; } Collection<ModuleDefinition> collection = Modules; for (int i = 0; i < collection.Count; i++) { collection[i].Dispose(); } } public static AssemblyDefinition CreateAssembly(AssemblyNameDefinition assemblyName, string moduleName, ModuleKind kind) { return CreateAssembly(assemblyName, moduleName, new ModuleParameters { Kind = kind }); } public static AssemblyDefinition CreateAssembly(AssemblyNameDefinition assemblyName, string moduleName, ModuleParameters parameters) { if (assemblyName == null) { throw new ArgumentNullException("assemblyName"); } if (moduleName == null) { throw new ArgumentNullException("moduleName"); } Mixin.CheckParameters(parameters); if (parameters.Kind == ModuleKind.NetModule) { throw new ArgumentException("kind"); } AssemblyDefinition assembly = ModuleDefinition.CreateModule(moduleName, parameters).Assembly; assembly.Name = assemblyName; return assembly; } public static AssemblyDefinition ReadAssembly(string fileName) { return ReadAssembly(ModuleDefinition.ReadModule(fileName)); } public static AssemblyDefinition ReadAssembly(string fileName, ReaderParameters parameters) { return ReadAssembly(ModuleDefinition.ReadModule(fileName, parameters)); } public static AssemblyDefinition ReadAssembly(Stream stream) { return ReadAssembly(ModuleDefinition.ReadModule(stream)); } public static AssemblyDefinition ReadAssembly(Stream stream, ReaderParameters parameters) { return ReadAssembly(ModuleDefinition.ReadModule(stream, parameters)); } private static AssemblyDefinition ReadAssembly(ModuleDefinition module) { return module.Assembly ?? throw new ArgumentException(); } public void Write(string fileName) { Write(fileName, new WriterParameters()); } public void Write(string fileName, WriterParameters parameters) { main_module.Write(fileName, parameters); } public void Write() { main_module.Write(); } public void Write(WriterParameters parameters) { main_module.Write(parameters); } public void Write(Stream stream) { Write(stream, new WriterParameters()); } public void Write(Stream stream, WriterParameters parameters) { main_module.Write(stream, parameters); } public override string ToString() { return FullName; } } [Flags] public enum AssemblyAttributes : uint { PublicKey = 1u, SideBySideCompatible = 0u, Retargetable = 0x100u, WindowsRuntime = 0x200u, DisableJITCompileOptimizer = 0x4000u, EnableJITCompileTracking = 0x8000u } public enum AssemblyHashAlgorithm : uint { None = 0u, Reserved = 32771u, SHA1 = 32772u } public sealed class AssemblyLinkedResource : Resource { private AssemblyNameReference reference; public AssemblyNameReference Assembly { get { return reference; } set { reference = value; } } public override ResourceType ResourceType => ResourceType.AssemblyLinked; public AssemblyLinkedResource(string name, ManifestResourceAttributes flags) : base(name, flags) { } public AssemblyLinkedResource(string name, ManifestResourceAttributes flags, AssemblyNameReference reference) : base(name, flags) { this.reference = reference; } } public sealed class AssemblyNameDefinition : AssemblyNameReference { public override byte[] Hash => Empty<byte>.Array; internal AssemblyNameDefinition() { token = new MetadataToken(TokenType.Assembly, 1); } public AssemblyNameDefinition(string name, Version version) : base(name, version) { token = new MetadataToken(TokenType.Assembly, 1); } } public class AssemblyNameReference : IMetadataScope, IMetadataTokenProvider { private string name; private string culture; private Version version; private uint attributes; private byte[] public_key; private byte[] public_key_token; private AssemblyHashAlgorithm hash_algorithm; private byte[] hash; internal MetadataToken token; private string full_name; public string Name { get { return name; } set { name = value; full_name = null; } } public string Culture { get { return culture; } set { culture = value; full_name = null; } } public Version Version { get { return version; } set { version = Mixin.CheckVersion(value); full_name = null; } } public AssemblyAttributes Attributes { get { return (AssemblyAttributes)attributes; } set { attributes = (uint)value; } } public bool HasPublicKey { get { return attributes.GetAttributes(1u); } set { attributes = attributes.SetAttributes(1u, value); } } public bool IsSideBySideCompatible { get { return attributes.GetAttributes(0u); } set { attributes = attributes.SetAttributes(0u, value); } } public bool IsRetargetable { get { return attributes.GetAttributes(256u); } set { attributes = attributes.SetAttributes(256u, value); } } public bool IsWindowsRuntime { get { return attributes.GetAttributes(512u); } set { attributes = attributes.SetAttributes(512u, value); } } public byte[] PublicKey { get { return public_key ?? Empty<byte>.Array; } set { public_key = value; HasPublicKey = !public_key.IsNullOrEmpty(); public_key_token = Empty<byte>.Array; full_name = null; } } public byte[] PublicKeyToken { get { if (public_key_token.IsNullOrEmpty() && !public_key.IsNullOrEmpty()) { byte[] array = HashPublicKey(); byte[] array2 = new byte[8]; Array.Copy(array, array.Length - 8, array2, 0, 8); Array.Reverse((Array)array2, 0, 8); public_key_token = array2; } return public_key_token ?? Empty<byte>.Array; } set { public_key_token = value; full_name = null; } } public virtual MetadataScopeType MetadataScopeType => MetadataScopeType.AssemblyNameReference; public string FullName { get { if (full_name != null) { return full_name; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(name); stringBuilder.Append(", "); stringBuilder.Append("Version="); stringBuilder.Append(version.ToString(4)); stringBuilder.Append(", "); stringBuilder.Append("Culture="); stringBuilder.Append(string.IsNullOrEmpty(culture) ? "neutral" : culture); stringBuilder.Append(", "); stringBuilder.Append("PublicKeyToken="); byte[] publicKeyToken = PublicKeyToken; if (!publicKeyToken.IsNullOrEmpty() && publicKeyToken.Length != 0) { for (int i = 0; i < publicKeyToken.Length; i++) { stringBuilder.Append(publicKeyToken[i].ToString("x2")); } } else { stringBuilder.Append("null"); } if (IsRetargetable) { stringBuilder.Append(", "); stringBuilder.Append("Retargetable=Yes"); } return full_name = stringBuilder.ToString(); } } public AssemblyHashAlgorithm HashAlgorithm { get { return hash_algorithm; } set { hash_algorithm = value; } } public virtual byte[] Hash { get { return hash; } set { hash = value; } } public MetadataToken MetadataToken { get { return token; } set { token = value; } } private byte[] HashPublicKey() { AssemblyHashAlgorithm assemblyHashAlgorithm = hash_algorithm; HashAlgorithm hashAlgorithm = ((assemblyHashAlgorithm != AssemblyHashAlgorithm.Reserved) ? ((HashAlgorithm)SHA1.Create()) : ((HashAlgorithm)MD5.Create())); using (hashAlgorithm) { return hashAlgorithm.ComputeHash(public_key); } } public static AssemblyNameReference Parse(string fullName) { if (fullName == null) { throw new ArgumentNullException("fullName"); } if (fullName.Length == 0) { throw new ArgumentException("Name can not be empty"); } AssemblyNameReference assemblyNameReference = new AssemblyNameReference(); string[] array = fullName.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (i == 0) { assemblyNameReference.Name = text; continue; } string[] array2 = text.Split(new char[1] { '=' }); if (array2.Length != 2) { throw new ArgumentException("Malformed name"); } switch (array2[0].ToLowerInvariant()) { case "version": assemblyNameReference.Version = new Version(array2[1]); break; case "culture": assemblyNameReference.Culture = ((array2[1] == "neutral") ? "" : array2[1]); break; case "publickeytoken": { string text2 = array2[1]; if (!(text2 == "null")) { assemblyNameReference.PublicKeyToken = new byte[text2.Length / 2]; for (int j = 0; j < assemblyNameReference.PublicKeyToken.Length; j++) { assemblyNameReference.PublicKeyToken[j] = byte.Parse(text2.Substring(j * 2, 2), NumberStyles.HexNumber); } } break; } } } return assemblyNameReference; } internal AssemblyNameReference() { version = Mixin.ZeroVersion; token = new MetadataToken(TokenType.AssemblyRef); } public AssemblyNameReference(string name, Version version) { Mixin.CheckName(name); this.name = name; this.version = Mixin.CheckVersion(version); hash_algorithm = AssemblyHashAlgorithm.None; token = new MetadataToken(TokenType.AssemblyRef); } public override string ToString() { return FullName; } } internal abstract class ModuleReader { protected readonly ModuleDefinition module; protected ModuleReader(Image image, ReadingMode mode) { module = new ModuleDefinition(image); module.ReadingMode = mode; } protected abstract void ReadModule(); public abstract void ReadSymbols(ModuleDefinition module); protected void ReadModuleManifest(MetadataReader reader) { reader.Populate(module); ReadAssembly(reader); } private void ReadAssembly(MetadataReader reader) { AssemblyNameDefinition assemblyNameDefinition = reader.ReadAssemblyNameDefinition(); if (assemblyNameDefinition == null) { module.kind = ModuleKind.NetModule; return; } AssemblyDefinition assemblyDefinition = new AssemblyDefinition(); assemblyDefinition.Name = assemblyNameDefinition; module.assembly = assemblyDefinition; assemblyDefinition.main_module = module; } public static ModuleDefinition CreateModule(Image image, ReaderParameters parameters) { ModuleReader moduleReader = CreateModuleReader(image, parameters.ReadingMode); ModuleDefinition moduleDefinition = moduleReader.module; if (parameters.assembly_resolver != null) { moduleDefinition.assembly_resolver = Disposable.NotOwned(parameters.assembly_resolver); } if (parameters.metadata_resolver != null) { moduleDefinition.metadata_resolver = parameters.metadata_resolver; } if (parameters.metadata_importer_provider != null) { moduleDefinition.metadata_importer = parameters.metadata_importer_provider.GetMetadataImporter(moduleDefinition); } if (parameters.reflection_importer_provider != null) { moduleDefinition.reflection_importer = parameters.reflection_importer_provider.GetReflectionImporter(moduleDefinition); } GetMetadataKind(moduleDefinition, parameters); moduleReader.ReadModule(); ReadSymbols(moduleDefinition, parameters); moduleReader.ReadSymbols(moduleDefinition); if (parameters.ReadingMode == ReadingMode.Immediate) { moduleDefinition.MetadataSystem.Clear(); } return moduleDefinition; } private static void ReadSymbols(ModuleDefinition module, ReaderParameters parameters) { ISymbolReaderProvider symbolReaderProvider = parameters.SymbolReaderProvider; if (symbolReaderProvider == null && parameters.ReadSymbols) { symbolReaderProvider = new DefaultSymbolReaderProvider(); } if (symbolReaderProvider != null) { module.SymbolReaderProvider = symbolReaderProvider; ISymbolReader symbolReader = ((parameters.SymbolStream != null) ? symbolReaderProvider.GetSymbolReader(module, parameters.SymbolStream) : symbolReaderProvider.GetSymbolReader(module, module.FileName)); if (symbolReader != null) { try { module.ReadSymbols(symbolReader, parameters.ThrowIfSymbolsAreNotMatching); } catch (Exception) { symbolReader.Dispose(); throw; } } } if (module.Image.HasDebugTables()) { module.ReadSymbols(new PortablePdbReader(module.Image, module)); } } private static void GetMetadataKind(ModuleDefinition module, ReaderParameters parameters) { if (!parameters.ApplyWindowsRuntimeProjections) { module.MetadataKind = MetadataKind.Ecma335; return; } string runtimeVersion = module.RuntimeVersion; if (!runtimeVersion.Contains("WindowsRuntime")) { module.MetadataKind = MetadataKind.Ecma335; } else if (runtimeVersion.Contains("CLR")) { module.MetadataKind = MetadataKind.ManagedWindowsMetadata; } else { module.MetadataKind = MetadataKind.WindowsMetadata; } } private static ModuleReader CreateModuleReader(Image image, ReadingMode mode) { return mode switch { ReadingMode.Immediate => new ImmediateModuleReader(image), ReadingMode.Deferred => new DeferredModuleReader(image), _ => throw new ArgumentException(), }; } } internal sealed class ImmediateModuleReader : ModuleReader { private bool resolve_attributes; public ImmediateModuleReader(Image image) : base(image, ReadingMode.Immediate) { } protected override void ReadModule() { module.Read(module, delegate(ModuleDefinition module, MetadataReader reader) { ReadModuleManifest(reader); ReadModule(module, resolve_attributes: true); }); } public void ReadModule(ModuleDefinition module, bool resolve_attributes) { this.resolve_attributes = resolve_attributes; if (module.HasAssemblyReferences) { Mixin.Read(module.AssemblyReferences); } if (module.HasResources) { Mixin.Read(module.Resources); } if (module.HasModuleReferences) { Mixin.Read(module.ModuleReferences); } if (module.HasTypes) { ReadTypes(module.Types); } if (module.HasExportedTypes) { Mixin.Read(module.ExportedTypes); } ReadCustomAttributes(module); AssemblyDefinition assembly = module.Assembly; if (assembly != null) { ReadCustomAttributes(assembly); ReadSecurityDeclarations(assembly); } } private void ReadTypes(Collection<TypeDefinition> types) { for (int i = 0; i < types.Count; i++) { ReadType(types[i]); } } private void ReadType(TypeDefinition type) { ReadGenericParameters(type); if (type.HasInterfaces) { ReadInterfaces(type); } if (type.HasNestedTypes) { ReadTypes(type.NestedTypes); } if (type.HasLayoutInfo) { Mixin.Read(type.ClassSize); } if (type.HasFields) { ReadFields(type); } if (type.HasMethods) { ReadMethods(type); } if (type.HasProperties) { ReadProperties(type); } if (type.HasEvents) { ReadEvents(type); } ReadSecurityDeclarations(type); ReadCustomAttributes(type); } private void ReadInterfaces(TypeDefinition type) { Collection<InterfaceImplementation> interfaces = type.Interfaces; for (int i = 0; i < interfaces.Count; i++) { ReadCustomAttributes(interfaces[i]); } } private void ReadGenericParameters(IGenericParameterProvider provider) { if (!provider.HasGenericParameters) { return; } Collection<GenericParameter> genericParameters = provider.GenericParameters; for (int i = 0; i < genericParameters.Count; i++) { GenericParameter genericParameter = genericParameters[i]; if (genericParameter.HasConstraints) { Mixin.Read(genericParameter.Constraints); } ReadCustomAttributes(genericParameter); } } private void ReadSecurityDeclarations(ISecurityDeclarationProvider provider) { if (!provider.HasSecurityDeclarations) { return; } Collection<SecurityDeclaration> securityDeclarations = provider.SecurityDeclarations; if (resolve_attributes) { for (int i = 0; i < securityDeclarations.Count; i++) { Mixin.Read(securityDeclarations[i].SecurityAttributes); } } } private void ReadCustomAttributes(ICustomAttributeProvider provider) { if (!provider.HasCustomAttributes) { return; } Collection<CustomAttribute> customAttributes = provider.CustomAttributes; if (resolve_attributes) { for (int i = 0; i < customAttributes.Count; i++) { Mixin.Read(customAttributes[i].ConstructorArguments); } } } private void ReadFields(TypeDefinition type) { Collection<FieldDefinition> fields = type.Fields; for (int i = 0; i < fields.Count; i++) { FieldDefinition fieldDefinition = fields[i]; if (fieldDefinition.HasConstant) { Mixin.Read(fieldDefinition.Constant); } if (fieldDefinition.HasLayoutInfo) { Mixin.Read(fieldDefinition.Offset); } if (fieldDefinition.RVA > 0) { Mixin.Read(fieldDefinition.InitialValue); } if (fieldDefinition.HasMarshalInfo) { Mixin.Read(fieldDefinition.MarshalInfo); } ReadCustomAttributes(fieldDefinition); } } private void ReadMethods(TypeDefinition type) { Collection<MethodDefinition> methods = type.Methods; for (int i = 0; i < methods.Count; i++) { MethodDefinition methodDefinition = methods[i]; ReadGenericParameters(methodDefinition); if (methodDefinition.HasParameters) { ReadParameters(methodDefinition); } if (methodDefinition.HasOverrides) { Mixin.Read(methodDefinition.Overrides); } if (methodDefinition.IsPInvokeImpl) { Mixin.Read(methodDefinition.PInvokeInfo); } ReadSecurityDeclarations(methodDefinition); ReadCustomAttributes(methodDefinition); MethodReturnType methodReturnType = methodDefinition.MethodReturnType; if (methodReturnType.HasConstant) { Mixin.Read(methodReturnType.Constant); } if (methodReturnType.HasMarshalInfo) { Mixin.Read(methodReturnType.MarshalInfo); } ReadCustomAttributes(methodReturnType); } } private void ReadParameters(MethodDefinition method) { Collection<ParameterDefinition> parameters = method.Parameters; for (int i = 0; i < parameters.Count; i++) { ParameterDefinition parameterDefinition = parameters[i]; if (parameterDefinition.HasConstant) { Mixin.Read(parameterDefinition.Constant); } if (parameterDefinition.HasMarshalInfo) { Mixin.Read(parameterDefinition.MarshalInfo); } ReadCustomAttributes(parameterDefinition); } } private void ReadProperties(TypeDefinition type) { Collection<PropertyDefinition> properties = type.Properties; for (int i = 0; i < properties.Count; i++) { PropertyDefinition propertyDefinition = properties[i]; Mixin.Read(propertyDefinition.GetMethod); if (propertyDefinition.HasConstant) { Mixin.Read(propertyDefinition.Constant); } ReadCustomAttributes(propertyDefinition); } } private void ReadEvents(TypeDefinition type) { Collection<EventDefinition> events = type.Events; for (int i = 0; i < events.Count; i++) { EventDefinition eventDefinition = events[i]; Mixin.Read(eventDefinition.AddMethod); ReadCustomAttributes(eventDefinition); } } public override void ReadSymbols(ModuleDefinition module) { if (module.symbol_reader != null) { ReadTypesSymbols(module.Types, module.symbol_reader); } } private void ReadTypesSymbols(Collection<TypeDefinition> types, ISymbolReader symbol_reader) { for (int i = 0; i < types.Count; i++) { TypeDefinition typeDefinition = types[i]; if (typeDefinition.HasNestedTypes) { ReadTypesSymbols(typeDefinition.NestedTypes, symbol_reader); } if (typeDefinition.HasMethods) { ReadMethodsSymbols(typeDefinition, symbol_reader); } } } private void ReadMethodsSymbols(TypeDefinition type, ISymbolReader symbol_reader) { Collection<MethodDefinition> methods = type.Methods; for (int i = 0; i < methods.Count; i++) { MethodDefinition methodDefinition = methods[i]; if (methodDefinition.HasBody && methodDefinition.token.RID != 0 && methodDefinition.debug_info == null) { methodDefinition.debug_info = symbol_reader.Read(methodDefinition); } } } } internal sealed class DeferredModuleReader : ModuleReader { public DeferredModuleReader(Image image) : base(image, ReadingMode.Deferred) { } protected override void ReadModule() { module.Read(module, delegate(ModuleDefinition _, MetadataReader reader) { ReadModuleManifest(reader); }); } public override void ReadSymbols(ModuleDefinition module) { } } internal sealed class MetadataReader : ByteBuffer { internal readonly Image image; internal readonly ModuleDefinition module; internal readonly MetadataSystem metadata; internal CodeReader code; internal IGenericContext context; private readonly MetadataReader metadata_reader; public MetadataReader(ModuleDefinition module) : base(module.Image.TableHeap.data) { image = module.Image; this.module = module; metadata = module.MetadataSystem; code = new CodeReader(this); } public MetadataReader(Image image, ModuleDefinition module, MetadataReader metadata_reader) : base(image.TableHeap.data) { this.image = image; this.module = module; metadata = module.MetadataSystem; this.metadata_reader = metadata_reader; } private int GetCodedIndexSize(CodedIndex index) { return image.GetCodedIndexSize(index); } private uint ReadByIndexSize(int size) { if (size == 4) { return ReadUInt32(); } return ReadUInt16(); } private byte[] ReadBlob() { BlobHeap blobHeap = image.BlobHeap; if (blobHeap == null) { position += 2; return Empty<byte>.Array; } return blobHeap.Read(ReadBlobIndex()); } private byte[] ReadBlob(uint signature) { BlobHeap blobHeap = image.BlobHeap; if (blobHeap == null) { return Empty<byte>.Array; } return blobHeap.Read(signature); } private uint ReadBlobIndex() { return ReadByIndexSize(image.BlobHeap?.IndexSize ?? 2); } private void GetBlobView(uint signature, out byte[] blob, out int index, out int count) { BlobHeap blobHeap = image.BlobHeap; if (blobHeap == null) { blob = null; index = (count = 0); } else { blobHeap.GetView(signature, out blob, out index, out count); } } private string ReadString() { return image.StringHeap.Read(ReadByIndexSize(image.StringHeap.IndexSize)); } private uint ReadStringIndex() { return ReadByIndexSize(image.StringHeap.IndexSize); } private Guid ReadGuid() { return image.GuidHeap.Read(ReadByIndexSize(image.GuidHeap.IndexSize)); } private uint ReadTableIndex(Table table) { return ReadByIndexSize(image.GetTableIndexSize(table)); } private MetadataToken ReadMetadataToken(CodedIndex index) { return index.GetMetadataToken(ReadByIndexSize(GetCodedIndexSize(index))); } private int MoveTo(Table table) { TableInformation tableInformation = image.TableHeap[table]; if (tableInformation.Length != 0) { position = (int)tableInformation.Offset; } return (int)tableInformation.Length; } private bool MoveTo(Table table, uint row) { TableInformation tableInformation = image.TableHeap[table]; uint num = tableInformation.Length; if (num == 0 || row > num) { return false; } position = (int)(tableInformation.Offset + tableInformation.RowSize * (row - 1)); return true; } public AssemblyNameDefinition ReadAssemblyNameDefinition() { if (MoveTo(Table.Assembly) == 0) { return null; } AssemblyNameDefinition assemblyNameDefinition = new AssemblyNameDefinition(); assemblyNameDefinition.HashAlgorithm = (AssemblyHashAlgorithm)ReadUInt32(); PopulateVersionAndFlags(assemblyNameDefinition); assemblyNameDefinition.PublicKey = ReadBlob(); PopulateNameAndCulture(assemblyNameDefinition); return assemblyNameDefinition; } public ModuleDefinition Populate(ModuleDefinition module) { if (MoveTo(Table.Module) == 0) { return module; } Advance(2); module.Name = ReadString(); module.Mvid = ReadGuid(); return module; } private void InitializeAssemblyReferences() { if (metadata.AssemblyReferences != null) { return; } int num = MoveTo(Table.AssemblyRef); AssemblyNameReference[] array = (metadata.AssemblyReferences = new AssemblyNameReference[num]); for (uint num2 = 0u; num2 < num; num2++) { AssemblyNameReference assemblyNameReference = new AssemblyNameReference(); assemblyNameReference.token = new MetadataToken(TokenType.AssemblyRef, num2 + 1); PopulateVersionAndFlags(assemblyNameReference); byte[] array2 = ReadBlob(); if (assemblyNameReference.HasPublicKey) { assemblyNameReference.PublicKey = array2; } else { assemblyNameReference.PublicKeyToken = array2; } PopulateNameAndCulture(assemblyNameReference); assemblyNameReference.Hash = ReadBlob(); array[num2] = assemblyNameReference; } } public Collection<AssemblyNameReference> ReadAssemblyReferences() { InitializeAssemblyReferences(); Collection<AssemblyNameReference> collection = new Collection<AssemblyNameReference>(metadata.AssemblyReferences); if (module.IsWindowsMetadata()) { module.Projections.AddVirtualReferences(collection); } return collection; } public MethodDefinition ReadEntryPoint() { if (module.Image.EntryPointToken == 0) { return null; } return GetMethodDefinition(new MetadataToken(module.Image.EntryPointToken).RID); } public Collection<ModuleDefinition> ReadModules() { Collection<ModuleDefinition> collection = new Collection<ModuleDefinition>(1); collection.Add(module); int num = MoveTo(Table.File); for (uint num2 = 1u; num2 <= num; num2++) { uint num3 = ReadUInt32(); string name = ReadString(); ReadBlobIndex(); if (num3 == 0) { ReaderParameters parameters = new ReaderParameters { ReadingMode = module.ReadingMode, SymbolReaderProvider = module.SymbolReaderProvider, AssemblyResolver = module.AssemblyResolver }; collection.Add(ModuleDefinition.ReadModule(GetModuleFileName(name), parameters)); } } return collection; } private string GetModuleFileName(string name) { if (module.FileName == null) { throw new NotSupportedException(); } return Path.Combine(Path.GetDirectoryName(module.FileName), name); } private void InitializeModuleReferences() { if (metadata.ModuleReferences == null) { int num = MoveTo(Table.ModuleRef); ModuleReference[] array = (metadata.ModuleReferences = new ModuleReference[num]); for (uint num2 = 0u; num2 < num; num2++) { ModuleReference moduleReference = new ModuleReference(ReadString()); moduleReference.token = new MetadataToken(TokenType.ModuleRef, num2 + 1); array[num2] = moduleReference; } } } public Collection<ModuleReference> ReadModuleReferences() { InitializeModuleReferences(); return new Collection<ModuleReference>(metadata.ModuleReferences); } public bool HasFileResource() { int num = MoveTo(Table.File); if (num == 0) { return false; } for (uint num2 = 1u; num2 <= num; num2++) { if (ReadFileRecord(num2).Col1 == FileAttributes.ContainsNoMetaData) { return true; } } return false; } public Collection<Resource> ReadResources() { int num = MoveTo(Table.ManifestResource); Collection<Resource> collection = new Collection<Resource>(num); for (int i = 1; i <= num; i++) { uint offset = ReadUInt32(); ManifestResourceAttributes manifestResourceAttributes = (ManifestResourceAttributes)ReadUInt32(); string name = ReadString(); MetadataToken scope = ReadMetadataToken(CodedIndex.Implementation); Resource item; if (scope.RID == 0) { item = new EmbeddedResource(name, manifestResourceAttributes, offset, this); } else if (scope.TokenType == TokenType.AssemblyRef) { item = new AssemblyLinkedResource(name, manifestResourceAttributes) { Assembly = (AssemblyNameReference)GetTypeReferenceScope(scope) }; } else { if (scope.TokenType != TokenType.File) { continue; } Row<FileAttributes, string, uint> row = ReadFileRecord(scope.RID); item = new LinkedResource(name, manifestResourceAttributes) { File = row.Col2, hash = ReadBlob(row.Col3) }; } collection.Add(item); } return collection; } private Row<FileAttributes, string, uint> ReadFileRecord(uint rid) { int num = position; if (!MoveTo(Table.File, rid)) { throw new ArgumentException(); } Row<FileAttributes, string, uint> result = new Row<FileAttributes, string, uint>((FileAttributes)ReadUInt32(), ReadString(), ReadBlobIndex()); position = num; return result; } public byte[] GetManagedResource(uint offset) { return image.GetReaderAt(image.Resources.VirtualAddress, offset, delegate(uint o, BinaryStreamReader reader) { reader.Advance((int)o); return reader.ReadBytes(reader.ReadInt32()); }) ?? Empty<byte>.Array; } private void PopulateVersionAndFlags(AssemblyNameReference name) { name.Version = new Version(ReadUInt16(), ReadUInt16(), ReadUInt16(), ReadUInt16()); name.Attributes = (AssemblyAttributes)ReadUInt32(); } private void PopulateNameAndCulture(AssemblyNameReference name) { name.Name = ReadString(); name.Culture = ReadString(); } public TypeDefinitionCollection ReadTypes() { InitializeTypeDefinitions(); TypeDefinition[] types = metadata.Types; int capacity = types.Length - metadata.NestedTypes.Count; TypeDefinitionCollection typeDefinitionCollection = new TypeDefinitionCollection(module, capacity); foreach (TypeDefinition typeDefinition in types) { if (!IsNested(typeDefinition.Attributes)) { typeDefinitionCollection.Add(typeDefinition); } } if (image.HasTable(Table.MethodPtr) || image.HasTable(Table.FieldPtr)) { CompleteTypes(); } return typeDefinitionCollection; } private void CompleteTypes() { TypeDefinition[] types = metadata.Types; foreach (TypeDefinition obj in types) { Mixin.Read(obj.Fields); Mixin.Read(obj.Methods); } } private void InitializeTypeDefinitions() { if (metadata.Types != null) { return; } InitializeNestedTypes(); InitializeFields(); InitializeMethods(); int num = MoveTo(Table.TypeDef); TypeDefinition[] array = (metadata.Types = new TypeDefinition[num]); for (uint num2 = 0u; num2 < num; num2++) { if (array[num2] == null) { array[num2] = ReadType(num2 + 1); } } if (module.IsWindowsMetadata()) { for (uint num3 = 0u; num3 < num; num3++) { WindowsRuntimeProjections.Project(array[num3]); } } } private static bool IsNested(TypeAttributes attributes) { switch (attributes & TypeAttributes.VisibilityMask) { case TypeAttributes.NestedPublic: case TypeAttributes.NestedPrivate: case TypeAttributes.NestedFamily: case TypeAttributes.NestedAssembly: case TypeAttributes.NestedFamANDAssem: case TypeAttributes.VisibilityMask: return true; default: return false; } } public bool HasNestedTypes(TypeDefinition type) { InitializeNestedTypes(); if (!metadata.TryGetNestedTypeMapping(type, out var mapping)) { return false; } return mapping.Count > 0; } public Collection<TypeDefinition> ReadNestedTypes(TypeDefinition type) { InitializeNestedTypes(); if (!metadata.TryGetNestedTypeMapping(type, out var mapping)) { return new MemberDefinitionCollection<TypeDefinition>(type); } MemberDefinitionCollection<TypeDefinition> memberDefinitionCollection = new MemberDefinitionCollection<TypeDefinition>(type, mapping.Count); for (int i = 0; i < mapping.Count; i++) { TypeDefinition typeDefinition = GetTypeDefinition(mapping[i]); if (typeDefinition != null) { memberDefinitionCollection.Add(typeDefinition); } } metadata.RemoveNestedTypeMapping(type); return memberDefinitionCollection; } private void InitializeNestedTypes() { if (metadata.NestedTypes != null) { return; } int num = MoveTo(Table.NestedClass); metadata.NestedTypes = new Dictionary<uint, Collection<uint>>(num); metadata.ReverseNestedTypes = new Dictionary<uint, uint>(num); if (num != 0) { for (int i = 1; i <= num; i++) { uint nested = ReadTableIndex(Table.TypeDef); uint declaring = ReadTableIndex(Table.TypeDef); AddNestedMapping(declaring, nested); } } } private void AddNestedMapping(uint declaring, uint nested) { metadata.SetNestedTypeMapping(declaring, AddMapping(metadata.NestedTypes, declaring, nested)); metadata.SetReverseNestedTypeMapping(nested, declaring); } private static Collection<TValue> AddMapping<TKey, TValue>(Dictionary<TKey, Collection<TValue>> cache, TKey key, TValue value) { if (!cache.TryGetValue(key, out var value2)) { value2 = new Collection<TValue>(); } value2.Add(value); return value2; } private TypeDefinition ReadType(uint rid) { if (!MoveTo(Table.TypeDef, rid)) { return null; } TypeAttributes attributes = (TypeAttributes)ReadUInt32(); string name = ReadString(); TypeDefinition typeDefinition = new TypeDefinition(ReadString(), name, attributes); typeDefinition.token = new MetadataToken(TokenType.TypeDef, rid); typeDefinition.scope = module; typeDefinition.module = module; metadata.AddTypeDefinition(typeDefinition); context = typeDefinition; typeDefinition.BaseType = GetTypeDefOrRef(ReadMetadataToken(CodedIndex.TypeDefOrRef)); typeDefinition.fields_range = ReadListRange(rid, Table.TypeDef, Table.Field); typeDefinition.methods_range = ReadListRange(rid, Table.TypeDef, Table.Method); if (IsNested(attributes)) { typeDefinition.DeclaringType = GetNestedTypeDeclaringType(typeDefinition); } return typeDefinition; } private TypeDefinition GetNestedTypeDeclaringType(TypeDefinition type) { if (!metadata.TryGetReverseNestedTypeMapping(type, out var declaring)) { return null; } metadata.RemoveReverseNestedTypeMapping(type); return GetTypeDefinition(declaring); } private Range ReadListRange(uint current_index, Table current, Table target) { Range result = default(Range); uint num = ReadTableIndex(target); if (num == 0) { return result; } TableInformation tableInformation = image.TableHeap[current]; uint num2; if (current_index == tableInformation.Length) { num2 = image.TableHeap[target].Length + 1; } else { int num3 = position; position += (int)(tableInformation.RowSize - image.GetTableIndexSize(target)); num2 = ReadTableIndex(target); position = num3; } result.Start = num; result.Length = num2 - num; return result; } public Row<short, int> ReadTypeLayout(TypeDefinition type) { InitializeTypeLayouts(); uint rID = type.token.RID; if (!metadata.ClassLayouts.TryGetValue(rID, out var value)) { return new Row<short, int>(-1, -1); } type.PackingSize = (short)value.Col1; type.ClassSize = (int)value.Col2; metadata.ClassLayouts.Remove(rID); return new Row<short, int>((short)value.Col1, (int)value.Col2); } private void InitializeTypeLayouts() { if (metadata.ClassLayouts == null) { int num = MoveTo(Table.ClassLayout); Dictionary<uint, Row<ushort, uint>> dictionary = (metadata.ClassLayouts = new Dictionary<uint, Row<ushort, uint>>(num)); for (uint num2 = 0u;
BepInEx/core/Mono.Cecil.Mdb.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.SymbolStore; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using Mono.Cecil.Cil; using Mono.Collections.Generic; using Mono.CompilerServices.SymbolWriter; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyProduct("Mono.Cecil")] [assembly: AssemblyCopyright("Copyright © 2008 - 2018 Jb Evain")] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("0.10.4.0")] [assembly: AssemblyInformationalVersion("0.10.4.0")] [assembly: AssemblyTitle("Mono.Cecil.Mdb")] [assembly: CLSCompliant(false)] [assembly: AssemblyVersion("0.10.4.0")] namespace Mono.CompilerServices.SymbolWriter { public class MonoSymbolFileException : Exception { public MonoSymbolFileException() { } public MonoSymbolFileException(string message, params object[] args) : base(string.Format(message, args)) { } public MonoSymbolFileException(string message, Exception innerException) : base(message, innerException) { } } internal sealed class MyBinaryWriter : BinaryWriter { public MyBinaryWriter(Stream stream) : base(stream) { } public void WriteLeb128(int value) { Write7BitEncodedInt(value); } } internal class MyBinaryReader : BinaryReader { public MyBinaryReader(Stream stream) : base(stream) { } public int ReadLeb128() { return Read7BitEncodedInt(); } public string ReadString(int offset) { long position = BaseStream.Position; BaseStream.Position = offset; string result = ReadString(); BaseStream.Position = position; return result; } } public interface ISourceFile { SourceFileEntry Entry { get; } } public interface ICompileUnit { CompileUnitEntry Entry { get; } } public interface IMethodDef { string Name { get; } int Token { get; } } public class MonoSymbolFile : IDisposable { private List<MethodEntry> methods = new List<MethodEntry>(); private List<SourceFileEntry> sources = new List<SourceFileEntry>(); private List<CompileUnitEntry> comp_units = new List<CompileUnitEntry>(); private Dictionary<int, AnonymousScopeEntry> anonymous_scopes; private OffsetTable ot; private int last_type_index; private int last_method_index; private int last_namespace_index; public readonly int MajorVersion = 50; public readonly int MinorVersion; public int NumLineNumbers; private MyBinaryReader reader; private Dictionary<int, SourceFileEntry> source_file_hash; private Dictionary<int, CompileUnitEntry> compile_unit_hash; private List<MethodEntry> method_list; private Dictionary<int, MethodEntry> method_token_hash; private Dictionary<string, int> source_name_hash; private Guid guid; internal int LineNumberCount; internal int LocalCount; internal int StringSize; internal int LineNumberSize; internal int ExtendedLineNumberSize; public int CompileUnitCount => ot.CompileUnitCount; public int SourceCount => ot.SourceCount; public int MethodCount => ot.MethodCount; public int TypeCount => ot.TypeCount; public int AnonymousScopeCount => ot.AnonymousScopeCount; public int NamespaceCount => last_namespace_index; public Guid Guid => guid; public OffsetTable OffsetTable => ot; public SourceFileEntry[] Sources { get { if (reader == null) { throw new InvalidOperationException(); } SourceFileEntry[] array = new SourceFileEntry[SourceCount]; for (int i = 0; i < SourceCount; i++) { array[i] = GetSourceFile(i + 1); } return array; } } public CompileUnitEntry[] CompileUnits { get { if (reader == null) { throw new InvalidOperationException(); } CompileUnitEntry[] array = new CompileUnitEntry[CompileUnitCount]; for (int i = 0; i < CompileUnitCount; i++) { array[i] = GetCompileUnit(i + 1); } return array; } } public MethodEntry[] Methods { get { if (reader == null) { throw new InvalidOperationException(); } lock (this) { read_methods(); MethodEntry[] array = new MethodEntry[MethodCount]; method_list.CopyTo(array, 0); return array; } } } internal MyBinaryReader BinaryReader { get { if (reader == null) { throw new InvalidOperationException(); } return reader; } } public MonoSymbolFile() { ot = new OffsetTable(); } public int AddSource(SourceFileEntry source) { sources.Add(source); return sources.Count; } public int AddCompileUnit(CompileUnitEntry entry) { comp_units.Add(entry); return comp_units.Count; } public void AddMethod(MethodEntry entry) { methods.Add(entry); } public MethodEntry DefineMethod(CompileUnitEntry comp_unit, int token, ScopeVariable[] scope_vars, LocalVariableEntry[] locals, LineNumberEntry[] lines, CodeBlockEntry[] code_blocks, string real_name, MethodEntry.Flags flags, int namespace_id) { if (reader != null) { throw new InvalidOperationException(); } MethodEntry methodEntry = new MethodEntry(this, comp_unit, token, scope_vars, locals, lines, code_blocks, real_name, flags, namespace_id); AddMethod(methodEntry); return methodEntry; } internal void DefineAnonymousScope(int id) { if (reader != null) { throw new InvalidOperationException(); } if (anonymous_scopes == null) { anonymous_scopes = new Dictionary<int, AnonymousScopeEntry>(); } anonymous_scopes.Add(id, new AnonymousScopeEntry(id)); } internal void DefineCapturedVariable(int scope_id, string name, string captured_name, CapturedVariable.CapturedKind kind) { if (reader != null) { throw new InvalidOperationException(); } anonymous_scopes[scope_id].AddCapturedVariable(name, captured_name, kind); } internal void DefineCapturedScope(int scope_id, int id, string captured_name) { if (reader != null) { throw new InvalidOperationException(); } anonymous_scopes[scope_id].AddCapturedScope(id, captured_name); } internal int GetNextTypeIndex() { return ++last_type_index; } internal int GetNextMethodIndex() { return ++last_method_index; } internal int GetNextNamespaceIndex() { return ++last_namespace_index; } private void Write(MyBinaryWriter bw, Guid guid) { bw.Write(5037318119232611860L); bw.Write(MajorVersion); bw.Write(MinorVersion); bw.Write(guid.ToByteArray()); long position = bw.BaseStream.Position; ot.Write(bw, MajorVersion, MinorVersion); methods.Sort(); for (int i = 0; i < methods.Count; i++) { methods[i].Index = i + 1; } ot.DataSectionOffset = (int)bw.BaseStream.Position; foreach (SourceFileEntry source in sources) { source.WriteData(bw); } foreach (CompileUnitEntry comp_unit in comp_units) { comp_unit.WriteData(bw); } foreach (MethodEntry method in methods) { method.WriteData(this, bw); } ot.DataSectionSize = (int)bw.BaseStream.Position - ot.DataSectionOffset; ot.MethodTableOffset = (int)bw.BaseStream.Position; for (int j = 0; j < methods.Count; j++) { methods[j].Write(bw); } ot.MethodTableSize = (int)bw.BaseStream.Position - ot.MethodTableOffset; ot.SourceTableOffset = (int)bw.BaseStream.Position; for (int k = 0; k < sources.Count; k++) { sources[k].Write(bw); } ot.SourceTableSize = (int)bw.BaseStream.Position - ot.SourceTableOffset; ot.CompileUnitTableOffset = (int)bw.BaseStream.Position; for (int l = 0; l < comp_units.Count; l++) { comp_units[l].Write(bw); } ot.CompileUnitTableSize = (int)bw.BaseStream.Position - ot.CompileUnitTableOffset; ot.AnonymousScopeCount = ((anonymous_scopes != null) ? anonymous_scopes.Count : 0); ot.AnonymousScopeTableOffset = (int)bw.BaseStream.Position; if (anonymous_scopes != null) { foreach (AnonymousScopeEntry value in anonymous_scopes.Values) { value.Write(bw); } } ot.AnonymousScopeTableSize = (int)bw.BaseStream.Position - ot.AnonymousScopeTableOffset; ot.TypeCount = last_type_index; ot.MethodCount = methods.Count; ot.SourceCount = sources.Count; ot.CompileUnitCount = comp_units.Count; ot.TotalFileSize = (int)bw.BaseStream.Position; bw.Seek((int)position, SeekOrigin.Begin); ot.Write(bw, MajorVersion, MinorVersion); bw.Seek(0, SeekOrigin.End); } public void CreateSymbolFile(Guid guid, FileStream fs) { if (reader != null) { throw new InvalidOperationException(); } Write(new MyBinaryWriter(fs), guid); } private MonoSymbolFile(Stream stream) { reader = new MyBinaryReader(stream); try { long num = reader.ReadInt64(); int num2 = reader.ReadInt32(); int num3 = reader.ReadInt32(); if (num != 5037318119232611860L) { throw new MonoSymbolFileException("Symbol file is not a valid"); } if (num2 != 50) { throw new MonoSymbolFileException("Symbol file has version {0} but expected {1}", num2, 50); } if (num3 != 0) { throw new MonoSymbolFileException("Symbol file has version {0}.{1} but expected {2}.{3}", num2, num3, 50, 0); } MajorVersion = num2; MinorVersion = num3; guid = new Guid(reader.ReadBytes(16)); ot = new OffsetTable(reader, num2, num3); } catch (Exception innerException) { throw new MonoSymbolFileException("Cannot read symbol file", innerException); } source_file_hash = new Dictionary<int, SourceFileEntry>(); compile_unit_hash = new Dictionary<int, CompileUnitEntry>(); } public static MonoSymbolFile ReadSymbolFile(Assembly assembly) { string mdbFilename = assembly.Location + ".mdb"; Guid moduleVersionId = assembly.GetModules()[0].ModuleVersionId; return ReadSymbolFile(mdbFilename, moduleVersionId); } public static MonoSymbolFile ReadSymbolFile(string mdbFilename) { return ReadSymbolFile(new FileStream(mdbFilename, FileMode.Open, FileAccess.Read)); } public static MonoSymbolFile ReadSymbolFile(string mdbFilename, Guid assemblyGuid) { MonoSymbolFile monoSymbolFile = ReadSymbolFile(mdbFilename); if (assemblyGuid != monoSymbolFile.guid) { throw new MonoSymbolFileException("Symbol file `{0}' does not match assembly", mdbFilename); } return monoSymbolFile; } public static MonoSymbolFile ReadSymbolFile(Stream stream) { return new MonoSymbolFile(stream); } public SourceFileEntry GetSourceFile(int index) { if (index < 1 || index > ot.SourceCount) { throw new ArgumentException(); } if (reader == null) { throw new InvalidOperationException(); } lock (this) { if (source_file_hash.TryGetValue(index, out var value)) { return value; } long position = reader.BaseStream.Position; reader.BaseStream.Position = ot.SourceTableOffset + SourceFileEntry.Size * (index - 1); value = new SourceFileEntry(this, reader); source_file_hash.Add(index, value); reader.BaseStream.Position = position; return value; } } public CompileUnitEntry GetCompileUnit(int index) { if (index < 1 || index > ot.CompileUnitCount) { throw new ArgumentException(); } if (reader == null) { throw new InvalidOperationException(); } lock (this) { if (compile_unit_hash.TryGetValue(index, out var value)) { return value; } long position = reader.BaseStream.Position; reader.BaseStream.Position = ot.CompileUnitTableOffset + CompileUnitEntry.Size * (index - 1); value = new CompileUnitEntry(this, reader); compile_unit_hash.Add(index, value); reader.BaseStream.Position = position; return value; } } private void read_methods() { lock (this) { if (method_token_hash == null) { method_token_hash = new Dictionary<int, MethodEntry>(); method_list = new List<MethodEntry>(); long position = reader.BaseStream.Position; reader.BaseStream.Position = ot.MethodTableOffset; for (int i = 0; i < MethodCount; i++) { MethodEntry methodEntry = new MethodEntry(this, reader, i + 1); method_token_hash.Add(methodEntry.Token, methodEntry); method_list.Add(methodEntry); } reader.BaseStream.Position = position; } } } public MethodEntry GetMethodByToken(int token) { if (reader == null) { throw new InvalidOperationException(); } lock (this) { read_methods(); method_token_hash.TryGetValue(token, out var value); return value; } } public MethodEntry GetMethod(int index) { if (index < 1 || index > ot.MethodCount) { throw new ArgumentException(); } if (reader == null) { throw new InvalidOperationException(); } lock (this) { read_methods(); return method_list[index - 1]; } } public int FindSource(string file_name) { if (reader == null) { throw new InvalidOperationException(); } lock (this) { if (source_name_hash == null) { source_name_hash = new Dictionary<string, int>(); for (int i = 0; i < ot.SourceCount; i++) { SourceFileEntry sourceFile = GetSourceFile(i + 1); source_name_hash.Add(sourceFile.FileName, i); } } if (!source_name_hash.TryGetValue(file_name, out var value)) { return -1; } return value; } } public AnonymousScopeEntry GetAnonymousScope(int id) { if (reader == null) { throw new InvalidOperationException(); } lock (this) { if (anonymous_scopes != null) { anonymous_scopes.TryGetValue(id, out var value); return value; } anonymous_scopes = new Dictionary<int, AnonymousScopeEntry>(); reader.BaseStream.Position = ot.AnonymousScopeTableOffset; for (int i = 0; i < ot.AnonymousScopeCount; i++) { AnonymousScopeEntry value = new AnonymousScopeEntry(reader); anonymous_scopes.Add(value.ID, value); } return anonymous_scopes[id]; } } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (disposing && reader != null) { reader.Close(); reader = null; } } } public class OffsetTable { [Flags] public enum Flags { IsAspxSource = 1, WindowsFileNames = 2 } public const int MajorVersion = 50; public const int MinorVersion = 0; public const long Magic = 5037318119232611860L; public int TotalFileSize; public int DataSectionOffset; public int DataSectionSize; public int CompileUnitCount; public int CompileUnitTableOffset; public int CompileUnitTableSize; public int SourceCount; public int SourceTableOffset; public int SourceTableSize; public int MethodCount; public int MethodTableOffset; public int MethodTableSize; public int TypeCount; public int AnonymousScopeCount; public int AnonymousScopeTableOffset; public int AnonymousScopeTableSize; public Flags FileFlags; public int LineNumberTable_LineBase = -1; public int LineNumberTable_LineRange = 8; public int LineNumberTable_OpcodeBase = 9; internal OffsetTable() { int platform = (int)Environment.OSVersion.Platform; if (platform != 4 && platform != 128) { FileFlags |= Flags.WindowsFileNames; } } internal OffsetTable(BinaryReader reader, int major_version, int minor_version) { TotalFileSize = reader.ReadInt32(); DataSectionOffset = reader.ReadInt32(); DataSectionSize = reader.ReadInt32(); CompileUnitCount = reader.ReadInt32(); CompileUnitTableOffset = reader.ReadInt32(); CompileUnitTableSize = reader.ReadInt32(); SourceCount = reader.ReadInt32(); SourceTableOffset = reader.ReadInt32(); SourceTableSize = reader.ReadInt32(); MethodCount = reader.ReadInt32(); MethodTableOffset = reader.ReadInt32(); MethodTableSize = reader.ReadInt32(); TypeCount = reader.ReadInt32(); AnonymousScopeCount = reader.ReadInt32(); AnonymousScopeTableOffset = reader.ReadInt32(); AnonymousScopeTableSize = reader.ReadInt32(); LineNumberTable_LineBase = reader.ReadInt32(); LineNumberTable_LineRange = reader.ReadInt32(); LineNumberTable_OpcodeBase = reader.ReadInt32(); FileFlags = (Flags)reader.ReadInt32(); } internal void Write(BinaryWriter bw, int major_version, int minor_version) { bw.Write(TotalFileSize); bw.Write(DataSectionOffset); bw.Write(DataSectionSize); bw.Write(CompileUnitCount); bw.Write(CompileUnitTableOffset); bw.Write(CompileUnitTableSize); bw.Write(SourceCount); bw.Write(SourceTableOffset); bw.Write(SourceTableSize); bw.Write(MethodCount); bw.Write(MethodTableOffset); bw.Write(MethodTableSize); bw.Write(TypeCount); bw.Write(AnonymousScopeCount); bw.Write(AnonymousScopeTableOffset); bw.Write(AnonymousScopeTableSize); bw.Write(LineNumberTable_LineBase); bw.Write(LineNumberTable_LineRange); bw.Write(LineNumberTable_OpcodeBase); bw.Write((int)FileFlags); } public override string ToString() { return $"OffsetTable [{TotalFileSize} - {DataSectionOffset}:{DataSectionSize} - {SourceCount}:{SourceTableOffset}:{SourceTableSize} - {MethodCount}:{MethodTableOffset}:{MethodTableSize} - {TypeCount}]"; } } public class LineNumberEntry { public sealed class LocationComparer : IComparer<LineNumberEntry> { public static readonly LocationComparer Default = new LocationComparer(); public int Compare(LineNumberEntry l1, LineNumberEntry l2) { if (l1.Row != l2.Row) { int row = l1.Row; return row.CompareTo(l2.Row); } return l1.Column.CompareTo(l2.Column); } } public readonly int Row; public int Column; public int EndRow; public int EndColumn; public readonly int File; public readonly int Offset; public readonly bool IsHidden; public static readonly LineNumberEntry Null = new LineNumberEntry(0, 0, 0, 0); public LineNumberEntry(int file, int row, int column, int offset) : this(file, row, column, offset, is_hidden: false) { } public LineNumberEntry(int file, int row, int offset) : this(file, row, -1, offset, is_hidden: false) { } public LineNumberEntry(int file, int row, int column, int offset, bool is_hidden) : this(file, row, column, -1, -1, offset, is_hidden) { } public LineNumberEntry(int file, int row, int column, int end_row, int end_column, int offset, bool is_hidden) { File = file; Row = row; Column = column; EndRow = end_row; EndColumn = end_column; Offset = offset; IsHidden = is_hidden; } public override string ToString() { return $"[Line {File}:{Row},{Column}-{EndRow},{EndColumn}:{Offset}]"; } } public class CodeBlockEntry { public enum Type { Lexical = 1, CompilerGenerated, IteratorBody, IteratorDispatcher } public int Index; public int Parent; public Type BlockType; public int StartOffset; public int EndOffset; public CodeBlockEntry(int index, int parent, Type type, int start_offset) { Index = index; Parent = parent; BlockType = type; StartOffset = start_offset; } internal CodeBlockEntry(int index, MyBinaryReader reader) { Index = index; int num = reader.ReadLeb128(); BlockType = (Type)(num & 0x3F); Parent = reader.ReadLeb128(); StartOffset = reader.ReadLeb128(); EndOffset = reader.ReadLeb128(); if (((uint)num & 0x40u) != 0) { int num2 = reader.ReadInt16(); reader.BaseStream.Position += num2; } } public void Close(int end_offset) { EndOffset = end_offset; } internal void Write(MyBinaryWriter bw) { bw.WriteLeb128((int)BlockType); bw.WriteLeb128(Parent); bw.WriteLeb128(StartOffset); bw.WriteLeb128(EndOffset); } public override string ToString() { return $"[CodeBlock {Index}:{Parent}:{BlockType}:{StartOffset}:{EndOffset}]"; } } public struct LocalVariableEntry { public readonly int Index; public readonly string Name; public readonly int BlockIndex; public LocalVariableEntry(int index, string name, int block) { Index = index; Name = name; BlockIndex = block; } internal LocalVariableEntry(MonoSymbolFile file, MyBinaryReader reader) { Index = reader.ReadLeb128(); Name = reader.ReadString(); BlockIndex = reader.ReadLeb128(); } internal void Write(MonoSymbolFile file, MyBinaryWriter bw) { bw.WriteLeb128(Index); bw.Write(Name); bw.WriteLeb128(BlockIndex); } public override string ToString() { return $"[LocalVariable {Name}:{Index}:{BlockIndex - 1}]"; } } public struct CapturedVariable { public enum CapturedKind : byte { Local, Parameter, This } public readonly string Name; public readonly string CapturedName; public readonly CapturedKind Kind; public CapturedVariable(string name, string captured_name, CapturedKind kind) { Name = name; CapturedName = captured_name; Kind = kind; } internal CapturedVariable(MyBinaryReader reader) { Name = reader.ReadString(); CapturedName = reader.ReadString(); Kind = (CapturedKind)reader.ReadByte(); } internal void Write(MyBinaryWriter bw) { bw.Write(Name); bw.Write(CapturedName); bw.Write((byte)Kind); } public override string ToString() { return $"[CapturedVariable {Name}:{CapturedName}:{Kind}]"; } } public struct CapturedScope { public readonly int Scope; public readonly string CapturedName; public CapturedScope(int scope, string captured_name) { Scope = scope; CapturedName = captured_name; } internal CapturedScope(MyBinaryReader reader) { Scope = reader.ReadLeb128(); CapturedName = reader.ReadString(); } internal void Write(MyBinaryWriter bw) { bw.WriteLeb128(Scope); bw.Write(CapturedName); } public override string ToString() { return $"[CapturedScope {Scope}:{CapturedName}]"; } } public struct ScopeVariable { public readonly int Scope; public readonly int Index; public ScopeVariable(int scope, int index) { Scope = scope; Index = index; } internal ScopeVariable(MyBinaryReader reader) { Scope = reader.ReadLeb128(); Index = reader.ReadLeb128(); } internal void Write(MyBinaryWriter bw) { bw.WriteLeb128(Scope); bw.WriteLeb128(Index); } public override string ToString() { return $"[ScopeVariable {Scope}:{Index}]"; } } public class AnonymousScopeEntry { public readonly int ID; private List<CapturedVariable> captured_vars = new List<CapturedVariable>(); private List<CapturedScope> captured_scopes = new List<CapturedScope>(); public CapturedVariable[] CapturedVariables { get { CapturedVariable[] array = new CapturedVariable[captured_vars.Count]; captured_vars.CopyTo(array, 0); return array; } } public CapturedScope[] CapturedScopes { get { CapturedScope[] array = new CapturedScope[captured_scopes.Count]; captured_scopes.CopyTo(array, 0); return array; } } public AnonymousScopeEntry(int id) { ID = id; } internal AnonymousScopeEntry(MyBinaryReader reader) { ID = reader.ReadLeb128(); int num = reader.ReadLeb128(); for (int i = 0; i < num; i++) { captured_vars.Add(new CapturedVariable(reader)); } int num2 = reader.ReadLeb128(); for (int j = 0; j < num2; j++) { captured_scopes.Add(new CapturedScope(reader)); } } internal void AddCapturedVariable(string name, string captured_name, CapturedVariable.CapturedKind kind) { captured_vars.Add(new CapturedVariable(name, captured_name, kind)); } internal void AddCapturedScope(int scope, string captured_name) { captured_scopes.Add(new CapturedScope(scope, captured_name)); } internal void Write(MyBinaryWriter bw) { bw.WriteLeb128(ID); bw.WriteLeb128(captured_vars.Count); foreach (CapturedVariable captured_var in captured_vars) { captured_var.Write(bw); } bw.WriteLeb128(captured_scopes.Count); foreach (CapturedScope captured_scope in captured_scopes) { captured_scope.Write(bw); } } public override string ToString() { return $"[AnonymousScope {ID}]"; } } public class CompileUnitEntry : ICompileUnit { public readonly int Index; private int DataOffset; private MonoSymbolFile file; private SourceFileEntry source; private List<SourceFileEntry> include_files; private List<NamespaceEntry> namespaces; private bool creating; public static int Size => 8; CompileUnitEntry ICompileUnit.Entry => this; public SourceFileEntry SourceFile { get { if (creating) { return source; } ReadData(); return source; } } public NamespaceEntry[] Namespaces { get { ReadData(); NamespaceEntry[] array = new NamespaceEntry[namespaces.Count]; namespaces.CopyTo(array, 0); return array; } } public SourceFileEntry[] IncludeFiles { get { ReadData(); if (include_files == null) { return new SourceFileEntry[0]; } SourceFileEntry[] array = new SourceFileEntry[include_files.Count]; include_files.CopyTo(array, 0); return array; } } public CompileUnitEntry(MonoSymbolFile file, SourceFileEntry source) { this.file = file; this.source = source; Index = file.AddCompileUnit(this); creating = true; namespaces = new List<NamespaceEntry>(); } public void AddFile(SourceFileEntry file) { if (!creating) { throw new InvalidOperationException(); } if (include_files == null) { include_files = new List<SourceFileEntry>(); } include_files.Add(file); } public int DefineNamespace(string name, string[] using_clauses, int parent) { if (!creating) { throw new InvalidOperationException(); } int nextNamespaceIndex = file.GetNextNamespaceIndex(); NamespaceEntry item = new NamespaceEntry(name, nextNamespaceIndex, using_clauses, parent); namespaces.Add(item); return nextNamespaceIndex; } internal void WriteData(MyBinaryWriter bw) { DataOffset = (int)bw.BaseStream.Position; bw.WriteLeb128(source.Index); int value = ((include_files != null) ? include_files.Count : 0); bw.WriteLeb128(value); if (include_files != null) { foreach (SourceFileEntry include_file in include_files) { bw.WriteLeb128(include_file.Index); } } bw.WriteLeb128(namespaces.Count); foreach (NamespaceEntry @namespace in namespaces) { @namespace.Write(file, bw); } } internal void Write(BinaryWriter bw) { bw.Write(Index); bw.Write(DataOffset); } internal CompileUnitEntry(MonoSymbolFile file, MyBinaryReader reader) { this.file = file; Index = reader.ReadInt32(); DataOffset = reader.ReadInt32(); } public void ReadAll() { ReadData(); } private void ReadData() { if (creating) { throw new InvalidOperationException(); } lock (file) { if (namespaces != null) { return; } MyBinaryReader binaryReader = file.BinaryReader; int num = (int)binaryReader.BaseStream.Position; binaryReader.BaseStream.Position = DataOffset; int index = binaryReader.ReadLeb128(); source = file.GetSourceFile(index); int num2 = binaryReader.ReadLeb128(); if (num2 > 0) { include_files = new List<SourceFileEntry>(); for (int i = 0; i < num2; i++) { include_files.Add(file.GetSourceFile(binaryReader.ReadLeb128())); } } int num3 = binaryReader.ReadLeb128(); namespaces = new List<NamespaceEntry>(); for (int j = 0; j < num3; j++) { namespaces.Add(new NamespaceEntry(file, binaryReader)); } binaryReader.BaseStream.Position = num; } } } public class SourceFileEntry { public readonly int Index; private int DataOffset; private MonoSymbolFile file; private string file_name; private byte[] guid; private byte[] hash; private bool creating; private bool auto_generated; private readonly string sourceFile; public static int Size => 8; public byte[] Checksum => hash; public string FileName { get { return file_name; } set { file_name = value; } } public bool AutoGenerated => auto_generated; public SourceFileEntry(MonoSymbolFile file, string file_name) { this.file = file; this.file_name = file_name; Index = file.AddSource(this); creating = true; } public SourceFileEntry(MonoSymbolFile file, string sourceFile, byte[] guid, byte[] checksum) : this(file, sourceFile, sourceFile, guid, checksum) { } public SourceFileEntry(MonoSymbolFile file, string fileName, string sourceFile, byte[] guid, byte[] checksum) : this(file, fileName) { this.guid = guid; hash = checksum; this.sourceFile = sourceFile; } internal void WriteData(MyBinaryWriter bw) { DataOffset = (int)bw.BaseStream.Position; bw.Write(file_name); if (guid == null) { guid = new byte[16]; } if (hash == null) { try { using FileStream inputStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read); MD5 mD = MD5.Create(); hash = mD.ComputeHash(inputStream); } catch { hash = new byte[16]; } } bw.Write(guid); bw.Write(hash); bw.Write((byte)(auto_generated ? 1u : 0u)); } internal void Write(BinaryWriter bw) { bw.Write(Index); bw.Write(DataOffset); } internal SourceFileEntry(MonoSymbolFile file, MyBinaryReader reader) { this.file = file; Index = reader.ReadInt32(); DataOffset = reader.ReadInt32(); int num = (int)reader.BaseStream.Position; reader.BaseStream.Position = DataOffset; sourceFile = (file_name = reader.ReadString()); guid = reader.ReadBytes(16); hash = reader.ReadBytes(16); auto_generated = reader.ReadByte() == 1; reader.BaseStream.Position = num; } public void SetAutoGenerated() { if (!creating) { throw new InvalidOperationException(); } auto_generated = true; file.OffsetTable.FileFlags |= OffsetTable.Flags.IsAspxSource; } public bool CheckChecksum() { try { using FileStream inputStream = new FileStream(sourceFile, FileMode.Open); byte[] array = MD5.Create().ComputeHash(inputStream); for (int i = 0; i < 16; i++) { if (array[i] != hash[i]) { return false; } } return true; } catch { return false; } } public override string ToString() { return $"SourceFileEntry ({Index}:{DataOffset})"; } } public class LineNumberTable { protected LineNumberEntry[] _line_numbers; public readonly int LineBase; public readonly int LineRange; public readonly byte OpcodeBase; public readonly int MaxAddressIncrement; public const int Default_LineBase = -1; public const int Default_LineRange = 8; public const byte Default_OpcodeBase = 9; public const byte DW_LNS_copy = 1; public const byte DW_LNS_advance_pc = 2; public const byte DW_LNS_advance_line = 3; public const byte DW_LNS_set_file = 4; public const byte DW_LNS_const_add_pc = 8; public const byte DW_LNE_end_sequence = 1; public const byte DW_LNE_MONO_negate_is_hidden = 64; internal const byte DW_LNE_MONO__extensions_start = 64; internal const byte DW_LNE_MONO__extensions_end = 127; public LineNumberEntry[] LineNumbers => _line_numbers; protected LineNumberTable(MonoSymbolFile file) { LineBase = file.OffsetTable.LineNumberTable_LineBase; LineRange = file.OffsetTable.LineNumberTable_LineRange; OpcodeBase = (byte)file.OffsetTable.LineNumberTable_OpcodeBase; MaxAddressIncrement = (255 - OpcodeBase) / LineRange; } internal LineNumberTable(MonoSymbolFile file, LineNumberEntry[] lines) : this(file) { _line_numbers = lines; } internal void Write(MonoSymbolFile file, MyBinaryWriter bw, bool hasColumnsInfo, bool hasEndInfo) { int num = (int)bw.BaseStream.Position; bool flag = false; int num2 = 1; int num3 = 0; int num4 = 1; for (int i = 0; i < LineNumbers.Length; i++) { int num5 = LineNumbers[i].Row - num2; int num6 = LineNumbers[i].Offset - num3; if (LineNumbers[i].File != num4) { bw.Write((byte)4); bw.WriteLeb128(LineNumbers[i].File); num4 = LineNumbers[i].File; } if (LineNumbers[i].IsHidden != flag) { bw.Write((byte)0); bw.Write((byte)1); bw.Write((byte)64); flag = LineNumbers[i].IsHidden; } if (num6 >= MaxAddressIncrement) { if (num6 < 2 * MaxAddressIncrement) { bw.Write((byte)8); num6 -= MaxAddressIncrement; } else { bw.Write((byte)2); bw.WriteLeb128(num6); num6 = 0; } } if (num5 < LineBase || num5 >= LineBase + LineRange) { bw.Write((byte)3); bw.WriteLeb128(num5); if (num6 != 0) { bw.Write((byte)2); bw.WriteLeb128(num6); } bw.Write((byte)1); } else { byte value = (byte)(num5 - LineBase + LineRange * num6 + OpcodeBase); bw.Write(value); } num2 = LineNumbers[i].Row; num3 = LineNumbers[i].Offset; } bw.Write((byte)0); bw.Write((byte)1); bw.Write((byte)1); if (hasColumnsInfo) { for (int j = 0; j < LineNumbers.Length; j++) { LineNumberEntry lineNumberEntry = LineNumbers[j]; if (lineNumberEntry.Row >= 0) { bw.WriteLeb128(lineNumberEntry.Column); } } } if (hasEndInfo) { for (int k = 0; k < LineNumbers.Length; k++) { LineNumberEntry lineNumberEntry2 = LineNumbers[k]; if (lineNumberEntry2.EndRow == -1 || lineNumberEntry2.EndColumn == -1 || lineNumberEntry2.Row > lineNumberEntry2.EndRow) { bw.WriteLeb128(16777215); continue; } bw.WriteLeb128(lineNumberEntry2.EndRow - lineNumberEntry2.Row); bw.WriteLeb128(lineNumberEntry2.EndColumn); } } file.ExtendedLineNumberSize += (int)bw.BaseStream.Position - num; } internal static LineNumberTable Read(MonoSymbolFile file, MyBinaryReader br, bool readColumnsInfo, bool readEndInfo) { LineNumberTable lineNumberTable = new LineNumberTable(file); lineNumberTable.DoRead(file, br, readColumnsInfo, readEndInfo); return lineNumberTable; } private void DoRead(MonoSymbolFile file, MyBinaryReader br, bool includesColumns, bool includesEnds) { List<LineNumberEntry> list = new List<LineNumberEntry>(); bool flag = false; bool flag2 = false; int num = 1; int num2 = 0; int file2 = 1; while (true) { byte b = br.ReadByte(); if (b == 0) { byte b2 = br.ReadByte(); long position = br.BaseStream.Position + b2; b = br.ReadByte(); switch (b) { case 1: { if (flag2) { list.Add(new LineNumberEntry(file2, num, -1, num2, flag)); } _line_numbers = list.ToArray(); if (includesColumns) { for (int i = 0; i < _line_numbers.Length; i++) { LineNumberEntry lineNumberEntry = _line_numbers[i]; if (lineNumberEntry.Row >= 0) { lineNumberEntry.Column = br.ReadLeb128(); } } } if (!includesEnds) { return; } for (int j = 0; j < _line_numbers.Length; j++) { LineNumberEntry lineNumberEntry2 = _line_numbers[j]; int num3 = br.ReadLeb128(); if (num3 == 16777215) { lineNumberEntry2.EndRow = -1; lineNumberEntry2.EndColumn = -1; } else { lineNumberEntry2.EndRow = lineNumberEntry2.Row + num3; lineNumberEntry2.EndColumn = br.ReadLeb128(); } } return; } case 64: flag = !flag; flag2 = true; break; default: throw new MonoSymbolFileException("Unknown extended opcode {0:x}", b); case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72: case 73: case 74: case 75: case 76: case 77: case 78: case 79: case 80: case 81: case 82: case 83: case 84: case 85: case 86: case 87: case 88: case 89: case 90: case 91: case 92: case 93: case 94: case 95: case 96: case 97: case 98: case 99: case 100: case 101: case 102: case 103: case 104: case 105: case 106: case 107: case 108: case 109: case 110: case 111: case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: break; } br.BaseStream.Position = position; } else if (b < OpcodeBase) { switch (b) { case 1: list.Add(new LineNumberEntry(file2, num, -1, num2, flag)); flag2 = false; break; case 2: num2 += br.ReadLeb128(); flag2 = true; break; case 3: num += br.ReadLeb128(); flag2 = true; break; case 4: file2 = br.ReadLeb128(); flag2 = true; break; case 8: num2 += MaxAddressIncrement; flag2 = true; break; default: throw new MonoSymbolFileException("Unknown standard opcode {0:x} in LNT", b); } } else { b -= OpcodeBase; num2 += b / LineRange; num += LineBase + b % LineRange; list.Add(new LineNumberEntry(file2, num, -1, num2, flag)); flag2 = false; } } } public bool GetMethodBounds(out LineNumberEntry start, out LineNumberEntry end) { if (_line_numbers.Length > 1) { start = _line_numbers[0]; end = _line_numbers[_line_numbers.Length - 1]; return true; } start = LineNumberEntry.Null; end = LineNumberEntry.Null; return false; } } public class MethodEntry : IComparable { [Flags] public enum Flags { LocalNamesAmbiguous = 1, ColumnsInfoIncluded = 2, EndInfoIncluded = 4 } public readonly int CompileUnitIndex; public readonly int Token; public readonly int NamespaceID; private int DataOffset; private int LocalVariableTableOffset; private int LineNumberTableOffset; private int CodeBlockTableOffset; private int ScopeVariableTableOffset; private int RealNameOffset; private Flags flags; private int index; public readonly CompileUnitEntry CompileUnit; private LocalVariableEntry[] locals; private CodeBlockEntry[] code_blocks; private ScopeVariable[] scope_vars; private LineNumberTable lnt; private string real_name; public readonly MonoSymbolFile SymbolFile; public const int Size = 12; public Flags MethodFlags => flags; public int Index { get { return index; } set { index = value; } } internal MethodEntry(MonoSymbolFile file, MyBinaryReader reader, int index) { SymbolFile = file; this.index = index; Token = reader.ReadInt32(); DataOffset = reader.ReadInt32(); LineNumberTableOffset = reader.ReadInt32(); long position = reader.BaseStream.Position; reader.BaseStream.Position = DataOffset; CompileUnitIndex = reader.ReadLeb128(); LocalVariableTableOffset = reader.ReadLeb128(); NamespaceID = reader.ReadLeb128(); CodeBlockTableOffset = reader.ReadLeb128(); ScopeVariableTableOffset = reader.ReadLeb128(); RealNameOffset = reader.ReadLeb128(); flags = (Flags)reader.ReadLeb128(); reader.BaseStream.Position = position; CompileUnit = file.GetCompileUnit(CompileUnitIndex); } internal MethodEntry(MonoSymbolFile file, CompileUnitEntry comp_unit, int token, ScopeVariable[] scope_vars, LocalVariableEntry[] locals, LineNumberEntry[] lines, CodeBlockEntry[] code_blocks, string real_name, Flags flags, int namespace_id) { SymbolFile = file; this.real_name = real_name; this.locals = locals; this.code_blocks = code_blocks; this.scope_vars = scope_vars; this.flags = flags; index = -1; Token = token; CompileUnitIndex = comp_unit.Index; CompileUnit = comp_unit; NamespaceID = namespace_id; CheckLineNumberTable(lines); lnt = new LineNumberTable(file, lines); file.NumLineNumbers += lines.Length; int num = ((locals != null) ? locals.Length : 0); if (num <= 32) { for (int i = 0; i < num; i++) { string name = locals[i].Name; for (int j = i + 1; j < num; j++) { if (locals[j].Name == name) { flags |= Flags.LocalNamesAmbiguous; return; } } } return; } Dictionary<string, LocalVariableEntry> dictionary = new Dictionary<string, LocalVariableEntry>(); for (int k = 0; k < locals.Length; k++) { LocalVariableEntry value = locals[k]; if (dictionary.ContainsKey(value.Name)) { flags |= Flags.LocalNamesAmbiguous; break; } dictionary.Add(value.Name, value); } } private static void CheckLineNumberTable(LineNumberEntry[] line_numbers) { int num = -1; int num2 = -1; if (line_numbers == null) { return; } foreach (LineNumberEntry lineNumberEntry in line_numbers) { if (lineNumberEntry.Equals(LineNumberEntry.Null)) { throw new MonoSymbolFileException(); } if (lineNumberEntry.Offset < num) { throw new MonoSymbolFileException(); } if (lineNumberEntry.Offset > num) { num2 = lineNumberEntry.Row; num = lineNumberEntry.Offset; } else if (lineNumberEntry.Row > num2) { num2 = lineNumberEntry.Row; } } } internal void Write(MyBinaryWriter bw) { if (index <= 0 || DataOffset == 0) { throw new InvalidOperationException(); } bw.Write(Token); bw.Write(DataOffset); bw.Write(LineNumberTableOffset); } internal void WriteData(MonoSymbolFile file, MyBinaryWriter bw) { if (index <= 0) { throw new InvalidOperationException(); } LocalVariableTableOffset = (int)bw.BaseStream.Position; int num = ((locals != null) ? locals.Length : 0); bw.WriteLeb128(num); for (int i = 0; i < num; i++) { locals[i].Write(file, bw); } file.LocalCount += num; CodeBlockTableOffset = (int)bw.BaseStream.Position; int num2 = ((code_blocks != null) ? code_blocks.Length : 0); bw.WriteLeb128(num2); for (int j = 0; j < num2; j++) { code_blocks[j].Write(bw); } ScopeVariableTableOffset = (int)bw.BaseStream.Position; int num3 = ((scope_vars != null) ? scope_vars.Length : 0); bw.WriteLeb128(num3); for (int k = 0; k < num3; k++) { scope_vars[k].Write(bw); } if (real_name != null) { RealNameOffset = (int)bw.BaseStream.Position; bw.Write(real_name); } LineNumberEntry[] lineNumbers = lnt.LineNumbers; foreach (LineNumberEntry lineNumberEntry in lineNumbers) { if (lineNumberEntry.EndRow != -1 || lineNumberEntry.EndColumn != -1) { flags |= Flags.EndInfoIncluded; } } LineNumberTableOffset = (int)bw.BaseStream.Position; lnt.Write(file, bw, (flags & Flags.ColumnsInfoIncluded) != 0, (flags & Flags.EndInfoIncluded) != 0); DataOffset = (int)bw.BaseStream.Position; bw.WriteLeb128(CompileUnitIndex); bw.WriteLeb128(LocalVariableTableOffset); bw.WriteLeb128(NamespaceID); bw.WriteLeb128(CodeBlockTableOffset); bw.WriteLeb128(ScopeVariableTableOffset); bw.WriteLeb128(RealNameOffset); bw.WriteLeb128((int)flags); } public void ReadAll() { GetLineNumberTable(); GetLocals(); GetCodeBlocks(); GetScopeVariables(); GetRealName(); } public LineNumberTable GetLineNumberTable() { lock (SymbolFile) { if (lnt != null) { return lnt; } if (LineNumberTableOffset == 0) { return null; } MyBinaryReader binaryReader = SymbolFile.BinaryReader; long position = binaryReader.BaseStream.Position; binaryReader.BaseStream.Position = LineNumberTableOffset; lnt = LineNumberTable.Read(SymbolFile, binaryReader, (flags & Flags.ColumnsInfoIncluded) != 0, (flags & Flags.EndInfoIncluded) != 0); binaryReader.BaseStream.Position = position; return lnt; } } public LocalVariableEntry[] GetLocals() { lock (SymbolFile) { if (locals != null) { return locals; } if (LocalVariableTableOffset == 0) { return null; } MyBinaryReader binaryReader = SymbolFile.BinaryReader; long position = binaryReader.BaseStream.Position; binaryReader.BaseStream.Position = LocalVariableTableOffset; int num = binaryReader.ReadLeb128(); locals = new LocalVariableEntry[num]; for (int i = 0; i < num; i++) { locals[i] = new LocalVariableEntry(SymbolFile, binaryReader); } binaryReader.BaseStream.Position = position; return locals; } } public CodeBlockEntry[] GetCodeBlocks() { lock (SymbolFile) { if (code_blocks != null) { return code_blocks; } if (CodeBlockTableOffset == 0) { return null; } MyBinaryReader binaryReader = SymbolFile.BinaryReader; long position = binaryReader.BaseStream.Position; binaryReader.BaseStream.Position = CodeBlockTableOffset; int num = binaryReader.ReadLeb128(); code_blocks = new CodeBlockEntry[num]; for (int i = 0; i < num; i++) { code_blocks[i] = new CodeBlockEntry(i, binaryReader); } binaryReader.BaseStream.Position = position; return code_blocks; } } public ScopeVariable[] GetScopeVariables() { lock (SymbolFile) { if (scope_vars != null) { return scope_vars; } if (ScopeVariableTableOffset == 0) { return null; } MyBinaryReader binaryReader = SymbolFile.BinaryReader; long position = binaryReader.BaseStream.Position; binaryReader.BaseStream.Position = ScopeVariableTableOffset; int num = binaryReader.ReadLeb128(); scope_vars = new ScopeVariable[num]; for (int i = 0; i < num; i++) { scope_vars[i] = new ScopeVariable(binaryReader); } binaryReader.BaseStream.Position = position; return scope_vars; } } public string GetRealName() { lock (SymbolFile) { if (real_name != null) { return real_name; } if (RealNameOffset == 0) { return null; } real_name = SymbolFile.BinaryReader.ReadString(RealNameOffset); return real_name; } } public int CompareTo(object obj) { MethodEntry methodEntry = (MethodEntry)obj; if (methodEntry.Token < Token) { return 1; } if (methodEntry.Token > Token) { return -1; } return 0; } public override string ToString() { return $"[Method {index}:{Token:x}:{CompileUnitIndex}:{CompileUnit}]"; } } public struct NamespaceEntry { public readonly string Name; public readonly int Index; public readonly int Parent; public readonly string[] UsingClauses; public NamespaceEntry(string name, int index, string[] using_clauses, int parent) { Name = name; Index = index; Parent = parent; UsingClauses = ((using_clauses != null) ? using_clauses : new string[0]); } internal NamespaceEntry(MonoSymbolFile file, MyBinaryReader reader) { Name = reader.ReadString(); Index = reader.ReadLeb128(); Parent = reader.ReadLeb128(); int num = reader.ReadLeb128(); UsingClauses = new string[num]; for (int i = 0; i < num; i++) { UsingClauses[i] = reader.ReadString(); } } internal void Write(MonoSymbolFile file, MyBinaryWriter bw) { bw.Write(Name); bw.WriteLeb128(Index); bw.WriteLeb128(Parent); bw.WriteLeb128(UsingClauses.Length); string[] usingClauses = UsingClauses; foreach (string value in usingClauses) { bw.Write(value); } } public override string ToString() { return $"[Namespace {Name}:{Index}:{Parent}]"; } } public class MonoSymbolWriter { private List<SourceMethodBuilder> methods; private List<SourceFileEntry> sources; private List<CompileUnitEntry> comp_units; protected readonly MonoSymbolFile file; private string filename; private SourceMethodBuilder current_method; private Stack<SourceMethodBuilder> current_method_stack = new Stack<SourceMethodBuilder>(); public MonoSymbolFile SymbolFile => file; public MonoSymbolWriter(string filename) { methods = new List<SourceMethodBuilder>(); sources = new List<SourceFileEntry>(); comp_units = new List<CompileUnitEntry>(); file = new MonoSymbolFile(); this.filename = filename + ".mdb"; } public void CloseNamespace() { } public void DefineLocalVariable(int index, string name) { if (current_method != null) { current_method.AddLocal(index, name); } } public void DefineCapturedLocal(int scope_id, string name, string captured_name) { file.DefineCapturedVariable(scope_id, name, captured_name, CapturedVariable.CapturedKind.Local); } public void DefineCapturedParameter(int scope_id, string name, string captured_name) { file.DefineCapturedVariable(scope_id, name, captured_name, CapturedVariable.CapturedKind.Parameter); } public void DefineCapturedThis(int scope_id, string captured_name) { file.DefineCapturedVariable(scope_id, "this", captured_name, CapturedVariable.CapturedKind.This); } public void DefineCapturedScope(int scope_id, int id, string captured_name) { file.DefineCapturedScope(scope_id, id, captured_name); } public void DefineScopeVariable(int scope, int index) { if (current_method != null) { current_method.AddScopeVariable(scope, index); } } public void MarkSequencePoint(int offset, SourceFileEntry file, int line, int column, bool is_hidden) { if (current_method != null) { current_method.MarkSequencePoint(offset, file, line, column, is_hidden); } } public SourceMethodBuilder OpenMethod(ICompileUnit file, int ns_id, IMethodDef method) { SourceMethodBuilder result = new SourceMethodBuilder(file, ns_id, method); current_method_stack.Push(current_method); current_method = result; methods.Add(current_method); return result; } public void CloseMethod() { current_method = current_method_stack.Pop(); } public SourceFileEntry DefineDocument(string url) { SourceFileEntry sourceFileEntry = new SourceFileEntry(file, url); sources.Add(sourceFileEntry); return sourceFileEntry; } public SourceFileEntry DefineDocument(string url, byte[] guid, byte[] checksum) { SourceFileEntry sourceFileEntry = new SourceFileEntry(file, url, guid, checksum); sources.Add(sourceFileEntry); return sourceFileEntry; } public CompileUnitEntry DefineCompilationUnit(SourceFileEntry source) { CompileUnitEntry compileUnitEntry = new CompileUnitEntry(file, source); comp_units.Add(compileUnitEntry); return compileUnitEntry; } public int DefineNamespace(string name, CompileUnitEntry unit, string[] using_clauses, int parent) { if (unit == null || using_clauses == null) { throw new NullReferenceException(); } return unit.DefineNamespace(name, using_clauses, parent); } public int OpenScope(int start_offset) { if (current_method == null) { return 0; } current_method.StartBlock(CodeBlockEntry.Type.Lexical, start_offset); return 0; } public void CloseScope(int end_offset) { if (current_method != null) { current_method.EndBlock(end_offset); } } public void OpenCompilerGeneratedBlock(int start_offset) { if (current_method != null) { current_method.StartBlock(CodeBlockEntry.Type.CompilerGenerated, start_offset); } } public void CloseCompilerGeneratedBlock(int end_offset) { if (current_method != null) { current_method.EndBlock(end_offset); } } public void StartIteratorBody(int start_offset) { current_method.StartBlock(CodeBlockEntry.Type.IteratorBody, start_offset); } public void EndIteratorBody(int end_offset) { current_method.EndBlock(end_offset); } public void StartIteratorDispatcher(int start_offset) { current_method.StartBlock(CodeBlockEntry.Type.IteratorDispatcher, start_offset); } public void EndIteratorDispatcher(int end_offset) { current_method.EndBlock(end_offset); } public void DefineAnonymousScope(int id) { file.DefineAnonymousScope(id); } public void WriteSymbolFile(Guid guid) { foreach (SourceMethodBuilder method in methods) { method.DefineMethod(file); } try { File.Delete(filename); } catch { } using FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write); file.CreateSymbolFile(guid, fs); } } public class SourceMethodBuilder { private List<LocalVariableEntry> _locals; private List<CodeBlockEntry> _blocks; private List<ScopeVariable> _scope_vars; private Stack<CodeBlockEntry> _block_stack; private readonly List<LineNumberEntry> method_lines; private readonly ICompileUnit _comp_unit; private readonly int ns_id; private readonly IMethodDef method; public CodeBlockEntry[] Blocks { get { if (_blocks == null) { return new CodeBlockEntry[0]; } CodeBlockEntry[] array = new CodeBlockEntry[_blocks.Count]; _blocks.CopyTo(array, 0); return array; } } public CodeBlockEntry CurrentBlock { get { if (_block_stack != null && _block_stack.Count > 0) { return _block_stack.Peek(); } return null; } } public LocalVariableEntry[] Locals { get { if (_locals == null) { return new LocalVariableEntry[0]; } return _locals.ToArray(); } } public ICompileUnit SourceFile => _comp_unit; public ScopeVariable[] ScopeVariables { get { if (_scope_vars == null) { return new ScopeVariable[0]; } return _scope_vars.ToArray(); } } public SourceMethodBuilder(ICompileUnit comp_unit) { _comp_unit = comp_unit; method_lines = new List<LineNumberEntry>(); } public SourceMethodBuilder(ICompileUnit comp_unit, int ns_id, IMethodDef method) : this(comp_unit) { this.ns_id = ns_id; this.method = method; } public void MarkSequencePoint(int offset, SourceFileEntry file, int line, int column, bool is_hidden) { MarkSequencePoint(offset, file, line, column, -1, -1, is_hidden); } public void MarkSequencePoint(int offset, SourceFileEntry file, int line, int column, int end_line, int end_column, bool is_hidden) { LineNumberEntry lineNumberEntry = new LineNumberEntry(file?.Index ?? 0, line, column, end_line, end_column, offset, is_hidden); if (method_lines.Count > 0) { LineNumberEntry lineNumberEntry2 = method_lines[method_lines.Count - 1]; if (lineNumberEntry2.Offset == offset) { if (LineNumberEntry.LocationComparer.Default.Compare(lineNumberEntry, lineNumberEntry2) > 0) { method_lines[method_lines.Count - 1] = lineNumberEntry; } return; } } method_lines.Add(lineNumberEntry); } public void StartBlock(CodeBlockEntry.Type type, int start_offset) { StartBlock(type, start_offset, (_blocks == null) ? 1 : (_blocks.Count + 1)); } public void StartBlock(CodeBlockEntry.Type type, int start_offset, int scopeIndex) { if (_block_stack == null) { _block_stack = new Stack<CodeBlockEntry>(); } if (_blocks == null) { _blocks = new List<CodeBlockEntry>(); } int parent = ((CurrentBlock != null) ? CurrentBlock.Index : (-1)); CodeBlockEntry item = new CodeBlockEntry(scopeIndex, parent, type, start_offset); _block_stack.Push(item); _blocks.Add(item); } public void EndBlock(int end_offset) { _block_stack.Pop().Close(end_offset); } public void AddLocal(int index, string name) { if (_locals == null) { _locals = new List<LocalVariableEntry>(); } int block = ((CurrentBlock != null) ? CurrentBlock.Index : 0); _locals.Add(new LocalVariableEntry(index, name, block)); } public void AddScopeVariable(int scope, int index) { if (_scope_vars == null) { _scope_vars = new List<ScopeVariable>(); } _scope_vars.Add(new ScopeVariable(scope, index)); } public void DefineMethod(MonoSymbolFile file) { DefineMethod(file, method.Token); } public void DefineMethod(MonoSymbolFile file, int token) { CodeBlockEntry[] array = Blocks; if (array.Length != 0) { List<CodeBlockEntry> list = new List<CodeBlockEntry>(array.Length); int num = 0; for (int i = 0; i < array.Length; i++) { num = Math.Max(num, array[i].Index); } for (int j = 0; j < num; j++) { int num2 = j + 1; if (j < array.Length && array[j].Index == num2) { list.Add(array[j]); continue; } bool flag = false; for (int k = 0; k < array.Length; k++) { if (array[k].Index == num2) { list.Add(array[k]); flag = true; break; } } if (!flag) { list.Add(new CodeBlockEntry(num2, -1, CodeBlockEntry.Type.CompilerGenerated, 0)); } } array = list.ToArray(); } MethodEntry entry = new MethodEntry(file, _comp_unit.Entry, token, ScopeVariables, Locals, method_lines.ToArray(), array, null, MethodEntry.Flags.ColumnsInfoIncluded, ns_id); file.AddMethod(entry); } } public class SymbolWriterImpl : ISymbolWriter { private MonoSymbolWriter msw; private int nextLocalIndex; private int currentToken; private string methodName; private Stack namespaceStack = new Stack(); private bool methodOpened; private Hashtable documents = new Hashtable(); private Guid guid; public SymbolWriterImpl(Guid guid) { this.guid = guid; } public void Close() { msw.WriteSymbolFile(guid); } public void CloseMethod() { if (methodOpened) { methodOpened = false; nextLocalIndex = 0; msw.CloseMethod(); } } public void CloseNamespace() { namespaceStack.Pop(); msw.CloseNamespace(); } public void CloseScope(int endOffset) { msw.CloseScope(endOffset); } public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) { SymbolDocumentWriterImpl symbolDocumentWriterImpl = (SymbolDocumentWriterImpl)documents[url]; if (symbolDocumentWriterImpl == null) { SourceFileEntry source = msw.DefineDocument(url); symbolDocumentWriterImpl = new SymbolDocumentWriterImpl(msw.DefineCompilationUnit(source)); documents[url] = symbolDocumentWriterImpl; } return symbolDocumentWriterImpl; } public void DefineField(SymbolToken parent, string name, FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3) { } public void DefineGlobalVariable(string name, FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3) { } public void DefineLocalVariable(string name, FieldAttributes attributes, byte[] signature, SymAddressKind addrKind, int addr1, int addr2, int addr3, int startOffset, int endOffset) { msw.DefineLocalVariable(nextLocalIndex++, name); } public void DefineParameter(string name, ParameterAttributes attributes, int sequence, SymAddressKind addrKind, int addr1, int addr2, int addr3) { } public void DefineSequencePoints(ISymbolDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns) { SourceFileEntry file = ((SymbolDocumentWriterImpl)document)?.Entry.SourceFile; for (int i = 0; i < offsets.Length; i++) { if (i <= 0 || offsets[i] != offsets[i - 1] || lines[i] != lines[i - 1] || columns[i] != columns[i - 1]) { msw.MarkSequencePoint(offsets[i], file, lines[i], columns[i], is_hidden: false); } } } public void Initialize(IntPtr emitter, string filename, bool fFullBuild) { msw = new MonoSymbolWriter(filename); } public void OpenMethod(SymbolToken method) { currentToken = method.GetToken(); } public void OpenNamespace(string name) { NamespaceInfo namespaceInfo = new NamespaceInfo(); namespaceInfo.NamespaceID = -1; namespaceInfo.Name = name; namespaceStack.Push(namespaceInfo); } public int OpenScope(int startOffset) { return msw.OpenScope(startOffset); } public void SetMethodSourceRange(ISymbolDocumentWriter startDoc, int startLine, int startColumn, ISymbolDocumentWriter endDoc, int endLine, int endColumn) { int currentNamespace = GetCurrentNamespace(startDoc); SourceMethodImpl method = new SourceMethodImpl(methodName, currentToken, currentNamespace); msw.OpenMethod(((ICompileUnit)startDoc).Entry, currentNamespace, method); methodOpened = true; } public void SetScopeRange(int scopeID, int startOffset, int endOffset) { } public void SetSymAttribute(SymbolToken parent, string name, byte[] data) { if (name == "__name") { methodName = Encoding.UTF8.GetString(data); } } public void SetUnderlyingWriter(IntPtr underlyingWriter) { } public void SetUserEntryPoint(SymbolToken entryMethod) { } public void UsingNamespace(string fullName) { if (namespaceStack.Count == 0) { OpenNamespace(""); } NamespaceInfo namespaceInfo = (NamespaceInfo)namespaceStack.Peek(); if (namespaceInfo.NamespaceID != -1) { NamespaceInfo namespaceInfo2 = namespaceInfo; CloseNamespace(); OpenNamespace(namespaceInfo2.Name); namespaceInfo = (NamespaceInfo)namespaceStack.Peek(); namespaceInfo.UsingClauses = namespaceInfo2.UsingClauses; } namespaceInfo.UsingClauses.Add(fullName); } private int GetCurrentNamespace(ISymbolDocumentWriter doc) { if (namespaceStack.Count == 0) { OpenNamespace(""); } NamespaceInfo namespaceInfo = (NamespaceInfo)namespaceStack.Peek(); if (namespaceInfo.NamespaceID == -1) { string[] using_clauses = (string[])namespaceInfo.UsingClauses.ToArray(typeof(string)); int parent = 0; if (namespaceStack.Count > 1) { namespaceStack.Pop(); parent = ((NamespaceInfo)namespaceStack.Peek()).NamespaceID; namespaceStack.Push(namespaceInfo); } namespaceInfo.NamespaceID = msw.DefineNamespace(namespaceInfo.Name, ((ICompileUnit)doc).Entry, using_clauses, parent); } return namespaceInfo.NamespaceID; } } internal class SymbolDocumentWriterImpl : ISymbolDocumentWriter, ISourceFile, ICompileUnit { private CompileUnitEntry comp_unit; SourceFileEntry ISourceFile.Entry => comp_unit.SourceFile; public CompileUnitEntry Entry => comp_unit; public SymbolDocumentWriterImpl(CompileUnitEntry comp_unit) { this.comp_unit = comp_unit; } public void SetCheckSum(Guid algorithmId, byte[] checkSum) { } public void SetSource(byte[] source) { } } internal class SourceMethodImpl : IMethodDef { private string name; private int token; private int namespaceID; public string Name => name; public int NamespaceID => namespaceID; public int Token => token; public SourceMethodImpl(string name, int token, int namespaceID) { this.name = name; this.token = token; this.namespaceID = namespaceID; } } internal class NamespaceInfo { public string Name; public int NamespaceID; public ArrayList UsingClauses = new ArrayList(); } } namespace Mono.Cecil.Mdb { public sealed class MdbReaderProvider : ISymbolReaderProvider { public ISymbolReader GetSymbolReader(ModuleDefinition module, string fileName) { Mixin.CheckModule(module); Mixin.CheckFileName(fileName); return (ISymbolReader)(object)new MdbReader(module, MonoSymbolFile.ReadSymbolFile(Mixin.GetMdbFileName(fileName))); } public ISymbolReader GetSymbolReader(ModuleDefinition module, Stream symbolStream) { Mixin.CheckModule(module); Mixin.CheckStream((object)symbolStream); return (ISymbolReader)(object)new MdbReader(module, MonoSymbolFile.ReadSymbolFile(symbolStream)); } } public sealed class MdbReader : ISymbolReader, IDisposable { private readonly ModuleDefinition module; private readonly MonoSymbolFile symbol_file; private readonly Dictionary<string, Document> documents; public MdbReader(ModuleDefinition module, MonoSymbolFile symFile) { this.module = module; symbol_file = symFile; documents = new Dictionary<string, Document>(); } public ISymbolWriterProvider GetWriterProvider() { return (ISymbolWriterProvider)(object)new MdbWriterProvider(); } public bool ProcessDebugHeader(ImageDebugHeader header) { return symbol_file.Guid == module.Mvid; } public MethodDebugInformation Read(MethodDefinition method) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown MetadataToken metadataToken = ((MemberReference)method).MetadataToken; MethodEntry methodByToken = symbol_file.GetMethodByToken(((MetadataToken)(ref metadataToken)).ToInt32()); if (methodByToken == null) { return null; } MethodDebugInformation val = new MethodDebugInformation(method); val.code_size = ReadCodeSize(method); ScopeDebugInformation[] scopes = ReadScopes(methodByToken, val); ReadLineNumbers(methodByToken, val); ReadLocalVariables(methodByToken, scopes); return val; } private static int ReadCodeSize(MethodDefinition method) { return ((MemberReference)method).Module.Read<MethodDefinition, int>(method, (Func<MethodDefinition, MetadataReader, int>)((MethodDefinition m, MetadataReader reader) => reader.ReadCodeSize(m))); } private static void ReadLocalVariables(MethodEntry entry, ScopeDebugInformation[] scopes) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown LocalVariableEntry[] locals = entry.GetLocals(); for (int i = 0; i < locals.Length; i++) { LocalVariableEntry localVariableEntry = locals[i]; VariableDebugInformation val = new VariableDebugInformation(localVariableEntry.Index, localVariableEntry.Name); int blockIndex = localVariableEntry.BlockIndex; if (blockIndex >= 0 && blockIndex < scopes.Length) { ScopeDebugInformation val2 = scopes[blockIndex]; if (val2 != null) { val2.Variables.Add(val); } } } } private void ReadLineNumbers(MethodEntry entry, MethodDebugInformation info) { LineNumberTable lineNumberTable = entry.GetLineNumberTable(); info.sequence_points = new Collection<SequencePoint>(lineNumberTable.LineNumbers.Length); for (int i = 0; i < lineNumberTable.LineNumbers.Length; i++) { LineNumberEntry lineNumberEntry = lineNumberTable.LineNumbers[i]; if (i <= 0 || lineNumberTable.LineNumbers[i - 1].Offset != lineNumberEntry.Offset) { info.sequence_points.Add(LineToSequencePoint(lineNumberEntry)); } } } private Document GetDocument(SourceFileEntry file) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown string fileName = file.FileName; if (documents.TryGetValue(fileName, out var value)) { return value; } value = new Document(fileName) { Hash = file.Checksum }; documents.Add(fileName, value); return value; } private static ScopeDebugInformation[] ReadScopes(MethodEntry entry, MethodDebugInformation info) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0039: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) CodeBlockEntry[] codeBlocks = entry.GetCodeBlocks(); ScopeDebugInformation[] array = (ScopeDebugInformation[])(object)new ScopeDebugInformation[codeBlocks.Length + 1]; ScopeDebugInformation val = new ScopeDebugInformation { Start = new InstructionOffset(0), End = new InstructionOffset(info.code_size) }; ScopeDebugInformation scope = val; array[0] = val; info.scope = scope; CodeBlockEntry[] array2 = codeBlocks; foreach (CodeBlockEntry codeBlockEntry in array2) { if (codeBlockEntry.BlockType == CodeBlockEntry.Type.Lexical || codeBlockEntry.BlockType == CodeBlockEntry.Type.CompilerGenerated) { ScopeDebugInformation val2 = new ScopeDebugInformation(); val2.Start = new InstructionOffset(codeBlockEntry.StartOffset); val2.End = new InstructionOffset(codeBlockEntry.EndOffset); array[codeBlockEntry.Index + 1] = val2; if (!AddScope(info.scope.Scopes, val2)) { info.scope.Scopes.Add(val2); } } } return array; } private static bool AddScope(Collection<ScopeDebugInformation> scopes, ScopeDebugInformation scope) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Enumerator<ScopeDebugInformation> enumerator = scopes.GetEnumerator(); try { while (enumerator.MoveNext()) { ScopeDebugInformation current = enumerator.Current; if (current.HasScopes && AddScope(current.Scopes, scope)) { return true; } InstructionOffset val = scope.Start; int offset = ((InstructionOffset)(ref val)).Offset; val = current.Start; if (offset >= ((InstructionOffset)(ref val)).Offset) { val = scope.End; int offset2 = ((InstructionOffset)(ref val)).Offset; val = current.End; if (offset2 <= ((InstructionOffset)(ref val)).Offset) { current.Scopes.Add(scope); return true; } } } } finally { ((IDisposable)enumerator).Dispose(); } return false; } private SequencePoint LineToSequencePoint(LineNumberEntry line) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown SourceFileEntry sourceFile = symbol_file.GetSourceFile(line.File); return new SequencePoint(line.Offset, GetDocument(sourceFile)) { StartLine = line.Row, EndLine = line.EndRow, StartColumn = line.Column, EndColumn = line.EndColumn }; } public void Dispose() { symbol_file.Dispose(); } } internal static class MethodEntryExtensions { public static bool HasColumnInfo(this MethodEntry entry) { return (entry.MethodFlags & MethodEntry.Flags.ColumnsInfoIncluded) != 0; } public static bool HasEndInfo(this MethodEntry entry) { return (entry.MethodFlags & MethodEntry.Flags.EndInfoIncluded) != 0; } } public sealed class MdbWriterProvider : ISymbolWriterProvider { public ISymbolWriter GetSymbolWriter(ModuleDefinition module, string fileName) { Mixin.CheckModule(module); Mixin.CheckFileName(fileName); return (ISymbolWriter)(object)new MdbWriter(module.Mvid, fileName); } public ISymbolWriter GetSymbolWriter(ModuleDefinition module, Stream symbolStream) { throw new NotImplementedException(); } } public sealed class MdbWriter : ISymbolWriter, IDisposable { private class SourceFile : ISourceFile { private readonly CompileUnitEntry compilation_unit; private readonly SourceFileEntry entry; public SourceFileEntry Entry => entry; public CompileUnitEntry CompilationUnit => compilation_unit; public SourceFile(CompileUnitEntry comp_unit, SourceFileEntry entry) { compilation_unit = comp_unit; this.entry = entry; } } private class SourceMethod : IMethodDef { private readonly MethodDefinition method; public string Name => ((MemberReference)method).Name; public int Token { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) MetadataToken metadataToken = ((MemberReference)method).MetadataToken; return ((MetadataToken)(ref metadataToken)).ToInt32(); } } public SourceMethod(MethodDefinition method) { this.method = method; } } private readonly Guid mvid; private readonly MonoSymbolWriter writer; private readonly Dictionary<string, SourceFile> source_files; public MdbWriter(Guid mvid, string assembly) { this.mvid = mvid; writer = new MonoSymbolWriter(assembly); source_files = new Dictionary<string, SourceFile>(); } public ISymbolReaderProvider GetReaderProvider() { return (ISymbolReaderProvider)(object)new MdbReaderProvider(); } private SourceFile GetSourceFile(Document document) { string url = document.Url; if (source_files.TryGetValue(url, out var value)) { return value; } SourceFileEntry sourceFileEntry = writer.DefineDocument(url, null, (document.Hash != null && document.Hash.Length == 16) ? document.Hash : null); value = new SourceFile(writer.DefineCompilationUnit(sourceFileEntry), sourceFileEntry); source_files.Add(url, value); return value; } private void Populate(Collection<SequencePoint> sequencePoints, int[] offsets, int[] startRows, int[] endRows, int[] startCols, int[] endCols, out SourceFile file) { SourceFile sourceFile = null; for (int i = 0; i < sequencePoints.Count; i++) { SequencePoint val = sequencePoints[i]; offsets[i] = val.Offset; if (sourceFile == null) { sourceFile = GetSourceFile(val.Document); } startRows[i] = val.StartLine; endRows[i] = val.EndLine; startCols[i] = val.StartColumn; endCols[i] = val.EndColumn; } file = sourceFile; } public void Write(MethodDebugInformation info) { SourceMethod method = new SourceMethod(info.method); Collection<SequencePoint> sequencePoints = info.SequencePoints; int count = sequencePoints.Count; if (count != 0) { int[] array = new int[count]; int[] array2 = new int[count]; int[] array3 = new int[count]; int[] array4 = new int[count]; int[] array5 = new int[count]; Populate(sequencePoints, array, array2, array3, array4, array5, out var file); SourceMethodBuilder sourceMethodBuilder = writer.OpenMethod(file.CompilationUnit, 0, method); for (int i = 0; i < count; i++) { sourceMethodBuilder.MarkSequencePoint(array[i], file.CompilationUnit.SourceFile, array2[i], array4[i], array3[i], array5[i], is_hidden: false); } if (info.scope != null) { WriteRootScope(info.scope, info); } writer.CloseMethod(); } } private void WriteRootScope(ScopeDebugInformation scope, MethodDebugInformation info) { WriteScopeVariables(scope); if (scope.HasScopes) { WriteScopes(scope.Scopes, info); } } private void WriteScope(ScopeDebugInformation scope, MethodDebugInformation info) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) MonoSymbolWriter monoSymbolWriter = writer; InstructionOffset val = scope.Start; monoSymbolWriter.OpenScope(((InstructionOffset)(ref val)).Offset); WriteScopeVariables(scope); if (scope.HasScopes) { WriteScopes(scope.Scopes, info); } MonoSymbolWriter monoSymbolWriter2 = writer; val = scope.End; int end_offset; if (!((InstructionOffset)(ref val)).IsEndOfMethod) { val = scope.End; end_offset = ((InstructionOffset)(ref val)).Offset; } else { end_offset = info.code_size; } monoSymbolWriter2.CloseScope(end_offset); } private void WriteScopes(Collection<ScopeDebugInformation> scopes, MethodDebugInformation info) { for (int i = 0; i < scopes.Count; i++) { WriteScope(scopes[i], info); } } private void WriteScopeVariables(ScopeDebugInformation scope) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!scope.HasVariables) { return; } Enumerator<VariableDebugInformation> enumerator = scope.variables.GetEnumerator(); try { while (enumerator.MoveNext()) { VariableDebugInformation current = enumerator.Current; if (!string.IsNullOrEmpty(current.Name)) { writer.DefineLocalVariable(current.Index, current.Name); } } } finally { ((IDisposable)enumerator).Dispose(); } } public ImageDebugHeader GetDebugHeader() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new ImageDebugHeader(); } public void Dispose() { writer.WriteSymbolFile(mvid); } } }
BepInEx/core/Mono.Cecil.Pdb.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Text; using Microsoft.Cci; using Microsoft.Cci.Pdb; using Mono.Cecil.Cil; using Mono.Cecil.PE; using Mono.Collections.Generic; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyProduct("Mono.Cecil")] [assembly: AssemblyCopyright("Copyright © 2008 - 2018 Jb Evain")] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("0.10.4.0")] [assembly: AssemblyInformationalVersion("0.10.4.0")] [assembly: AssemblyTitle("Mono.Cecil.Pdb")] [assembly: CLSCompliant(false)] [assembly: AssemblyVersion("0.10.4.0")] namespace Mono.Cecil.Pdb { [ComImport] [Guid("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedDocumentWriter { } [ComImport] [Guid("0B97726E-9E6D-4f05-9A26-424022093CAA")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISymUnmanagedWriter2 { void DefineDocument([In][MarshalAs(UnmanagedType.LPWStr)] string url, [In] ref Guid langauge, [In] ref Guid languageVendor, [In] ref Guid documentType, [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedDocumentWriter pRetVal); void SetUserEntryPoint([In] int methodToken); void OpenMethod([In] int methodToken); void CloseMethod(); void OpenScope([In] int startOffset, out int pRetVal); void CloseScope([In] int endOffset); void SetScopeRange_Placeholder(); void DefineLocalVariable_Placeholder(); void DefineParameter_Placeholder(); void DefineField_Placeholder(); void DefineGlobalVariable_Placeholder(); void Close(); void SetSymAttribute(uint parent, string name, uint data, IntPtr signature); void OpenNamespace([In][MarshalAs(UnmanagedType.LPWStr)] string name); void CloseNamespace(); void UsingNamespace([In][MarshalAs(UnmanagedType.LPWStr)] string fullName); void SetMethodSourceRange_Placeholder(); void Initialize([In][MarshalAs(UnmanagedType.IUnknown)] object emitter, [In][MarshalAs(UnmanagedType.LPWStr)] string filename, [In] IStream pIStream, [In] bool fFullBuild); void GetDebugInfo(out ImageDebugDirectory pIDD, [In] int cData, out int pcData, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data); void DefineSequencePoints([In][MarshalAs(UnmanagedType.Interface)] ISymUnmanagedDocumentWriter document, [In] int spCount, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] offsets, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] lines, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] columns, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endLines, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] endColumns); void RemapToken_Placeholder(); void Initialize2_Placeholder(); void DefineConstant_Placeholder(); void Abort_Placeholder(); void DefineLocalVariable2([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In] int attributes, [In] int sigToken, [In] int addrKind, [In] int addr1, [In] int addr2, [In] int addr3, [In] int startOffset, [In] int endOffset); void DefineGlobalVariable2_Placeholder(); void DefineConstant2([In][MarshalAs(UnmanagedType.LPWStr)] string name, [In][MarshalAs(UnmanagedType.Struct)] object variant, [In] int sigToken); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("BA3FEE4C-ECB9-4e41-83B7-183FA41CD859")] internal interface IMetaDataEmit { void SetModuleProps(string szName); void Save(string szFile, uint dwSaveFlags); void SaveToStream(IntPtr pIStream, uint dwSaveFlags); uint GetSaveSize(uint fSave); uint DefineTypeDef(IntPtr szTypeDef, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements); uint DefineNestedType(IntPtr szTypeDef, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements, uint tdEncloser); void SetHandler([In][MarshalAs(UnmanagedType.IUnknown)] object pUnk); uint DefineMethod(uint td, IntPtr zName, uint dwMethodFlags, IntPtr pvSigBlob, uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags); void DefineMethodImpl(uint td, uint tkBody, uint tkDecl); uint DefineTypeRefByName(uint tkResolutionScope, IntPtr szName); uint DefineImportType(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint tdImport, IntPtr pAssemEmit); uint DefineMemberRef(uint tkImport, string szName, IntPtr pvSigBlob, uint cbSigBlob); uint DefineImportMember(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint mbMember, IntPtr pAssemEmit, uint tkParent); uint DefineEvent(uint td, string szEvent, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, IntPtr rmdOtherMethods); void SetClassLayout(uint td, uint dwPackSize, IntPtr rFieldOffsets, uint ulClassSize); void DeleteClassLayout(uint td); void SetFieldMarshal(uint tk, IntPtr pvNativeType, uint cbNativeType); void DeleteFieldMarshal(uint tk); uint DefinePermissionSet(uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission); void SetRVA(uint md, uint ulRVA); uint GetTokenFromSig(IntPtr pvSig, uint cbSig); uint DefineModuleRef(string szName); void SetParent(uint mr, uint tk); uint GetTokenFromTypeSpec(IntPtr pvSig, uint cbSig); void SaveToMemory(IntPtr pbData, uint cbData); uint DefineUserString(string szString, uint cchString); void DeleteToken(uint tkObj); void SetMethodProps(uint md, uint dwMethodFlags, uint ulCodeRVA, uint dwImplFlags); void SetTypeDefProps(uint td, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements); void SetEventProps(uint ev, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, IntPtr rmdOtherMethods); uint SetPermissionSetProps(uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission); void DefinePinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL); void SetPinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL); void DeletePinvokeMap(uint tk); uint DefineCustomAttribute(uint tkObj, uint tkType, IntPtr pCustomAttribute, uint cbCustomAttribute); void SetCustomAttributeValue(uint pcv, IntPtr pCustomAttribute, uint cbCustomAttribute); uint DefineField(uint td, string szName, uint dwFieldFlags, IntPtr pvSigBlob, uint cbSigBlob, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue); uint DefineProperty(uint td, string szProperty, uint dwPropFlags, IntPtr pvSig, uint cbSig, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, IntPtr rmdOtherMethods); uint DefineParam(uint md, uint ulParamSeq, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue); void SetFieldProps(uint fd, uint dwFieldFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue); void SetPropertyProps(uint pr, uint dwPropFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, IntPtr rmdOtherMethods); void SetParamProps(uint pd, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue); uint DefineSecurityAttributeSet(uint tkObj, IntPtr rSecAttrs, uint cSecAttrs); void ApplyEditAndContinue([MarshalAs(UnmanagedType.IUnknown)] object pImport); uint TranslateSigWithScope(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport import, IntPtr pbSigBlob, uint cbSigBlob, IntPtr pAssemEmit, IMetaDataEmit emit, IntPtr pvTranslatedSig, uint cbTranslatedSigMax); void SetMethodImplFlags(uint md, uint dwImplFlags); void SetFieldRVA(uint fd, uint ulRVA); void Merge(IMetaDataImport pImport, IntPtr pHostMapToken, [MarshalAs(UnmanagedType.IUnknown)] object pHandler); void MergeEnd(); } [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("7DAC8207-D3AE-4c75-9B67-92801A497D44")] internal interface IMetaDataImport { [PreserveSig] void CloseEnum(uint hEnum); uint CountEnum(uint hEnum); void ResetEnum(uint hEnum, uint ulPos); uint EnumTypeDefs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rTypeDefs, uint cMax); uint EnumInterfaceImpls(ref uint phEnum, uint td, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rImpls, uint cMax); uint EnumTypeRefs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rTypeRefs, uint cMax); uint FindTypeDefByName(string szTypeDef, uint tkEnclosingClass); Guid GetScopeProps(StringBuilder szName, uint cchName, out uint pchName); uint GetModuleFromScope(); uint GetTypeDefProps(uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags); uint GetInterfaceImplProps(uint iiImpl, out uint pClass); uint GetTypeRefProps(uint tr, out uint ptkResolutionScope, StringBuilder szName, uint cchName); uint ResolveTypeRef(uint tr, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppIScope); uint EnumMembers(ref uint phEnum, uint cl, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rMembers, uint cMax); uint EnumMembersWithName(ref uint phEnum, uint cl, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMembers, uint cMax); uint EnumMethods(ref uint phEnum, uint cl, IntPtr rMethods, uint cMax); uint EnumMethodsWithName(ref uint phEnum, uint cl, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMethods, uint cMax); uint EnumFields(ref uint phEnum, uint cl, IntPtr rFields, uint cMax); uint EnumFieldsWithName(ref uint phEnum, uint cl, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rFields, uint cMax); uint EnumParams(ref uint phEnum, uint mb, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rParams, uint cMax); uint EnumMemberRefs(ref uint phEnum, uint tkParent, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rMemberRefs, uint cMax); uint EnumMethodImpls(ref uint phEnum, uint td, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMethodBody, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rMethodDecl, uint cMax); uint EnumPermissionSets(ref uint phEnum, uint tk, uint dwActions, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rPermission, uint cMax); uint FindMember(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob); uint FindMethod(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob); uint FindField(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob); uint FindMemberRef(uint td, string szName, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSigBlob, uint cbSigBlob); uint GetMethodProps(uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA); uint GetMemberRefProps(uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out IntPtr ppvSigBlob); uint EnumProperties(ref uint phEnum, uint td, IntPtr rProperties, uint cMax); uint EnumEvents(ref uint phEnum, uint td, IntPtr rEvents, uint cMax); uint GetEventProps(uint ev, out uint pClass, StringBuilder szEvent, uint cchEvent, out uint pchEvent, out uint pdwEventFlags, out uint ptkEventType, out uint pmdAddOn, out uint pmdRemoveOn, out uint pmdFire, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 11)] uint[] rmdOtherMethod, uint cMax); uint EnumMethodSemantics(ref uint phEnum, uint mb, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] uint[] rEventProp, uint cMax); uint GetMethodSemantics(uint mb, uint tkEventProp); uint GetClassLayout(uint td, out uint pdwPackSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] IntPtr rFieldOffset, uint cMax, out uint pcFieldOffset); uint GetFieldMarshal(uint tk, out IntPtr ppvNativeType); uint GetRVA(uint tk, out uint pulCodeRVA); uint GetPermissionSetProps(uint pm, out uint pdwAction, out IntPtr ppvPermission); uint GetSigFromToken(uint mdSig, out IntPtr ppvSig); uint GetModuleRefProps(uint mur, StringBuilder szName, uint cchName); uint EnumModuleRefs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rModuleRefs, uint cmax); uint GetTypeSpecFromToken(uint typespec, out IntPtr ppvSig); uint GetNameFromToken(uint tk); uint EnumUnresolvedMethods(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rMethods, uint cMax); uint GetUserString(uint stk, StringBuilder szString, uint cchString); uint GetPinvokeMap(uint tk, out uint pdwMappingFlags, StringBuilder szImportName, uint cchImportName, out uint pchImportName); uint EnumSignatures(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rSignatures, uint cmax); uint EnumTypeSpecs(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rTypeSpecs, uint cmax); uint EnumUserStrings(ref uint phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rStrings, uint cmax); [PreserveSig] int GetParamForMethodIndex(uint md, uint ulParamSeq, out uint pParam); uint EnumCustomAttributes(ref uint phEnum, uint tk, uint tkType, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] rCustomAttributes, uint cMax); uint GetCustomAttributeProps(uint cv, out uint ptkObj, out uint ptkType, out IntPtr ppBlob); uint FindTypeRef(uint tkResolutionScope, string szName); uint GetMemberProps(uint mb, out uint pClass, StringBuilder szMember, uint cchMember, out uint pchMember, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pulCodeRVA, out uint pdwImplFlags, out uint pdwCPlusTypeFlag, out IntPtr ppValue); uint GetFieldProps(uint mb, out uint pClass, StringBuilder szField, uint cchField, out uint pchField, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pdwCPlusTypeFlag, out IntPtr ppValue); uint GetPropertyProps(uint prop, out uint pClass, StringBuilder szProperty, uint cchProperty, out uint pchProperty, out uint pdwPropFlags, out IntPtr ppvSig, out uint pbSig, out uint pdwCPlusTypeFlag, out IntPtr ppDefaultValue, out uint pcchDefaultValue, out uint pmdSetter, out uint pmdGetter, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 14)] uint[] rmdOtherMethod, uint cMax); uint GetParamProps(uint tk, out uint pmd, out uint pulSequence, StringBuilder szName, uint cchName, out uint pchName, out uint pdwAttr, out uint pdwCPlusTypeFlag, out IntPtr ppValue); uint GetCustomAttributeByName(uint tkObj, string szName, out IntPtr ppData); [PreserveSig] [return: MarshalAs(UnmanagedType.Bool)] bool IsValidToken(uint tk); uint GetNestedClassProps(uint tdNestedClass); uint GetNativeCallConvFromSig(IntPtr pvSig, uint cbSig); int IsGlobal(uint pd); } internal class ModuleMetadata : IMetaDataEmit, IMetaDataImport { private readonly ModuleDefinition module; private Dictionary<uint, TypeDefinition> types; private Dictionary<uint, MethodDefinition> methods; public ModuleMetadata(ModuleDefinition module) { this.module = module; } private bool TryGetType(uint token, out TypeDefinition type) { if (types == null) { InitializeMetadata(module); } return types.TryGetValue(token, out type); } private bool TryGetMethod(uint token, out MethodDefinition method) { if (methods == null) { InitializeMetadata(module); } return methods.TryGetValue(token, out method); } private void InitializeMetadata(ModuleDefinition module) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) types = new Dictionary<uint, TypeDefinition>(); methods = new Dictionary<uint, MethodDefinition>(); foreach (TypeDefinition type in module.GetTypes()) { Dictionary<uint, TypeDefinition> dictionary = types; MetadataToken metadataToken = ((MemberReference)type).MetadataToken; dictionary.Add(((MetadataToken)(ref metadataToken)).ToUInt32(), type); InitializeMethods(type); } } private void InitializeMethods(TypeDefinition type) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator(); try { while (enumerator.MoveNext()) { MethodDefinition current = enumerator.Current; Dictionary<uint, MethodDefinition> dictionary = methods; MetadataToken metadataToken = ((MemberReference)current).MetadataToken; dictionary.Add(((MetadataToken)(ref metadataToken)).ToUInt32(), current); } } finally { ((IDisposable)enumerator).Dispose(); } } public void SetModuleProps(string szName) { throw new NotImplementedException(); } public void Save(string szFile, uint dwSaveFlags) { throw new NotImplementedException(); } public void SaveToStream(IntPtr pIStream, uint dwSaveFlags) { throw new NotImplementedException(); } public uint GetSaveSize(uint fSave) { throw new NotImplementedException(); } public uint DefineTypeDef(IntPtr szTypeDef, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements) { throw new NotImplementedException(); } public uint DefineNestedType(IntPtr szTypeDef, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements, uint tdEncloser) { throw new NotImplementedException(); } public void SetHandler(object pUnk) { throw new NotImplementedException(); } public uint DefineMethod(uint td, IntPtr zName, uint dwMethodFlags, IntPtr pvSigBlob, uint cbSigBlob, uint ulCodeRVA, uint dwImplFlags) { throw new NotImplementedException(); } public void DefineMethodImpl(uint td, uint tkBody, uint tkDecl) { throw new NotImplementedException(); } public uint DefineTypeRefByName(uint tkResolutionScope, IntPtr szName) { throw new NotImplementedException(); } public uint DefineImportType(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint tdImport, IntPtr pAssemEmit) { throw new NotImplementedException(); } public uint DefineMemberRef(uint tkImport, string szName, IntPtr pvSigBlob, uint cbSigBlob) { throw new NotImplementedException(); } public uint DefineImportMember(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport pImport, uint mbMember, IntPtr pAssemEmit, uint tkParent) { throw new NotImplementedException(); } public uint DefineEvent(uint td, string szEvent, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, IntPtr rmdOtherMethods) { throw new NotImplementedException(); } public void SetClassLayout(uint td, uint dwPackSize, IntPtr rFieldOffsets, uint ulClassSize) { throw new NotImplementedException(); } public void DeleteClassLayout(uint td) { throw new NotImplementedException(); } public void SetFieldMarshal(uint tk, IntPtr pvNativeType, uint cbNativeType) { throw new NotImplementedException(); } public void DeleteFieldMarshal(uint tk) { throw new NotImplementedException(); } public uint DefinePermissionSet(uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission) { throw new NotImplementedException(); } public void SetRVA(uint md, uint ulRVA) { throw new NotImplementedException(); } public uint GetTokenFromSig(IntPtr pvSig, uint cbSig) { throw new NotImplementedException(); } public uint DefineModuleRef(string szName) { throw new NotImplementedException(); } public void SetParent(uint mr, uint tk) { throw new NotImplementedException(); } public uint GetTokenFromTypeSpec(IntPtr pvSig, uint cbSig) { throw new NotImplementedException(); } public void SaveToMemory(IntPtr pbData, uint cbData) { throw new NotImplementedException(); } public uint DefineUserString(string szString, uint cchString) { throw new NotImplementedException(); } public void DeleteToken(uint tkObj) { throw new NotImplementedException(); } public void SetMethodProps(uint md, uint dwMethodFlags, uint ulCodeRVA, uint dwImplFlags) { throw new NotImplementedException(); } public void SetTypeDefProps(uint td, uint dwTypeDefFlags, uint tkExtends, IntPtr rtkImplements) { throw new NotImplementedException(); } public void SetEventProps(uint ev, uint dwEventFlags, uint tkEventType, uint mdAddOn, uint mdRemoveOn, uint mdFire, IntPtr rmdOtherMethods) { throw new NotImplementedException(); } public uint SetPermissionSetProps(uint tk, uint dwAction, IntPtr pvPermission, uint cbPermission) { throw new NotImplementedException(); } public void DefinePinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL) { throw new NotImplementedException(); } public void SetPinvokeMap(uint tk, uint dwMappingFlags, string szImportName, uint mrImportDLL) { throw new NotImplementedException(); } public void DeletePinvokeMap(uint tk) { throw new NotImplementedException(); } public uint DefineCustomAttribute(uint tkObj, uint tkType, IntPtr pCustomAttribute, uint cbCustomAttribute) { throw new NotImplementedException(); } public void SetCustomAttributeValue(uint pcv, IntPtr pCustomAttribute, uint cbCustomAttribute) { throw new NotImplementedException(); } public uint DefineField(uint td, string szName, uint dwFieldFlags, IntPtr pvSigBlob, uint cbSigBlob, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) { throw new NotImplementedException(); } public uint DefineProperty(uint td, string szProperty, uint dwPropFlags, IntPtr pvSig, uint cbSig, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, IntPtr rmdOtherMethods) { throw new NotImplementedException(); } public uint DefineParam(uint md, uint ulParamSeq, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) { throw new NotImplementedException(); } public void SetFieldProps(uint fd, uint dwFieldFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) { throw new NotImplementedException(); } public void SetPropertyProps(uint pr, uint dwPropFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue, uint mdSetter, uint mdGetter, IntPtr rmdOtherMethods) { throw new NotImplementedException(); } public void SetParamProps(uint pd, string szName, uint dwParamFlags, uint dwCPlusTypeFlag, IntPtr pValue, uint cchValue) { throw new NotImplementedException(); } public uint DefineSecurityAttributeSet(uint tkObj, IntPtr rSecAttrs, uint cSecAttrs) { throw new NotImplementedException(); } public void ApplyEditAndContinue(object pImport) { throw new NotImplementedException(); } public uint TranslateSigWithScope(IntPtr pAssemImport, IntPtr pbHashValue, uint cbHashValue, IMetaDataImport import, IntPtr pbSigBlob, uint cbSigBlob, IntPtr pAssemEmit, IMetaDataEmit emit, IntPtr pvTranslatedSig, uint cbTranslatedSigMax) { throw new NotImplementedException(); } public void SetMethodImplFlags(uint md, uint dwImplFlags) { throw new NotImplementedException(); } public void SetFieldRVA(uint fd, uint ulRVA) { throw new NotImplementedException(); } public void Merge(IMetaDataImport pImport, IntPtr pHostMapToken, object pHandler) { throw new NotImplementedException(); } public void MergeEnd() { throw new NotImplementedException(); } public void CloseEnum(uint hEnum) { throw new NotImplementedException(); } public uint CountEnum(uint hEnum) { throw new NotImplementedException(); } public void ResetEnum(uint hEnum, uint ulPos) { throw new NotImplementedException(); } public uint EnumTypeDefs(ref uint phEnum, uint[] rTypeDefs, uint cMax) { throw new NotImplementedException(); } public uint EnumInterfaceImpls(ref uint phEnum, uint td, uint[] rImpls, uint cMax) { throw new NotImplementedException(); } public uint EnumTypeRefs(ref uint phEnum, uint[] rTypeRefs, uint cMax) { throw new NotImplementedException(); } public uint FindTypeDefByName(string szTypeDef, uint tkEnclosingClass) { throw new NotImplementedException(); } public Guid GetScopeProps(StringBuilder szName, uint cchName, out uint pchName) { throw new NotImplementedException(); } public uint GetModuleFromScope() { throw new NotImplementedException(); } public uint GetTypeDefProps(uint td, IntPtr szTypeDef, uint cchTypeDef, out uint pchTypeDef, IntPtr pdwTypeDefFlags) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected I4, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!TryGetType(td, out var type)) { Marshal.WriteInt16(szTypeDef, 0); pchTypeDef = 1u; return 0u; } WriteString(((TypeReference)type).IsNested ? ((MemberReference)type).Name : ((MemberReference)type).FullName, szTypeDef, cchTypeDef, out pchTypeDef); WriteIntPtr(pdwTypeDefFlags, (uint)(int)type.Attributes); if (type.BaseType == null) { return 0u; } MetadataToken metadataToken = ((MemberReference)type.BaseType).MetadataToken; return ((MetadataToken)(ref metadataToken)).ToUInt32(); } private static void WriteIntPtr(IntPtr ptr, uint value) { if (!(ptr == IntPtr.Zero)) { Marshal.WriteInt32(ptr, (int)value); } } private static void WriteString(string str, IntPtr buffer, uint bufferSize, out uint chars) { uint num = ((str.Length + 1 >= bufferSize) ? (bufferSize - 1) : ((uint)str.Length)); chars = num + 1; int num2 = 0; for (int i = 0; i < num; i++) { Marshal.WriteInt16(buffer, num2, str[i]); num2 += 2; } Marshal.WriteInt16(buffer, num2, 0); } public uint GetInterfaceImplProps(uint iiImpl, out uint pClass) { throw new NotImplementedException(); } public uint GetTypeRefProps(uint tr, out uint ptkResolutionScope, StringBuilder szName, uint cchName) { throw new NotImplementedException(); } public uint ResolveTypeRef(uint tr, ref Guid riid, out object ppIScope) { throw new NotImplementedException(); } public uint EnumMembers(ref uint phEnum, uint cl, uint[] rMembers, uint cMax) { throw new NotImplementedException(); } public uint EnumMembersWithName(ref uint phEnum, uint cl, string szName, uint[] rMembers, uint cMax) { throw new NotImplementedException(); } public uint EnumMethods(ref uint phEnum, uint cl, IntPtr rMethods, uint cMax) { throw new NotImplementedException(); } public uint EnumMethodsWithName(ref uint phEnum, uint cl, string szName, uint[] rMethods, uint cMax) { throw new NotImplementedException(); } public uint EnumFields(ref uint phEnum, uint cl, IntPtr rFields, uint cMax) { throw new NotImplementedException(); } public uint EnumFieldsWithName(ref uint phEnum, uint cl, string szName, uint[] rFields, uint cMax) { throw new NotImplementedException(); } public uint EnumParams(ref uint phEnum, uint mb, uint[] rParams, uint cMax) { throw new NotImplementedException(); } public uint EnumMemberRefs(ref uint phEnum, uint tkParent, uint[] rMemberRefs, uint cMax) { throw new NotImplementedException(); } public uint EnumMethodImpls(ref uint phEnum, uint td, uint[] rMethodBody, uint[] rMethodDecl, uint cMax) { throw new NotImplementedException(); } public uint EnumPermissionSets(ref uint phEnum, uint tk, uint dwActions, uint[] rPermission, uint cMax) { throw new NotImplementedException(); } public uint FindMember(uint td, string szName, byte[] pvSigBlob, uint cbSigBlob) { throw new NotImplementedException(); } public uint FindMethod(uint td, string szName, byte[] pvSigBlob, uint cbSigBlob) { throw new NotImplementedException(); } public uint FindField(uint td, string szName, byte[] pvSigBlob, uint cbSigBlob) { throw new NotImplementedException(); } public uint FindMemberRef(uint td, string szName, byte[] pvSigBlob, uint cbSigBlob) { throw new NotImplementedException(); } public uint GetMethodProps(uint mb, out uint pClass, IntPtr szMethod, uint cchMethod, out uint pchMethod, IntPtr pdwAttr, IntPtr ppvSigBlob, IntPtr pcbSigBlob, IntPtr pulCodeRVA) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected I4, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected I4, but got Unknown if (!TryGetMethod(mb, out var method)) { Marshal.WriteInt16(szMethod, 0); pchMethod = 1u; pClass = 0u; return 0u; } MetadataToken metadataToken = ((MemberReference)method.DeclaringType).MetadataToken; pClass = ((MetadataToken)(ref metadataToken)).ToUInt32(); WriteString(((MemberReference)method).Name, szMethod, cchMethod, out pchMethod); WriteIntPtr(pdwAttr, (uint)(int)method.Attributes); WriteIntPtr(pulCodeRVA, (uint)method.RVA); return (uint)(int)method.ImplAttributes; } public uint GetMemberRefProps(uint mr, ref uint ptk, StringBuilder szMember, uint cchMember, out uint pchMember, out IntPtr ppvSigBlob) { throw new NotImplementedException(); } public uint EnumProperties(ref uint phEnum, uint td, IntPtr rProperties, uint cMax) { throw new NotImplementedException(); } public uint EnumEvents(ref uint phEnum, uint td, IntPtr rEvents, uint cMax) { throw new NotImplementedException(); } public uint GetEventProps(uint ev, out uint pClass, StringBuilder szEvent, uint cchEvent, out uint pchEvent, out uint pdwEventFlags, out uint ptkEventType, out uint pmdAddOn, out uint pmdRemoveOn, out uint pmdFire, uint[] rmdOtherMethod, uint cMax) { throw new NotImplementedException(); } public uint EnumMethodSemantics(ref uint phEnum, uint mb, uint[] rEventProp, uint cMax) { throw new NotImplementedException(); } public uint GetMethodSemantics(uint mb, uint tkEventProp) { throw new NotImplementedException(); } public uint GetClassLayout(uint td, out uint pdwPackSize, IntPtr rFieldOffset, uint cMax, out uint pcFieldOffset) { throw new NotImplementedException(); } public uint GetFieldMarshal(uint tk, out IntPtr ppvNativeType) { throw new NotImplementedException(); } public uint GetRVA(uint tk, out uint pulCodeRVA) { throw new NotImplementedException(); } public uint GetPermissionSetProps(uint pm, out uint pdwAction, out IntPtr ppvPermission) { throw new NotImplementedException(); } public uint GetSigFromToken(uint mdSig, out IntPtr ppvSig) { throw new NotImplementedException(); } public uint GetModuleRefProps(uint mur, StringBuilder szName, uint cchName) { throw new NotImplementedException(); } public uint EnumModuleRefs(ref uint phEnum, uint[] rModuleRefs, uint cmax) { throw new NotImplementedException(); } public uint GetTypeSpecFromToken(uint typespec, out IntPtr ppvSig) { throw new NotImplementedException(); } public uint GetNameFromToken(uint tk) { throw new NotImplementedException(); } public uint EnumUnresolvedMethods(ref uint phEnum, uint[] rMethods, uint cMax) { throw new NotImplementedException(); } public uint GetUserString(uint stk, StringBuilder szString, uint cchString) { throw new NotImplementedException(); } public uint GetPinvokeMap(uint tk, out uint pdwMappingFlags, StringBuilder szImportName, uint cchImportName, out uint pchImportName) { throw new NotImplementedException(); } public uint EnumSignatures(ref uint phEnum, uint[] rSignatures, uint cmax) { throw new NotImplementedException(); } public uint EnumTypeSpecs(ref uint phEnum, uint[] rTypeSpecs, uint cmax) { throw new NotImplementedException(); } public uint EnumUserStrings(ref uint phEnum, uint[] rStrings, uint cmax) { throw new NotImplementedException(); } public int GetParamForMethodIndex(uint md, uint ulParamSeq, out uint pParam) { throw new NotImplementedException(); } public uint EnumCustomAttributes(ref uint phEnum, uint tk, uint tkType, uint[] rCustomAttributes, uint cMax) { throw new NotImplementedException(); } public uint GetCustomAttributeProps(uint cv, out uint ptkObj, out uint ptkType, out IntPtr ppBlob) { throw new NotImplementedException(); } public uint FindTypeRef(uint tkResolutionScope, string szName) { throw new NotImplementedException(); } public uint GetMemberProps(uint mb, out uint pClass, StringBuilder szMember, uint cchMember, out uint pchMember, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pulCodeRVA, out uint pdwImplFlags, out uint pdwCPlusTypeFlag, out IntPtr ppValue) { throw new NotImplementedException(); } public uint GetFieldProps(uint mb, out uint pClass, StringBuilder szField, uint cchField, out uint pchField, out uint pdwAttr, out IntPtr ppvSigBlob, out uint pcbSigBlob, out uint pdwCPlusTypeFlag, out IntPtr ppValue) { throw new NotImplementedException(); } public uint GetPropertyProps(uint prop, out uint pClass, StringBuilder szProperty, uint cchProperty, out uint pchProperty, out uint pdwPropFlags, out IntPtr ppvSig, out uint pbSig, out uint pdwCPlusTypeFlag, out IntPtr ppDefaultValue, out uint pcchDefaultValue, out uint pmdSetter, out uint pmdGetter, uint[] rmdOtherMethod, uint cMax) { throw new NotImplementedException(); } public uint GetParamProps(uint tk, out uint pmd, out uint pulSequence, StringBuilder szName, uint cchName, out uint pchName, out uint pdwAttr, out uint pdwCPlusTypeFlag, out IntPtr ppValue) { throw new NotImplementedException(); } public uint GetCustomAttributeByName(uint tkObj, string szName, out IntPtr ppData) { throw new NotImplementedException(); } public bool IsValidToken(uint tk) { throw new NotImplementedException(); } public uint GetNestedClassProps(uint tdNestedClass) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!TryGetType(tdNestedClass, out var type)) { return 0u; } if (!((TypeReference)type).IsNested) { return 0u; } MetadataToken metadataToken = ((MemberReference)type.DeclaringType).MetadataToken; return ((MetadataToken)(ref metadataToken)).ToUInt32(); } public uint GetNativeCallConvFromSig(IntPtr pvSig, uint cbSig) { throw new NotImplementedException(); } public int IsGlobal(uint pd) { throw new NotImplementedException(); } } public class NativePdbReader : ISymbolReader, IDisposable { private int age; private Guid guid; private readonly Disposable<Stream> pdb_file; private readonly Dictionary<string, Document> documents = new Dictionary<string, Document>(); private readonly Dictionary<uint, PdbFunction> functions = new Dictionary<uint, PdbFunction>(); private readonly Dictionary<PdbScope, ImportDebugInformation> imports = new Dictionary<PdbScope, ImportDebugInformation>(); internal NativePdbReader(Disposable<Stream> file) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) pdb_file = file; } public ISymbolWriterProvider GetWriterProvider() { return (ISymbolWriterProvider)(object)new NativePdbWriterProvider(); } public bool ProcessDebugHeader(ImageDebugHeader header) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 if (!header.HasEntries) { return false; } ImageDebugHeaderEntry codeViewEntry = Mixin.GetCodeViewEntry(header); if (codeViewEntry == null) { return false; } if ((int)codeViewEntry.Directory.Type != 2) { return false; } byte[] data = codeViewEntry.Data; if (data.Length < 24) { return false; } if (ReadInt32(data, 0) != 1396986706) { return false; } byte[] array = new byte[16]; Buffer.BlockCopy(data, 4, array, 0, 16); guid = new Guid(array); age = ReadInt32(data, 20); return PopulateFunctions(); } private static int ReadInt32(byte[] bytes, int start) { return bytes[start] | (bytes[start + 1] << 8) | (bytes[start + 2] << 16) | (bytes[start + 3] << 24); } private bool PopulateFunctions() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Disposable<Stream> val = pdb_file; try { Dictionary<uint, PdbTokenLine> tokenToSourceMapping; string sourceServerData; int num; Guid guid; PdbFunction[] array = PdbFile.LoadFunctions(pdb_file.value, out tokenToSourceMapping, out sourceServerData, out num, out guid); if (this.guid != guid) { return false; } PdbFunction[] array2 = array; foreach (PdbFunction pdbFunction in array2) { functions.Add(pdbFunction.token, pdbFunction); } } finally { ((IDisposable)val).Dispose(); } return true; } public MethodDebugInformation Read(MethodDefinition method) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown MetadataToken metadataToken = ((MemberReference)method).MetadataToken; if (!functions.TryGetValue(((MetadataToken)(ref metadataToken)).ToUInt32(), out var value)) { return null; } MethodDebugInformation val = new MethodDebugInformation(method); ReadSequencePoints(value, val); val.scope = (ScopeDebugInformation)((!Mixin.IsNullOrEmpty<PdbScope>(value.scopes)) ? ((object)ReadScopeAndLocals(value.scopes[0], val)) : ((object)new ScopeDebugInformation { Start = new InstructionOffset(0), End = new InstructionOffset((int)value.length) })); uint tokenOfMethodWhoseUsingInfoAppliesToThisMethod = value.tokenOfMethodWhoseUsingInfoAppliesToThisMethod; MetadataToken metadataToken2 = ((MemberReference)method).MetadataToken; if (tokenOfMethodWhoseUsingInfoAppliesToThisMethod != ((MetadataToken)(ref metadataToken2)).ToUInt32() && value.tokenOfMethodWhoseUsingInfoAppliesToThisMethod != 0) { val.scope.import = GetImport(value.tokenOfMethodWhoseUsingInfoAppliesToThisMethod, ((MemberReference)method).Module); } if (value.scopes.Length > 1) { for (int i = 1; i < value.scopes.Length; i++) { ScopeDebugInformation val2 = ReadScopeAndLocals(value.scopes[i], val); if (!AddScope(val.scope.Scopes, val2)) { val.scope.Scopes.Add(val2); } } } if (value.iteratorScopes != null) { StateMachineScopeDebugInformation val3 = new StateMachineScopeDebugInformation(); foreach (ILocalScope iteratorScope in value.iteratorScopes) { val3.Scopes.Add(new StateMachineScope((int)iteratorScope.Offset, (int)(iteratorScope.Offset + iteratorScope.Length + 1))); } ((DebugInformation)val).CustomDebugInformations.Add((CustomDebugInformation)(object)val3); } if (value.synchronizationInformation != null) { AsyncMethodBodyDebugInformation val4 = new AsyncMethodBodyDebugInformation((int)value.synchronizationInformation.GeneratedCatchHandlerOffset); PdbSynchronizationPoint[] synchronizationPoints = value.synchronizationInformation.synchronizationPoints; foreach (PdbSynchronizationPoint pdbSynchronizationPoint in synchronizationPoints) { val4.Yields.Add(new InstructionOffset((int)pdbSynchronizationPoint.SynchronizeOffset)); val4.Resumes.Add(new InstructionOffset((int)pdbSynchronizationPoint.ContinuationOffset)); val4.ResumeMethods.Add(method); } ((DebugInformation)val).CustomDebugInformations.Add((CustomDebugInformation)(object)val4); val.StateMachineKickOffMethod = (MethodDefinition)((MemberReference)method).Module.LookupToken((int)value.synchronizationInformation.kickoffMethodToken); } return val; } private Collection<ScopeDebugInformation> ReadScopeAndLocals(PdbScope[] scopes, MethodDebugInformation info) { Collection<ScopeDebugInformation> val = new Collection<ScopeDebugInformation>(scopes.Length); foreach (PdbScope pdbScope in scopes) { if (pdbScope != null) { val.Add(ReadScopeAndLocals(pdbScope, info)); } } return val; } private ScopeDebugInformation ReadScopeAndLocals(PdbScope scope, MethodDebugInformation info) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown ScopeDebugInformation val = new ScopeDebugInformation(); val.Start = new InstructionOffset((int)scope.offset); val.End = new InstructionOffset((int)(scope.offset + scope.length)); if (!Mixin.IsNullOrEmpty<PdbSlot>(scope.slots)) { val.variables = new Collection<VariableDebugInformation>(scope.slots.Length); PdbSlot[] slots = scope.slots; foreach (PdbSlot pdbSlot in slots) { if ((pdbSlot.flags & 1) == 0) { VariableDebugInformation val2 = new VariableDebugInformation((int)pdbSlot.slot, pdbSlot.name); if ((pdbSlot.flags & 4u) != 0) { val2.IsDebuggerHidden = true; } val.variables.Add(val2); } } } if (!Mixin.IsNullOrEmpty<PdbConstant>(scope.constants)) { val.constants = new Collection<ConstantDebugInformation>(scope.constants.Length); PdbConstant[] constants = scope.constants; foreach (PdbConstant pdbConstant in constants) { TypeReference val3 = ((MemberReference)info.Method).Module.Read<PdbConstant, TypeReference>(pdbConstant, (Func<PdbConstant, MetadataReader, TypeReference>)((PdbConstant c, MetadataReader r) => r.ReadConstantSignature(new MetadataToken(c.token)))); object obj = pdbConstant.value; if (val3 != null && !val3.IsValueType && obj is int && (int)obj == 0) { obj = null; } val.constants.Add(new ConstantDebugInformation(pdbConstant.name, val3, obj)); } } if (!Mixin.IsNullOrEmpty<string>(scope.usedNamespaces)) { if (imports.TryGetValue(scope, out var value)) { val.import = value; } else { value = GetImport(scope, ((MemberReference)info.Method).Module); imports.Add(scope, value); val.import = value; } } val.scopes = ReadScopeAndLocals(scope.scopes, info); return val; } private static bool AddScope(Collection<ScopeDebugInformation> scopes, ScopeDebugInformation scope) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Enumerator<ScopeDebugInformation> enumerator = scopes.GetEnumerator(); try { while (enumerator.MoveNext()) { ScopeDebugInformation current = enumerator.Current; if (current.HasScopes && AddScope(current.Scopes, scope)) { return true; } InstructionOffset val = scope.Start; int offset = ((InstructionOffset)(ref val)).Offset; val = current.Start; if (offset >= ((InstructionOffset)(ref val)).Offset) { val = scope.End; int offset2 = ((InstructionOffset)(ref val)).Offset; val = current.End; if (offset2 <= ((InstructionOffset)(ref val)).Offset) { current.Scopes.Add(scope); return true; } } } } finally { ((IDisposable)enumerator).Dispose(); } return false; } private ImportDebugInformation GetImport(uint token, ModuleDefinition module) { if (!functions.TryGetValue(token, out var value)) { return null; } if (value.scopes.Length != 1) { return null; } PdbScope pdbScope = value.scopes[0]; if (imports.TryGetValue(pdbScope, out var value2)) { return value2; } value2 = GetImport(pdbScope, module); imports.Add(pdbScope, value2); return value2; } private static ImportDebugInformation GetImport(PdbScope scope, ModuleDefinition module) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown if (Mixin.IsNullOrEmpty<string>(scope.usedNamespaces)) { return null; } ImportDebugInformation val = new ImportDebugInformation(); string[] usedNamespaces = scope.usedNamespaces; foreach (string text in usedNamespaces) { if (string.IsNullOrEmpty(text)) { continue; } ImportTarget val2 = null; string text2 = text.Substring(1); switch (text[0]) { case 'U': val2 = new ImportTarget((ImportTargetKind)1) { @namespace = text2 }; break; case 'T': { TypeReference val4 = TypeParser.ParseType(module, text2, false); if (val4 != null) { val2 = new ImportTarget((ImportTargetKind)3) { type = val4 }; } break; } case 'A': { int num = text.IndexOf(' '); if (num < 0) { val2 = new ImportTarget((ImportTargetKind)1) { @namespace = text }; break; } string alias = text.Substring(1, num - 1); string text3 = text.Substring(num + 2); switch (text[num + 1]) { case 'U': val2 = new ImportTarget((ImportTargetKind)7) { alias = alias, @namespace = text3 }; break; case 'T': { TypeReference val3 = TypeParser.ParseType(module, text3, false); if (val3 != null) { val2 = new ImportTarget((ImportTargetKind)9) { alias = alias, type = val3 }; } break; } } break; } case '*': val2 = new ImportTarget((ImportTargetKind)1) { @namespace = text2 }; break; case '@': if (!text2.StartsWith("P:")) { continue; } val2 = new ImportTarget((ImportTargetKind)1) { @namespace = text2.Substring(2) }; break; } if (val2 != null) { val.Targets.Add(val2); } } return val; } private void ReadSequencePoints(PdbFunction function, MethodDebugInformation info) { if (function.lines != null) { info.sequence_points = new Collection<SequencePoint>(); PdbLines[] lines = function.lines; foreach (PdbLines lines2 in lines) { ReadLines(lines2, info); } } } private void ReadLines(PdbLines lines, MethodDebugInformation info) { Document document = GetDocument(lines.file); PdbLine[] lines2 = lines.lines; for (int i = 0; i < lines2.Length; i++) { ReadLine(lines2[i], document, info); } } private static void ReadLine(PdbLine line, Document document, MethodDebugInformation info) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown SequencePoint val = new SequencePoint((int)line.offset, document); val.StartLine = (int)line.lineBegin; val.StartColumn = line.colBegin; val.EndLine = (int)line.lineEnd; val.EndColumn = line.colEnd; info.sequence_points.Add(val); } private Document GetDocument(PdbSource source) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown string name = source.name; if (documents.TryGetValue(name, out var value)) { return value; } value = new Document(name) { Language = PdbGuidMapping.ToLanguage(source.language), LanguageVendor = PdbGuidMapping.ToVendor(source.vendor), Type = PdbGuidMapping.ToType(source.doctype) }; documents.Add(name, value); return value; } public void Dispose() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) pdb_file.Dispose(); } } public class NativePdbWriter : ISymbolWriter, IDisposable { private readonly ModuleDefinition module; private readonly MetadataBuilder metadata; private readonly SymWriter writer; private readonly Dictionary<string, SymDocumentWriter> documents; private readonly Dictionary<ImportDebugInformation, MetadataToken> import_info_to_parent; internal NativePdbWriter(ModuleDefinition module, SymWriter writer) { this.module = module; metadata = module.metadata_builder; this.writer = writer; documents = new Dictionary<string, SymDocumentWriter>(); import_info_to_parent = new Dictionary<ImportDebugInformation, MetadataToken>(); } public ISymbolReaderProvider GetReaderProvider() { return (ISymbolReaderProvider)(object)new NativePdbReaderProvider(); } public ImageDebugHeader GetDebugHeader() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown ImageDebugDirectory idd; byte[] debugInfo = writer.GetDebugInfo(out idd); idd.TimeDateStamp = (int)module.timestamp; return new ImageDebugHeader(new ImageDebugHeaderEntry(idd, debugInfo)); } public void Write(MethodDebugInformation info) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) MetadataToken metadataToken = ((MemberReference)info.method).MetadataToken; int methodToken = ((MetadataToken)(ref metadataToken)).ToInt32(); if (info.HasSequencePoints || info.scope != null || ((DebugInformation)info).HasCustomDebugInformations || info.StateMachineKickOffMethod != null) { writer.OpenMethod(methodToken); if (!Mixin.IsNullOrEmpty<SequencePoint>(info.sequence_points)) { DefineSequencePoints(info.sequence_points); } MetadataToken import_parent = default(MetadataToken); if (info.scope != null) { DefineScope(info.scope, info, out import_parent); } DefineCustomMetadata(info, import_parent); writer.CloseMethod(); } } private void DefineCustomMetadata(MethodDebugInformation info, MetadataToken import_parent) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) CustomMetadataWriter customMetadataWriter = new CustomMetadataWriter(writer); if (((MetadataToken)(ref import_parent)).RID != 0) { customMetadataWriter.WriteForwardInfo(import_parent); } else if (info.scope != null && info.scope.Import != null && info.scope.Import.HasTargets) { customMetadataWriter.WriteUsingInfo(info.scope.Import); } if (info.Method.HasCustomAttributes) { Enumerator<CustomAttribute> enumerator = info.Method.CustomAttributes.GetEnumerator(); try { while (enumerator.MoveNext()) { CustomAttribute current = enumerator.Current; TypeReference attributeType = current.AttributeType; if (Mixin.IsTypeOf(attributeType, "System.Runtime.CompilerServices", "IteratorStateMachineAttribute") || Mixin.IsTypeOf(attributeType, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute")) { CustomAttributeArgument val = current.ConstructorArguments[0]; object value = ((CustomAttributeArgument)(ref val)).Value; TypeReference val2 = (TypeReference)((value is TypeReference) ? value : null); if (val2 != null) { customMetadataWriter.WriteForwardIterator(val2); } } } } finally { ((IDisposable)enumerator).Dispose(); } } if (((DebugInformation)info).HasCustomDebugInformations) { CustomDebugInformation? obj = ((IEnumerable<CustomDebugInformation>)((DebugInformation)info).CustomDebugInformations).FirstOrDefault((Func<CustomDebugInformation, bool>)((CustomDebugInformation cdi) => (int)cdi.Kind == 1)); StateMachineScopeDebugInformation val3 = (StateMachineScopeDebugInformation)(object)((obj is StateMachineScopeDebugInformation) ? obj : null); if (val3 != null) { customMetadataWriter.WriteIteratorScopes(val3, info); } } customMetadataWriter.WriteCustomMetadata(); DefineAsyncCustomMetadata(info); } private void DefineAsyncCustomMetadata(MethodDebugInformation info) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (!((DebugInformation)info).HasCustomDebugInformations) { return; } Enumerator<CustomDebugInformation> enumerator = ((DebugInformation)info).CustomDebugInformations.GetEnumerator(); try { while (enumerator.MoveNext()) { CustomDebugInformation current = enumerator.Current; AsyncMethodBodyDebugInformation val = (AsyncMethodBodyDebugInformation)(object)((current is AsyncMethodBodyDebugInformation) ? current : null); if (val == null) { continue; } using MemoryStream memoryStream = new MemoryStream(); BinaryStreamWriter val2 = new BinaryStreamWriter((Stream)memoryStream); int num; MetadataToken metadataToken; if (info.StateMachineKickOffMethod == null) { num = 0; } else { metadataToken = ((MemberReference)info.StateMachineKickOffMethod).MetadataToken; num = (int)((MetadataToken)(ref metadataToken)).ToUInt32(); } val2.WriteUInt32((uint)num); InstructionOffset val3 = val.CatchHandler; val2.WriteUInt32((uint)((InstructionOffset)(ref val3)).Offset); val2.WriteUInt32((uint)val.Resumes.Count); for (int i = 0; i < val.Resumes.Count; i++) { val3 = val.Yields[i]; val2.WriteUInt32((uint)((InstructionOffset)(ref val3)).Offset); metadataToken = ((MemberReference)val.resume_methods[i]).MetadataToken; val2.WriteUInt32(((MetadataToken)(ref metadataToken)).ToUInt32()); val3 = val.Resumes[i]; val2.WriteUInt32((uint)((InstructionOffset)(ref val3)).Offset); } writer.DefineCustomMetadata("asyncMethodInfo", memoryStream.ToArray()); } } finally { ((IDisposable)enumerator).Dispose(); } } private void DefineScope(ScopeDebugInformation scope, MethodDebugInformation info, out MetadataToken import_parent) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Invalid comparison between Unknown and I4 //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Invalid comparison between Unknown and I4 //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Invalid comparison between Unknown and I4 //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Invalid comparison between Unknown and I4 //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Invalid comparison between Unknown and I4 InstructionOffset val = scope.Start; int offset = ((InstructionOffset)(ref val)).Offset; val = scope.End; int num; if (!((InstructionOffset)(ref val)).IsEndOfMethod) { val = scope.End; num = ((InstructionOffset)(ref val)).Offset; } else { num = info.code_size; } int num2 = num; import_parent = new MetadataToken(0u); writer.OpenScope(offset); if (scope.Import != null && scope.Import.HasTargets && !import_info_to_parent.TryGetValue(info.scope.Import, out import_parent)) { Enumerator<ImportTarget> enumerator = scope.Import.Targets.GetEnumerator(); try { while (enumerator.MoveNext()) { ImportTarget current = enumerator.Current; ImportTargetKind kind = current.Kind; if ((int)kind <= 3) { if ((int)kind != 1) { if ((int)kind == 3) { writer.UsingNamespace("T" + TypeParser.ToParseable(current.type, true)); } } else { writer.UsingNamespace("U" + current.@namespace); } } else if ((int)kind != 7) { if ((int)kind == 9) { writer.UsingNamespace("A" + current.Alias + " T" + TypeParser.ToParseable(current.type, true)); } } else { writer.UsingNamespace("A" + current.Alias + " U" + current.@namespace); } } } finally { ((IDisposable)enumerator).Dispose(); } import_info_to_parent.Add(info.scope.Import, ((MemberReference)info.method).MetadataToken); } int local_var_token = ((MetadataToken)(ref info.local_var_token)).ToInt32(); if (!Mixin.IsNullOrEmpty<VariableDebugInformation>(scope.variables)) { for (int i = 0; i < scope.variables.Count; i++) { VariableDebugInformation variable = scope.variables[i]; DefineLocalVariable(variable, local_var_token, offset, num2); } } if (!Mixin.IsNullOrEmpty<ConstantDebugInformation>(scope.constants)) { for (int j = 0; j < scope.constants.Count; j++) { ConstantDebugInformation constant = scope.constants[j]; DefineConstant(constant); } } if (!Mixin.IsNullOrEmpty<ScopeDebugInformation>(scope.scopes)) { for (int k = 0; k < scope.scopes.Count; k++) { DefineScope(scope.scopes[k], info, out var _); } } writer.CloseScope(num2); } private void DefineSequencePoints(Collection<SequencePoint> sequence_points) { for (int i = 0; i < sequence_points.Count; i++) { SequencePoint val = sequence_points[i]; writer.DefineSequencePoints(GetDocument(val.Document), new int[1] { val.Offset }, new int[1] { val.StartLine }, new int[1] { val.StartColumn }, new int[1] { val.EndLine }, new int[1] { val.EndColumn }); } } private void DefineLocalVariable(VariableDebugInformation variable, int local_var_token, int start_offset, int end_offset) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) writer.DefineLocalVariable2(variable.Name, variable.Attributes, local_var_token, variable.Index, 0, 0, start_offset, end_offset); } private void DefineConstant(ConstantDebugInformation constant) { uint num = metadata.AddStandAloneSignature(metadata.GetConstantTypeBlobIndex(constant.ConstantType)); MetadataToken val = default(MetadataToken); ((MetadataToken)(ref val))..ctor((TokenType)285212672, num); writer.DefineConstant2(constant.Name, constant.Value, ((MetadataToken)(ref val)).ToInt32()); } private SymDocumentWriter GetDocument(Document document) { if (document == null) { return null; } if (documents.TryGetValue(document.Url, out var value)) { return value; } value = writer.DefineDocument(document.Url, document.LanguageGuid, document.LanguageVendorGuid, document.TypeGuid); documents[document.Url] = value; return value; } public void Dispose() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) MethodDefinition entryPoint = module.EntryPoint; if (entryPoint != null) { SymWriter symWriter = writer; MetadataToken metadataToken = ((MemberReference)entryPoint).MetadataToken; symWriter.SetUserEntryPoint(((MetadataToken)(ref metadataToken)).ToInt32()); } writer.Close(); } } internal enum CustomMetadataType : byte { UsingInfo = 0, ForwardInfo = 1, IteratorScopes = 3, ForwardIterator = 4 } internal class CustomMetadataWriter : IDisposable { private readonly SymWriter sym_writer; private readonly MemoryStream stream; private readonly BinaryStreamWriter writer; private int count; private const byte version = 4; public CustomMetadataWriter(SymWriter sym_writer) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown this.sym_writer = sym_writer; stream = new MemoryStream(); writer = new BinaryStreamWriter((Stream)stream); writer.WriteByte((byte)4); writer.WriteByte((byte)0); writer.Align(4); } public void WriteUsingInfo(ImportDebugInformation import_info) { Write(CustomMetadataType.UsingInfo, delegate { writer.WriteUInt16((ushort)1); writer.WriteUInt16((ushort)import_info.Targets.Count); }); } public void WriteForwardInfo(MetadataToken import_parent) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Write(CustomMetadataType.ForwardInfo, delegate { writer.WriteUInt32(((MetadataToken)(ref import_parent)).ToUInt32()); }); } public void WriteIteratorScopes(StateMachineScopeDebugInformation state_machine, MethodDebugInformation debug_info) { Write(CustomMetadataType.IteratorScopes, delegate { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) Collection<StateMachineScope> scopes = state_machine.Scopes; writer.WriteInt32(scopes.Count); Enumerator<StateMachineScope> enumerator = scopes.GetEnumerator(); try { while (enumerator.MoveNext()) { StateMachineScope current = enumerator.Current; InstructionOffset val = current.Start; int offset = ((InstructionOffset)(ref val)).Offset; val = current.End; int num; if (!((InstructionOffset)(ref val)).IsEndOfMethod) { val = current.End; num = ((InstructionOffset)(ref val)).Offset; } else { num = debug_info.code_size; } int num2 = num; writer.WriteInt32(offset); writer.WriteInt32(num2 - 1); } } finally { ((IDisposable)enumerator).Dispose(); } }); } public void WriteForwardIterator(TypeReference type) { Write(CustomMetadataType.ForwardIterator, delegate { writer.WriteBytes(Encoding.Unicode.GetBytes(((MemberReference)type).Name)); }); } private void Write(CustomMetadataType type, Action write) { count++; writer.WriteByte((byte)4); writer.WriteByte((byte)type); writer.Align(4); int position = writer.Position; writer.WriteUInt32(0u); write(); writer.Align(4); int position2 = writer.Position; int num = position2 - position + 4; writer.Position = position; writer.WriteInt32(num); writer.Position = position2; } public void WriteCustomMetadata() { if (count != 0) { ((BinaryWriter)(object)writer).BaseStream.Position = 1L; writer.WriteByte((byte)count); ((BinaryWriter)(object)writer).Flush(); sym_writer.DefineCustomMetadata("MD2", stream.ToArray()); } } public void Dispose() { stream.Dispose(); } } public sealed class NativePdbReaderProvider : ISymbolReaderProvider { public ISymbolReader GetSymbolReader(ModuleDefinition module, string fileName) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) Mixin.CheckModule(module); Mixin.CheckFileName(fileName); return (ISymbolReader)(object)new NativePdbReader(Disposable.Owned<Stream>((Stream)File.OpenRead(Mixin.GetPdbFileName(fileName)))); } public ISymbolReader GetSymbolReader(ModuleDefinition module, Stream symbolStream) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) Mixin.CheckModule(module); Mixin.CheckStream((object)symbolStream); return (ISymbolReader)(object)new NativePdbReader(Disposable.NotOwned<Stream>(symbolStream)); } } public sealed class PdbReaderProvider : ISymbolReaderProvider { public ISymbolReader GetSymbolReader(ModuleDefinition module, string fileName) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Mixin.CheckModule(module); Mixin.CheckFileName(fileName); if (module.HasDebugHeader && Mixin.GetEmbeddedPortablePdbEntry(module.GetDebugHeader()) != null) { return new EmbeddedPortablePdbReaderProvider().GetSymbolReader(module, fileName); } if (!Mixin.IsPortablePdb(Mixin.GetPdbFileName(fileName))) { return new NativePdbReaderProvider().GetSymbolReader(module, fileName); } return new PortablePdbReaderProvider().GetSymbolReader(module, fileName); } public ISymbolReader GetSymbolReader(ModuleDefinition module, Stream symbolStream) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) Mixin.CheckModule(module); Mixin.CheckStream((object)symbolStream); Mixin.CheckReadSeek(symbolStream); if (!Mixin.IsPortablePdb(symbolStream)) { return new NativePdbReaderProvider().GetSymbolReader(module, symbolStream); } return new PortablePdbReaderProvider().GetSymbolReader(module, symbolStream); } } public sealed class NativePdbWriterProvider : ISymbolWriterProvider { public ISymbolWriter GetSymbolWriter(ModuleDefinition module, string fileName) { Mixin.CheckModule(module); Mixin.CheckFileName(fileName); return (ISymbolWriter)(object)new NativePdbWriter(module, CreateWriter(module, Mixin.GetPdbFileName(fileName))); } private static SymWriter CreateWriter(ModuleDefinition module, string pdb) { SymWriter symWriter = new SymWriter(); if (File.Exists(pdb)) { File.Delete(pdb); } symWriter.Initialize(new ModuleMetadata(module), pdb, fFullBuild: true); return symWriter; } public ISymbolWriter GetSymbolWriter(ModuleDefinition module, Stream symbolStream) { throw new NotImplementedException(); } } public sealed class PdbWriterProvider : ISymbolWriterProvider { public ISymbolWriter GetSymbolWriter(ModuleDefinition module, string fileName) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) Mixin.CheckModule(module); Mixin.CheckFileName(fileName); if (HasPortablePdbSymbols(module)) { return new PortablePdbWriterProvider().GetSymbolWriter(module, fileName); } return new NativePdbWriterProvider().GetSymbolWriter(module, fileName); } private static bool HasPortablePdbSymbols(ModuleDefinition module) { if (module.symbol_reader != null) { return module.symbol_reader is PortablePdbReader; } return false; } public ISymbolWriter GetSymbolWriter(ModuleDefinition module, Stream symbolStream) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) Mixin.CheckModule(module); Mixin.CheckStream((object)symbolStream); Mixin.CheckReadSeek(symbolStream); if (HasPortablePdbSymbols(module)) { return new PortablePdbWriterProvider().GetSymbolWriter(module, symbolStream); } return new NativePdbWriterProvider().GetSymbolWriter(module, symbolStream); } } internal class SymDocumentWriter { private readonly ISymUnmanagedDocumentWriter m_unmanagedDocumentWriter; public SymDocumentWriter(ISymUnmanagedDocumentWriter unmanagedDocumentWriter) { m_unmanagedDocumentWriter = unmanagedDocumentWriter; } public ISymUnmanagedDocumentWriter GetUnmanaged() { return m_unmanagedDocumentWriter; } } internal class SymWriter { private static Guid s_symUnmangedWriterIID = new Guid("0b97726e-9e6d-4f05-9a26-424022093caa"); private static Guid s_CorSymWriter_SxS_ClassID = new Guid("108296c1-281e-11d3-bd22-0000f80849bd"); private readonly ISymUnmanagedWriter2 m_writer; private readonly Collection<ISymUnmanagedDocumentWriter> documents; [DllImport("ole32.dll")] private static extern int CoCreateInstance([In] ref Guid rclsid, [In][MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv); public SymWriter() { CoCreateInstance(ref s_CorSymWriter_SxS_ClassID, null, 1u, ref s_symUnmangedWriterIID, out var ppv); m_writer = (ISymUnmanagedWriter2)ppv; documents = new Collection<ISymUnmanagedDocumentWriter>(); } public byte[] GetDebugInfo(out ImageDebugDirectory idd) { m_writer.GetDebugInfo(out idd, 0, out var pcData, null); byte[] array = new byte[pcData]; m_writer.GetDebugInfo(out idd, pcData, out pcData, array); return array; } public void DefineLocalVariable2(string name, VariableAttributes attributes, int sigToken, int addr1, int addr2, int addr3, int startOffset, int endOffset) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected I4, but got Unknown m_writer.DefineLocalVariable2(name, (int)attributes, sigToken, 1, addr1, addr2, addr3, startOffset, endOffset); } public void DefineConstant2(string name, object value, int sigToken) { if (value == null) { m_writer.DefineConstant2(name, 0, sigToken); } else { m_writer.DefineConstant2(name, value, sigToken); } } public void Close() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) m_writer.Close(); Marshal.ReleaseComObject(m_writer); Enumerator<ISymUnmanagedDocumentWriter> enumerator = documents.GetEnumerator(); try { while (enumerator.MoveNext()) { Marshal.ReleaseComObject(enumerator.Current); } } finally { ((IDisposable)enumerator).Dispose(); } } public void CloseMethod() { m_writer.CloseMethod(); } public void CloseNamespace() { m_writer.CloseNamespace(); } public void CloseScope(int endOffset) { m_writer.CloseScope(endOffset); } public SymDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) { m_writer.DefineDocument(url, ref language, ref languageVendor, ref documentType, out var pRetVal); documents.Add(pRetVal); return new SymDocumentWriter(pRetVal); } public void DefineSequencePoints(SymDocumentWriter document, int[] offsets, int[] lines, int[] columns, int[] endLines, int[] endColumns) { m_writer.DefineSequencePoints(document.GetUnmanaged(), offsets.Length, offsets, lines, columns, endLines, endColumns); } public void Initialize(object emitter, string filename, bool fFullBuild) { m_writer.Initialize(emitter, filename, null, fFullBuild); } public void SetUserEntryPoint(int methodToken) { m_writer.SetUserEntryPoint(methodToken); } public void OpenMethod(int methodToken) { m_writer.OpenMethod(methodToken); } public void OpenNamespace(string name) { m_writer.OpenNamespace(name); } public int OpenScope(int startOffset) { m_writer.OpenScope(startOffset, out var pRetVal); return pRetVal; } public void UsingNamespace(string fullName) { m_writer.UsingNamespace(fullName); } public void DefineCustomMetadata(string name, byte[] metadata) { GCHandle gCHandle = GCHandle.Alloc(metadata, GCHandleType.Pinned); m_writer.SetSymAttribute(0u, name, (uint)metadata.Length, gCHandle.AddrOfPinnedObject()); gCHandle.Free(); } } } namespace Microsoft.Cci { public interface ILocalScope { uint Offset { get; } uint Length { get; } } public interface INamespaceScope { IEnumerable<IUsedNamespace> UsedNamespaces { get; } } public interface IUsedNamespace { IName Alias { get; } IName NamespaceName { get; } } public interface IName { int UniqueKey { get; } int UniqueKeyIgnoringCase { get; } string Value { get; } } internal sealed class PdbIteratorScope : ILocalScope { private uint offset; private uint length; public uint Offset => offset; public uint Length => length; internal PdbIteratorScope(uint offset, uint length) { this.offset = offset; this.length = length; } } } namespace Microsoft.Cci.Pdb { internal class BitAccess { private byte[] buffer; private int offset; internal byte[] Buffer => buffer; internal int Position { get { return offset; } set { offset = value; } } internal BitAccess(int capacity) { buffer = new byte[capacity]; } internal void FillBuffer(Stream stream, int capacity) { MinCapacity(capacity); stream.Read(buffer, 0, capacity); offset = 0; } internal void Append(Stream stream, int count) { int num = offset + count; if (buffer.Length < num) { byte[] destinationArray = new byte[num]; Array.Copy(buffer, destinationArray, buffer.Length); buffer = destinationArray; } stream.Read(buffer, offset, count); offset += count; } internal void MinCapacity(int capacity) { if (buffer.Length < capacity) { buffer = new byte[capacity]; } offset = 0; } internal void Align(int alignment) { while (offset % alignment != 0) { offset++; } } internal void ReadInt16(out short value) { value = (short)((buffer[offset] & 0xFF) | (buffer[offset + 1] << 8)); offset += 2; } internal void ReadInt8(out sbyte value) { value = (sbyte)buffer[offset]; offset++; } internal void ReadInt32(out int value) { value = (buffer[offset] & 0xFF) | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24); offset += 4; } internal void ReadInt64(out long value) { value = ((long)buffer[offset] & 0xFFL) | (long)((ulong)buffer[offset + 1] << 8) | (long)((ulong)buffer[offset + 2] << 16) | (long)((ulong)buffer[offset + 3] << 24) | (long)((ulong)buffer[offset + 4] << 32) | (long)((ulong)buffer[offset + 5] << 40) | (long)((ulong)buffer[offset + 6] << 48) | (long)((ulong)buffer[offset + 7] << 56); offset += 8; } internal void ReadUInt16(out ushort value) { value = (ushort)((buffer[offset] & 0xFFu) | (uint)(buffer[offset + 1] << 8)); offset += 2; } internal void ReadUInt8(out byte value) { value = (byte)(buffer[offset] & 0xFFu); offset++; } internal void ReadUInt32(out uint value) { value = (buffer[offset] & 0xFFu) | (uint)(buffer[offset + 1] << 8) | (uint)(buffer[offset + 2] << 16) | (uint)(buffer[offset + 3] << 24); offset += 4; } internal void ReadUInt64(out ulong value) { value = ((ulong)buffer[offset] & 0xFFuL) | ((ulong)buffer[offset + 1] << 8) | ((ulong)buffer[offset + 2] << 16) | ((ulong)buffer[offset + 3] << 24) | ((ulong)buffer[offset + 4] << 32) | ((ulong)buffer[offset + 5] << 40) | ((ulong)buffer[offset + 6] << 48) | ((ulong)buffer[offset + 7] << 56); offset += 8; } internal void ReadInt32(int[] values) { for (int i = 0; i < values.Length; i++) { ReadInt32(out values[i]); } } internal void ReadUInt32(uint[] values) { for (int i = 0; i < values.Length; i++) { ReadUInt32(out values[i]); } } internal void ReadBytes(byte[] bytes) { for (int i = 0; i < bytes.Length; i++) { bytes[i] = buffer[offset++]; } } internal float ReadFloat() { float result = BitConverter.ToSingle(buffer, offset); offset += 4; return result; } internal double ReadDouble() { double result = BitConverter.ToDouble(buffer, offset); offset += 8; return result; } internal decimal ReadDecimal() { int[] array = new int[4]; ReadInt32(array); return new decimal(array[2], array[3], array[1], array[0] < 0, (byte)((array[0] & 0xFF0000) >> 16)); } internal void ReadBString(out string value) { ReadUInt16(out var value2); value = Encoding.UTF8.GetString(buffer, offset, value2); offset += value2; } internal string ReadBString(int len) { string @string = Encoding.UTF8.GetString(buffer, offset, len); offset += len; return @string; } internal void ReadCString(out string value) { int i; for (i = 0; offset + i < buffer.Length && buffer[offset + i] != 0; i++) { } value = Encoding.UTF8.GetString(buffer, offset, i); offset += i + 1; } internal void SkipCString(out string value) { int i; for (i = 0; offset + i < buffer.Length && buffer[offset + i] != 0; i++) { } offset += i + 1; value = null; } internal void ReadGuid(out Guid guid) { ReadUInt32(out var value); ReadUInt16(out var value2); ReadUInt16(out var value3); ReadUInt8(out var value4); ReadUInt8(out var value5); ReadUInt8(out var value6); ReadUInt8(out var value7); ReadUInt8(out var value8); ReadUInt8(out var value9); ReadUInt8(out var value10); ReadUInt8(out var value11); guid = new Guid(value, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11); } internal string ReadString() { int i; for (i = 0; offset + i < buffer.Length && buffer[offset + i] != 0; i += 2) { } string @string = Encoding.Unicode.GetString(buffer, offset, i); offset += i + 2; return @string; } } internal struct BitSet { private int size; private uint[] words; internal bool IsEmpty => size == 0; internal BitSet(BitAccess bits) { bits.ReadInt32(out size); words = new uint[size]; bits.ReadUInt32(words); } internal bool IsSet(int index) { int num = index / 32; if (num >= size) { return false; } return (words[num] & GetBit(index)) != 0; } private static uint GetBit(int index) { return (uint)(1 << index % 32); } } internal struct FLOAT10 { internal byte Data_0; internal byte Data_1; internal byte Data_2; internal byte Data_3; internal byte Data_4; internal byte Data_5; internal byte Data_6; internal byte Data_7; internal byte Data_8; internal byte Data_9; } internal enum CV_SIGNATURE { C6 = 0, C7 = 1, C11 = 2, C13 = 4, RESERVERD = 5 } internal enum CV_prmode { CV_TM_DIRECT = 0, CV_TM_NPTR32 = 4, CV_TM_NPTR64 = 6, CV_TM_NPTR128 = 7 } internal enum CV_type { CV_SPECIAL = 0, CV_SIGNED = 1, CV_UNSIGNED = 2, CV_BOOLEAN = 3, CV_REAL = 4, CV_COMPLEX = 5, CV_SPECIAL2 = 6, CV_INT = 7, CV_CVRESERVED = 15 } internal enum CV_special { CV_SP_NOTYPE, CV_SP_ABS, CV_SP_SEGMENT, CV_SP_VOID, CV_SP_CURRENCY, CV_SP_NBASICSTR, CV_SP_FBASICSTR, CV_SP_NOTTRANS, CV_SP_HRESULT } internal enum CV_special2 { CV_S2_BIT, CV_S2_PASCHAR } internal enum CV_integral { CV_IN_1BYTE, CV_IN_2BYTE, CV_IN_4BYTE, CV_IN_8BYTE, CV_IN_16BYTE } internal enum CV_real { CV_RC_REAL32, CV_RC_REAL64, CV_RC_REAL80, CV_RC_REAL128 } internal enum CV_int { CV_RI_CHAR = 0, CV_RI_INT1 = 0, CV_RI_WCHAR = 1, CV_RI_UINT1 = 1, CV_RI_INT2 = 2, CV_RI_UINT2 = 3, CV_RI_INT4 = 4, CV_RI_UINT4 = 5, CV_RI_INT8 = 6, CV_RI_UINT8 = 7, CV_RI_INT16 = 8, CV_RI_UINT16 = 9 } [StructLayout(LayoutKind.Sequential, Size = 1)] internal struct CV_PRIMITIVE_TYPE { private const uint CV_MMASK = 1792u; private const uint CV_TMASK = 240u; private const uint CV_SMASK = 15u; private const int CV_MSHIFT = 8; private const int CV_TSHIFT = 4; private const int CV_SSHIFT = 0; private const uint CV_FIRST_NONPRIM = 4096u; } internal enum TYPE_ENUM { T_NOTYPE = 0, T_ABS = 1, T_SEGMENT = 2, T_VOID = 3, T_HRESULT = 8, T_32PHRESULT = 1032, T_64PHRESULT = 1544, T_PVOID = 259, T_PFVOID = 515, T_PHVOID = 771, T_32PVOID = 1027, T_64PVOID = 1539, T_CURRENCY = 4, T_NOTTRANS = 7, T_BIT = 96, T_PASCHAR = 97, T_CHAR = 16, T_32PCHAR = 1040, T_64PCHAR = 1552, T_UCHAR = 32, T_32PUCHAR = 1056, T_64PUCHAR = 1568, T_RCHAR = 112, T_32PRCHAR = 1136, T_64PRCHAR = 1648, T_WCHAR = 113, T_32PWCHAR = 1137, T_64PWCHAR = 1649, T_INT1 = 104, T_32PINT1 = 1128, T_64PINT1 = 1640, T_UINT1 = 105, T_32PUINT1 = 1129, T_64PUINT1 = 1641, T_SHORT = 17, T_32PSHORT = 1041, T_64PSHORT = 1553, T_USHORT = 33, T_32PUSHORT = 1057, T_64PUSHORT = 1569, T_INT2 = 114, T_32PINT2 = 1138, T_64PINT2 = 1650, T_UINT2 = 115, T_32PUINT2 = 1139, T_64PUINT2 = 1651, T_LONG = 18, T_ULONG = 34, T_32PLONG = 1042, T_32PULONG = 1058, T_64PLONG = 1554, T_64PULONG = 1570, T_INT4 = 116, T_32PINT4 = 1140, T_64PINT4 = 1652, T_UINT4 = 117, T_32PUINT4 = 1141, T_64PUINT4 = 1653, T_QUAD = 19, T_32PQUAD = 1043, T_64PQUAD = 1555, T_UQUAD = 35, T_32PUQUAD = 1059, T_64PUQUAD = 1571, T_INT8 = 118, T_32PINT8 = 1142, T_64PINT8 = 1654, T_UINT8 = 119, T_32PUINT8 = 1143, T_64PUINT8 = 1655, T_OCT = 20, T_32POCT = 1044, T_64POCT = 1556, T_UOCT = 36, T_32PUOCT = 1060, T_64PUOCT = 1572, T_INT16 = 120, T_32PINT16 = 1144, T_64PINT16 = 1656, T_UINT16 = 121, T_32PUINT16 = 1145, T_64PUINT16 = 1657, T_REAL32 = 64, T_32PREAL32 = 1088, T_64PREAL32 = 1600, T_REAL64 = 65, T_32PREAL64 = 1089, T_64PREAL64 = 1601, T_REAL80 = 66, T_32PREAL80 = 1090, T_64PREAL80 = 1602, T_REAL128 = 67, T_32PREAL128 = 1091, T_64PREAL128 = 1603, T_CPLX32 = 80, T_32PCPLX32 = 1104, T_64PCPLX32 = 1616, T_CPLX64 = 81, T_32PCPLX64 = 1105, T_64PCPLX64 = 1617, T_CPLX80 = 82, T_32PCPLX80 = 1106, T_64PCPLX80 = 1618, T_CPLX128 = 83, T_32PCPLX128 = 1107, T_64PCPLX128 = 1619, T_BOOL08 = 48, T_32PBOOL08 = 1072, T_64PBOOL08 = 1584, T_BOOL16 = 49, T_32PBOOL16 = 1073, T_64PBOOL16 = 1585, T_BOOL32 = 50, T_32PBOOL32 = 1074, T_64PBOOL32 = 1586, T_BOOL64 = 51, T_32PBOOL64 = 1075, T_64PBOOL64 = 1587 } internal enum LEAF { LF_VTSHAPE = 10, LF_COBOL1 = 12, LF_LABEL = 14, LF_NULL = 15, LF_NOTTRAN = 16, LF_ENDPRECOMP = 20, LF_TYPESERVER_ST = 22, LF_LIST = 515, LF_REFSYM = 524, LF_ENUMERATE_ST = 1027, LF_TI16_MAX = 4096, LF_MODIFIER = 4097, LF_POINTER = 4098, LF_ARRAY_ST = 4099, LF_CLASS_ST = 4100, LF_STRUCTURE_ST = 4101, LF_UNION_ST = 4102, LF_ENUM_ST = 4103, LF_PROCEDURE = 4104, LF_MFUNCTION = 4105, LF_COBOL0 = 4106, LF_BARRAY = 4107, LF_DIMARRAY_ST = 4108, LF_VFTPATH = 4109, LF_PRECOMP_ST = 4110, LF_OEM = 4111, LF_ALIAS_ST = 4112, LF_OEM2 = 4113, LF_SKIP = 4608, LF_ARGLIST = 4609, LF_DEFARG_ST = 4610, LF_FIELDLIST = 4611, LF_DERIVED = 4612, LF_BITFIELD = 4613, LF_METHODLIST = 4614, LF_DIMCONU = 4615, LF_DIMCONLU = 4616, LF_DIMVARU = 4617, LF_DIMVARLU = 4618, LF_BCLASS = 5120, LF_VBCLASS = 5121, LF_IVBCLASS = 5122, LF_FRIENDFCN_ST = 5123, LF_INDEX = 5124, LF_MEMBER_ST = 5125, LF_STMEMBER_ST = 5126, LF_METHOD_ST = 5127, LF_NESTTYPE_ST = 5128, LF_VFUNCTAB = 5129, LF_FRIENDCLS = 5130, LF_ONEMETHOD_ST = 5131, LF_VFUNCOFF = 5132, LF_NESTTYPEEX_ST = 5133, LF_MEMBERMODIFY_ST = 5134, LF_MANAGED_ST = 5135, LF_ST_MAX = 5376, LF_TYPESERVER = 5377, LF_ENUMERATE = 5378, LF_ARRAY = 5379, LF_CLASS = 5380, LF_STRUCTURE = 5381, LF_UNION = 5382, LF_ENUM = 5383, LF_DIMARRAY = 5384, LF_PRECOMP = 5385, LF_ALIAS = 5386, LF_DEFARG = 5387, LF_FRIENDFCN = 5388, LF_MEMBER = 5389, LF_STMEMBER = 5390, LF_METHOD = 5391, LF_NESTTYPE = 5392, LF_ONEMETHOD = 5393, LF_NESTTYPEEX = 5394, LF_MEMBERMODIFY = 5395, LF_MANAGED = 5396, LF_TYPESERVER2 = 5397, LF_NUMERIC = 32768, LF_CHAR = 32768, LF_SHORT = 32769, LF_USHORT = 32770, LF_LONG = 32771, LF_ULONG = 32772, LF_REAL32 = 32773, LF_REAL64 = 32774, LF_REAL80 = 32775, LF_REAL128 = 32776, LF_QUADWORD = 32777, LF_UQUADWORD = 32778, LF_COMPLEX32 = 32780, LF_COMPLEX64 = 32781, LF_COMPLEX80 = 32782, LF_COMPLEX128 = 32783, LF_VARSTRING = 32784, LF_OCTWORD = 32791, LF_UOCTWORD = 32792, LF_DECIMAL = 32793, LF_DATE = 32794, LF_UTF8STRING = 32795, LF_PAD0 = 240, LF_PAD1 = 241, LF_PAD2 = 242, LF_PAD3 = 243, LF_PAD4 = 244, LF_PAD5 = 245, LF_PAD6 = 246, LF_PAD7 = 247, LF_PAD8 = 248, LF_PAD9 = 249, LF_PAD10 = 250, LF_PAD11 = 251, LF_PAD12 = 252, LF_PAD13 = 253, LF_PAD14 = 254, LF_PAD15 = 255 } internal enum CV_ptrtype { CV_PTR_BASE_SEG = 3, CV_PTR_BASE_VAL = 4, CV_PTR_BASE_SEGVAL = 5, CV_PTR_BASE_ADDR = 6, CV_PTR_BASE_SEGADDR = 7, CV_PTR_BASE_TYPE = 8, CV_PTR_BASE_SELF = 9, CV_PTR_NEAR32 = 10, CV_PTR_64 = 12, CV_PTR_UNUSEDPTR = 13 } internal enum CV_ptrmode { CV_PTR_MODE_PTR, CV_PTR_MODE_REF, CV_PTR_MODE_PMEM, CV_PTR_MODE_PMFUNC, CV_PTR_MODE_RESERVED } internal enum CV_pmtype { CV_PMTYPE_Undef, CV_PMTYPE_D_Single, CV_PMTYPE_D_Multiple, CV_PMTYPE_D_Virtual, CV_PMTYPE_D_General, CV_PMTYPE_F_Single, CV_PMTYPE_F_Multiple, CV_PMTYPE_F_Virtual, CV_PMTYPE_F_General } internal enum CV_methodprop { CV_MTvanilla, CV_MTvirtual, CV_MTstatic, CV_MTfriend, CV_MTintro, CV_MTpurevirt, CV_MTpureintro } internal enum CV_VTS_desc { CV_VTS_near, CV_VTS_far, CV_VTS_thin, CV_VTS_outer, CV_VTS_meta, CV_VTS_near32, CV_VTS_far32, CV_VTS_unused } internal enum CV_LABEL_TYPE { CV_LABEL_NEAR = 0, CV_LABEL_FAR = 4 } [Flags] internal enum CV_modifier : ushort { MOD_const = 1, MOD_volatile = 2, MOD_unaligned = 4 } [Flags] internal enum CV_prop : ushort { packed = 1, ctor = 2, ovlops = 4, isnested = 8, cnested = 0x10, opassign = 0x20, opcast = 0x40, fwdref = 0x80, scoped = 0x100 } [Flags] internal enum CV_fldattr { access = 3, mprop = 0x1C, pseudo = 0x20, noinherit = 0x40, noconstruct = 0x80, compgenx = 0x100 } internal struct TYPTYPE { internal ushort len; internal ushort leaf; } internal struct CV_PDMR32_NVVFCN { internal int mdisp; } internal struct CV_PDMR32_VBASE { internal int mdisp; internal int pdisp; internal int vdisp; } internal struct CV_PMFR32_NVSA { internal uint off; } internal struct CV_PMFR32_NVMA { internal uint off; internal int disp; } internal struct CV_PMFR32_VBASE { internal uint off; internal int mdisp; internal int pdisp; internal int vdisp; } internal struct LeafModifier { internal uint type; internal CV_modifier attr; } [Flags] internal enum LeafPointerAttr : uint { ptrtype = 0x1Fu, ptrmode = 0xE0u, isflat32 = 0x100u, isvolatile = 0x200u, isconst = 0x400u, isunaligned = 0x800u, isrestrict = 0x1000u } [StructLayout(LayoutKind.Sequential, Size = 1)] internal struct LeafPointer { internal struct LeafPointerBody { internal uint utype; internal LeafPointerAttr attr; } } internal struct LeafArray { internal uint elemtype; internal uint idxtype; internal byte[] data; internal string name; } internal struct LeafClass { internal ushort count; internal ushort property; internal uint field; internal uint derived; internal uint vshape; internal byte[] data; internal string name; } internal struct LeafUnion { internal ushort count; internal ushort property; internal uint field; internal byte[] data; internal string name; } internal struct LeafAlias { internal uint utype; internal string name; } internal struct LeafManaged { internal string name; } internal struct LeafEnum { internal ushort count; internal ushort property; internal uint utype; internal uint field; internal string name; } internal struct LeafProc { internal uint rvtype; internal byte calltype; internal byte reserved; internal ushort parmcount; internal uint arglist; } internal struct LeafMFunc { internal uint rvtype; internal uint classtype; internal uint thistype; internal byte calltype; internal byte reserved; internal ushort parmcount; internal uint arglist; internal int thisadjust; } internal struct LeafVTShape { internal ushort count; internal byte[] desc; } internal struct LeafCobol0 { internal uint type; internal byte[] data; } internal struct LeafCobol1 { internal byte[] data; } internal struct LeafBArray { internal uint utype; } internal struct LeafLabel { internal ushort mode; } internal struct LeafDimArray { internal uint utype; internal uint diminfo; internal string name; } internal struct LeafVFTPath { internal uint count; internal uint[] bases; } internal struct LeafPreComp { internal uint start; internal uint count; internal uint signature; internal string name; } internal struct LeafEndPreComp { internal uint signature; } internal struct LeafOEM { internal ushort cvOEM; internal ushort recOEM; internal uint count; internal uint[] index; } internal enum OEM_ID { OEM_MS_FORTRAN90 = 61584, OEM_ODI = 16, OEM_THOMSON_SOFTWARE = 21587, OEM_ODI_REC_BASELIST = 0 } internal struct LeafOEM2 { internal Guid idOem; internal uint count; internal uint[] index; } internal struct LeafTypeServer { internal uint signature; internal uint age; internal string name; } internal struct LeafTypeServer2 { internal Guid sig70; internal uint age; internal string name; } internal struct LeafSkip { internal uint type; internal byte[] data; } internal struct LeafArgList { internal uint count; internal uint[] arg; } internal struct LeafDerived { internal uint count; internal uint[] drvdcls; } internal struct LeafDefArg { internal uint type; internal byte[] expr; } internal struct LeafList { internal byte[] data; } internal struct LeafFieldList { internal char[] data; } internal struct mlMethod { internal ushort attr; internal ushort pad0; internal uint index; internal uint[] vbaseoff; } internal struct LeafMethodList { internal byte[] mList; } internal struct LeafBitfield { internal uint type; internal byte length; internal byte position; } internal struct LeafDimCon { internal uint typ; internal ushort rank; internal byte[] dim; } internal struct LeafDimVar { internal uint rank; internal uint typ; internal uint[] dim; } internal struct LeafRefSym { internal byte[] Sym; } internal struct LeafChar { internal sbyte val; } internal struct LeafShort { internal short val; } internal struct LeafUShort { internal ushort val; } internal struct LeafLong { internal int val; } internal struct LeafULong { internal uint val; } internal struct LeafQuad { internal long val; } internal struct LeafUQuad { internal ulong val; } internal struct LeafOct { internal ulong val0; internal ulong val1; } internal struct LeafUOct { internal ulong val0; internal ulong val1; } internal struct LeafReal32 { internal float val; } internal struct LeafReal64 { internal double val; } internal struct LeafReal80 { internal FLOAT10 val; } internal struct LeafReal128 { internal ulong val0; internal ulong val1; } internal struct LeafCmplx32 { internal float val_real; internal float val_imag; } internal struct LeafCmplx64 { internal double val_real; internal double val_imag; } internal struct LeafCmplx80 { internal FLOAT10 val_real; internal FLOAT10 val_imag; } internal struct LeafCmplx128 { internal ulong val0_real; internal ulong val1_real; internal ulong val0_imag; internal ulong val1_imag; } internal struct LeafVarString { internal ushort len; internal byte[] value; } internal struct LeafIndex { internal ushort pad0; internal uint index; } internal struct LeafBClass { internal ushort attr; internal uint index; internal byte[] offset; } internal struct LeafVBClass { internal ushort attr; internal uint index; internal uint vbptr; internal byte[] vbpoff; } internal struct LeafFriendCls { internal ushort pad0; internal uint index; } internal struct LeafFriendFcn { internal ushort pad0; internal uint index; internal string name; } internal struct LeafMember { internal ushort attr; internal uint index; internal byte[] offset; internal string name; } internal struct LeafSTMember { internal ushort attr; internal uint index; internal string name; } internal struct LeafVFuncTab { internal ushort pad0; internal uint type; } internal struct LeafVFuncOff { internal ushort pad0; internal uint type; internal int offset; } internal struct LeafMethod { internal ushort count; internal uint mList; internal string name; } internal struct LeafOneMethod { internal ushort attr; internal uint index; internal uint[] vbaseoff; internal string name; } internal struct LeafEnumerate { internal ushort attr; internal byte[] value; internal string name; } internal struct LeafNestType { internal ushort pad0; internal uint index; internal string name; } internal struct LeafNestTypeEx { internal ushort attr; internal uint index; internal string name; } internal struct LeafMemberModify { internal ushort
BepInEx/core/Mono.Cecil.Rocks.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text; using Mono.Cecil.Cil; using Mono.Cecil.PE; using Mono.Collections.Generic; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyProduct("Mono.Cecil")] [assembly: AssemblyCopyright("Copyright © 2008 - 2018 Jb Evain")] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("0.10.4.0")] [assembly: AssemblyInformationalVersion("0.10.4.0")] [assembly: AssemblyTitle("Mono.Cecil.Rocks")] [assembly: CLSCompliant(false)] [assembly: AssemblyVersion("0.10.4.0")] namespace Mono.Cecil.Rocks; public class DocCommentId { private StringBuilder id; private DocCommentId() { id = new StringBuilder(); } private void WriteField(FieldDefinition field) { WriteDefinition('F', (IMemberDefinition)(object)field); } private void WriteEvent(EventDefinition @event) { WriteDefinition('E', (IMemberDefinition)(object)@event); } private void WriteType(TypeDefinition type) { id.Append('T').Append(':'); WriteTypeFullName((TypeReference)(object)type); } private void WriteMethod(MethodDefinition method) { WriteDefinition('M', (IMemberDefinition)(object)method); if (((MethodReference)method).HasGenericParameters) { id.Append('`').Append('`'); id.Append(((MethodReference)method).GenericParameters.Count); } if (((MethodReference)method).HasParameters) { WriteParameters((IList<ParameterDefinition>)((MethodReference)method).Parameters); } if (IsConversionOperator(method)) { WriteReturnType(method); } } private static bool IsConversionOperator(MethodDefinition self) { if (self == null) { throw new ArgumentNullException("self"); } if (self.IsSpecialName) { if (!(((MemberReference)self).Name == "op_Explicit")) { return ((MemberReference)self).Name == "op_Implicit"; } return true; } return false; } private void WriteReturnType(MethodDefinition method) { id.Append('~'); WriteTypeSignature(((MethodReference)method).ReturnType); } private void WriteProperty(PropertyDefinition property) { WriteDefinition('P', (IMemberDefinition)(object)property); if (property.HasParameters) { WriteParameters((IList<ParameterDefinition>)((PropertyReference)property).Parameters); } } private void WriteParameters(IList<ParameterDefinition> parameters) { id.Append('('); WriteList(parameters, delegate(ParameterDefinition p) { WriteTypeSignature(((ParameterReference)p).ParameterType); }); id.Append(')'); } private void WriteTypeSignature(TypeReference type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected I4, but got Unknown //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected I4, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown MetadataType metadataType = type.MetadataType; switch (metadataType - 15) { default: switch (metadataType - 27) { case 0: WriteFunctionPointerTypeSignature((FunctionPointerType)type); return; case 3: id.Append('`').Append('`'); id.Append(((GenericParameter)type).Position); return; case 5: WriteModiferTypeSignature((IModifierType)(OptionalModifierType)type, '!'); return; case 4: WriteModiferTypeSignature((IModifierType)(RequiredModifierType)type, '|'); return; } break; case 5: WriteArrayTypeSignature((ArrayType)type); return; case 1: WriteTypeSignature(((TypeSpecification)(ByReferenceType)type).ElementType); id.Append('@'); return; case 6: WriteGenericInstanceTypeSignature((GenericInstanceType)type); return; case 4: id.Append('`'); id.Append(((GenericParameter)type).Position); return; case 0: WriteTypeSignature(((TypeSpecification)(PointerType)type).ElementType); id.Append('*'); return; case 2: case 3: break; } WriteTypeFullName(type); } private void WriteGenericInstanceTypeSignature(GenericInstanceType type) { if (Mixin.IsTypeSpecification(((TypeSpecification)type).ElementType)) { throw new NotSupportedException(); } WriteTypeFullName(((TypeSpecification)type).ElementType, stripGenericArity: true); id.Append('{'); WriteList((IList<TypeReference>)type.GenericArguments, WriteTypeSignature); id.Append('}'); } private void WriteList<T>(IList<T> list, Action<T> action) { for (int i = 0; i < list.Count; i++) { if (i > 0) { id.Append(','); } action(list[i]); } } private void WriteModiferTypeSignature(IModifierType type, char id) { WriteTypeSignature(type.ElementType); this.id.Append(id); WriteTypeSignature(type.ModifierType); } private void WriteFunctionPointerTypeSignature(FunctionPointerType type) { id.Append("=FUNC:"); WriteTypeSignature(type.ReturnType); if (type.HasParameters) { WriteParameters((IList<ParameterDefinition>)type.Parameters); } } private void WriteArrayTypeSignature(ArrayType type) { WriteTypeSignature(((TypeSpecification)type).ElementType); if (type.IsVector) { id.Append("[]"); return; } id.Append("["); WriteList((IList<ArrayDimension>)type.Dimensions, delegate(ArrayDimension dimension) { if (((ArrayDimension)(ref dimension)).LowerBound.HasValue) { id.Append(((ArrayDimension)(ref dimension)).LowerBound.Value); } id.Append(':'); if (((ArrayDimension)(ref dimension)).UpperBound.HasValue) { id.Append(((ArrayDimension)(ref dimension)).UpperBound.Value - (((ArrayDimension)(ref dimension)).LowerBound.GetValueOrDefault() + 1)); } }); id.Append("]"); } private void WriteDefinition(char id, IMemberDefinition member) { this.id.Append(id).Append(':'); WriteTypeFullName((TypeReference)(object)member.DeclaringType); this.id.Append('.'); WriteItemName(member.Name); } private void WriteTypeFullName(TypeReference type, bool stripGenericArity = false) { if (((MemberReference)type).DeclaringType != null) { WriteTypeFullName(((MemberReference)type).DeclaringType); id.Append('.'); } if (!string.IsNullOrEmpty(type.Namespace)) { id.Append(type.Namespace); id.Append('.'); } string text = ((MemberReference)type).Name; if (stripGenericArity) { int num = text.LastIndexOf('`'); if (num > 0) { text = text.Substring(0, num); } } id.Append(text); } private void WriteItemName(string name) { id.Append(name.Replace('.', '#').Replace('<', '{').Replace('>', '}')); } public override string ToString() { return id.ToString(); } public static string GetDocCommentId(IMemberDefinition member) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Invalid comparison between Unknown and I4 //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown if (member == null) { throw new ArgumentNullException("member"); } DocCommentId docCommentId = new DocCommentId(); MetadataToken metadataToken = ((IMetadataTokenProvider)member).MetadataToken; TokenType tokenType = ((MetadataToken)(ref metadataToken)).TokenType; if ((int)tokenType <= 67108864) { if ((int)tokenType != 33554432) { if ((int)tokenType != 67108864) { goto IL_009d; } docCommentId.WriteField((FieldDefinition)member); } else { docCommentId.WriteType((TypeDefinition)member); } } else if ((int)tokenType != 100663296) { if ((int)tokenType != 335544320) { if ((int)tokenType != 385875968) { goto IL_009d; } docCommentId.WriteProperty((PropertyDefinition)member); } else { docCommentId.WriteEvent((EventDefinition)member); } } else { docCommentId.WriteMethod((MethodDefinition)member); } return docCommentId.ToString(); IL_009d: throw new NotSupportedException(member.FullName); } } internal static class Functional { public static Func<A, R> Y<A, R>(Func<Func<A, R>, Func<A, R>> f) { Func<A, R> g = null; g = f((A a) => g(a)); return g; } public static IEnumerable<TSource> Prepend<TSource>(this IEnumerable<TSource> source, TSource element) { if (source == null) { throw new ArgumentNullException("source"); } return PrependIterator(source, element); } private static IEnumerable<TSource> PrependIterator<TSource>(IEnumerable<TSource> source, TSource element) { yield return element; foreach (TSource item in source) { yield return item; } } } public interface IILVisitor { void OnInlineNone(OpCode opcode); void OnInlineSByte(OpCode opcode, sbyte value); void OnInlineByte(OpCode opcode, byte value); void OnInlineInt32(OpCode opcode, int value); void OnInlineInt64(OpCode opcode, long value); void OnInlineSingle(OpCode opcode, float value); void OnInlineDouble(OpCode opcode, double value); void OnInlineString(OpCode opcode, string value); void OnInlineBranch(OpCode opcode, int offset); void OnInlineSwitch(OpCode opcode, int[] offsets); void OnInlineVariable(OpCode opcode, VariableDefinition variable); void OnInlineArgument(OpCode opcode, ParameterDefinition parameter); void OnInlineSignature(OpCode opcode, CallSite callSite); void OnInlineType(OpCode opcode, TypeReference type); void OnInlineField(OpCode opcode, FieldReference field); void OnInlineMethod(OpCode opcode, MethodReference method); } public static class ILParser { private class ParseContext { public CodeReader Code { get; set; } public int Position { get; set; } public MetadataReader Metadata { get; set; } public Collection<VariableDefinition> Variables { get; set; } public IILVisitor Visitor { get; set; } } public static void Parse(MethodDefinition method, IILVisitor visitor) { if (method == null) { throw new ArgumentNullException("method"); } if (visitor == null) { throw new ArgumentNullException("visitor"); } if (!method.HasBody || !((MemberReference)method).HasImage) { throw new ArgumentException(); } ((MemberReference)method).Module.Read<MethodDefinition, bool>(method, (Func<MethodDefinition, MetadataReader, bool>)delegate(MethodDefinition m, MetadataReader _) { ParseMethod(m, visitor); return true; }); } private static void ParseMethod(MethodDefinition method, IILVisitor visitor) { ParseContext parseContext = CreateContext(method, visitor); CodeReader code = parseContext.Code; byte b = ((BinaryReader)(object)code).ReadByte(); switch (b & 3) { case 2: ParseCode(b >> 2, parseContext); break; case 3: ((BinaryStreamReader)code).Advance(-1); ParseFatMethod(parseContext); break; default: throw new NotSupportedException(); } code.MoveBackTo(parseContext.Position); } private static ParseContext CreateContext(MethodDefinition method, IILVisitor visitor) { CodeReader val = ((MemberReference)method).Module.Read<MethodDefinition, CodeReader>(method, (Func<MethodDefinition, MetadataReader, CodeReader>)((MethodDefinition _, MetadataReader reader) => reader.code)); int position = val.MoveTo(method); return new ParseContext { Code = val, Position = position, Metadata = val.reader, Visitor = visitor }; } private static void ParseFatMethod(ParseContext context) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) CodeReader code = context.Code; ((BinaryStreamReader)code).Advance(4); int code_size = ((BinaryReader)(object)code).ReadInt32(); MetadataToken val = code.ReadToken(); if (val != MetadataToken.Zero) { context.Variables = (Collection<VariableDefinition>)(object)code.ReadVariables(val); } ParseCode(code_size, context); } private static void ParseCode(int code_size, ParseContext context) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected I4, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Invalid comparison between Unknown and I4 //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Invalid comparison between Unknown and I4 //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Invalid comparison between Unknown and I4 //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Invalid comparison between Unknown and I4 //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Invalid comparison between Unknown and I4 //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Expected O, but got Unknown //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Invalid comparison between Unknown and I4 //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Invalid comparison between Unknown and I4 //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Expected O, but got Unknown //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Invalid comparison between Unknown and I4 //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Invalid comparison between Unknown and I4 //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Expected O, but got Unknown //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) CodeReader code = context.Code; MetadataReader metadata = context.Metadata; IILVisitor visitor = context.Visitor; int num = ((BinaryStreamReader)code).Position + code_size; while (((BinaryStreamReader)code).Position < num) { byte b = ((BinaryReader)(object)code).ReadByte(); OpCode val = ((b != 254) ? OpCodes.OneByteOpCode[b] : OpCodes.TwoBytesOpCode[((BinaryReader)(object)code).ReadByte()]); OperandType operandType = ((OpCode)(ref val)).OperandType; IMetadataTokenProvider val2; switch ((int)operandType) { case 5: visitor.OnInlineNone(val); break; case 10: { int num2 = ((BinaryReader)(object)code).ReadInt32(); int[] array = new int[num2]; for (int i = 0; i < num2; i++) { array[i] = ((BinaryReader)(object)code).ReadInt32(); } visitor.OnInlineSwitch(val, array); break; } case 15: visitor.OnInlineBranch(val, ((BinaryReader)(object)code).ReadSByte()); break; case 0: visitor.OnInlineBranch(val, ((BinaryReader)(object)code).ReadInt32()); break; case 16: if (val == OpCodes.Ldc_I4_S) { visitor.OnInlineSByte(val, ((BinaryReader)(object)code).ReadSByte()); } else { visitor.OnInlineByte(val, ((BinaryReader)(object)code).ReadByte()); } break; case 2: visitor.OnInlineInt32(val, ((BinaryReader)(object)code).ReadInt32()); break; case 3: visitor.OnInlineInt64(val, ((BinaryReader)(object)code).ReadInt64()); break; case 17: visitor.OnInlineSingle(val, ((BinaryReader)(object)code).ReadSingle()); break; case 7: visitor.OnInlineDouble(val, ((BinaryReader)(object)code).ReadDouble()); break; case 8: visitor.OnInlineSignature(val, code.GetCallSite(code.ReadToken())); break; case 9: visitor.OnInlineString(val, code.GetString(code.ReadToken())); break; case 19: visitor.OnInlineArgument(val, code.GetParameter((int)((BinaryReader)(object)code).ReadByte())); break; case 14: visitor.OnInlineArgument(val, code.GetParameter((int)((BinaryReader)(object)code).ReadInt16())); break; case 18: visitor.OnInlineVariable(val, GetVariable(context, ((BinaryReader)(object)code).ReadByte())); break; case 13: visitor.OnInlineVariable(val, GetVariable(context, ((BinaryReader)(object)code).ReadInt16())); break; case 1: case 4: case 11: case 12: { val2 = metadata.LookupToken(code.ReadToken()); MetadataToken metadataToken = val2.MetadataToken; TokenType tokenType = ((MetadataToken)(ref metadataToken)).TokenType; if ((int)tokenType <= 67108864) { if ((int)tokenType != 16777216 && (int)tokenType != 33554432) { if ((int)tokenType == 67108864) { visitor.OnInlineField(val, (FieldReference)val2); } break; } goto IL_02b8; } if ((int)tokenType <= 167772160) { if ((int)tokenType != 100663296) { if ((int)tokenType != 167772160) { break; } FieldReference val3 = (FieldReference)(object)((val2 is FieldReference) ? val2 : null); if (val3 != null) { visitor.OnInlineField(val, val3); break; } MethodReference val4 = (MethodReference)(object)((val2 is MethodReference) ? val2 : null); if (val4 != null) { visitor.OnInlineMethod(val, val4); break; } throw new InvalidOperationException(); } } else { if ((int)tokenType == 452984832) { goto IL_02b8; } if ((int)tokenType != 721420288) { break; } } visitor.OnInlineMethod(val, (MethodReference)val2); break; } IL_02b8: visitor.OnInlineType(val, (TypeReference)val2); break; } } } private static VariableDefinition GetVariable(ParseContext context, int index) { return context.Variables[index]; } } public static class MethodBodyRocks { public static void SimplifyMacros(this MethodBody self) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Expected I4, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0429: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Invalid comparison between Unknown and I4 //IL_0484: Unknown result type (might be due to invalid IL or missing references) if (self == null) { throw new ArgumentNullException("self"); } Enumerator<Instruction> enumerator = self.Instructions.GetEnumerator(); try { while (enumerator.MoveNext()) { Instruction current = enumerator.Current; OpCode opCode = current.OpCode; if ((int)((OpCode)(ref opCode)).OpCodeType != 1) { continue; } opCode = current.OpCode; Code code = ((OpCode)(ref opCode)).Code; switch (code - 2) { case 0: ExpandMacro(current, OpCodes.Ldarg, Mixin.GetParameter(self, 0)); continue; case 1: ExpandMacro(current, OpCodes.Ldarg, Mixin.GetParameter(self, 1)); continue; case 2: ExpandMacro(current, OpCodes.Ldarg, Mixin.GetParameter(self, 2)); continue; case 3: ExpandMacro(current, OpCodes.Ldarg, Mixin.GetParameter(self, 3)); continue; case 4: ExpandMacro(current, OpCodes.Ldloc, self.Variables[0]); continue; case 5: ExpandMacro(current, OpCodes.Ldloc, self.Variables[1]); continue; case 6: ExpandMacro(current, OpCodes.Ldloc, self.Variables[2]); continue; case 7: ExpandMacro(current, OpCodes.Ldloc, self.Variables[3]); continue; case 8: ExpandMacro(current, OpCodes.Stloc, self.Variables[0]); continue; case 9: ExpandMacro(current, OpCodes.Stloc, self.Variables[1]); continue; case 10: ExpandMacro(current, OpCodes.Stloc, self.Variables[2]); continue; case 11: ExpandMacro(current, OpCodes.Stloc, self.Variables[3]); continue; case 12: current.OpCode = OpCodes.Ldarg; continue; case 13: current.OpCode = OpCodes.Ldarga; continue; case 14: current.OpCode = OpCodes.Starg; continue; case 15: current.OpCode = OpCodes.Ldloc; continue; case 16: current.OpCode = OpCodes.Ldloca; continue; case 17: current.OpCode = OpCodes.Stloc; continue; case 19: ExpandMacro(current, OpCodes.Ldc_I4, -1); continue; case 20: ExpandMacro(current, OpCodes.Ldc_I4, 0); continue; case 21: ExpandMacro(current, OpCodes.Ldc_I4, 1); continue; case 22: ExpandMacro(current, OpCodes.Ldc_I4, 2); continue; case 23: ExpandMacro(current, OpCodes.Ldc_I4, 3); continue; case 24: ExpandMacro(current, OpCodes.Ldc_I4, 4); continue; case 25: ExpandMacro(current, OpCodes.Ldc_I4, 5); continue; case 26: ExpandMacro(current, OpCodes.Ldc_I4, 6); continue; case 27: ExpandMacro(current, OpCodes.Ldc_I4, 7); continue; case 28: ExpandMacro(current, OpCodes.Ldc_I4, 8); continue; case 29: ExpandMacro(current, OpCodes.Ldc_I4, (int)(sbyte)current.Operand); continue; case 40: current.OpCode = OpCodes.Br; continue; case 41: current.OpCode = OpCodes.Brfalse; continue; case 42: current.OpCode = OpCodes.Brtrue; continue; case 43: current.OpCode = OpCodes.Beq; continue; case 44: current.OpCode = OpCodes.Bge; continue; case 45: current.OpCode = OpCodes.Bgt; continue; case 46: current.OpCode = OpCodes.Ble; continue; case 47: current.OpCode = OpCodes.Blt; continue; case 48: current.OpCode = OpCodes.Bne_Un; continue; case 49: current.OpCode = OpCodes.Bge_Un; continue; case 50: current.OpCode = OpCodes.Bgt_Un; continue; case 51: current.OpCode = OpCodes.Ble_Un; continue; case 52: current.OpCode = OpCodes.Blt_Un; continue; case 18: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: continue; } if ((int)code == 188) { current.OpCode = OpCodes.Leave; } } } finally { ((IDisposable)enumerator).Dispose(); } } private static void ExpandMacro(Instruction instruction, OpCode opcode, object operand) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) instruction.OpCode = opcode; instruction.Operand = operand; } private static void MakeMacro(Instruction instruction, OpCode opcode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) instruction.OpCode = opcode; instruction.Operand = null; } public static void Optimize(this MethodBody self) { if (self == null) { throw new ArgumentNullException("self"); } self.OptimizeLongs(); self.OptimizeMacros(); } private static void OptimizeLongs(this MethodBody self) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < self.Instructions.Count; i++) { Instruction val = self.Instructions[i]; OpCode opCode = val.OpCode; if ((int)((OpCode)(ref opCode)).Code == 33) { long num = (long)val.Operand; if (num < int.MaxValue && num > int.MinValue) { ExpandMacro(val, OpCodes.Ldc_I4, (int)num); self.Instructions.Insert(++i, Instruction.Create(OpCodes.Conv_I8)); } } } } public static void OptimizeMacros(this MethodBody self) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected I4, but got Unknown //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) if (self == null) { throw new ArgumentNullException("self"); } MethodDefinition method = self.Method; Enumerator<Instruction> enumerator = self.Instructions.GetEnumerator(); try { while (enumerator.MoveNext()) { Instruction current = enumerator.Current; OpCode opCode = current.OpCode; Code code = ((OpCode)(ref opCode)).Code; if ((int)code != 32) { switch (code - 199) { case 0: { int index = ((ParameterReference)(ParameterDefinition)current.Operand).Index; if (index == -1 && current.Operand == self.ThisParameter) { index = 0; } else if (((MethodReference)method).HasThis) { index++; } switch (index) { case 0: MakeMacro(current, OpCodes.Ldarg_0); break; case 1: MakeMacro(current, OpCodes.Ldarg_1); break; case 2: MakeMacro(current, OpCodes.Ldarg_2); break; case 3: MakeMacro(current, OpCodes.Ldarg_3); break; default: if (index < 256) { ExpandMacro(current, OpCodes.Ldarg_S, current.Operand); } break; } break; } case 3: { int index = ((VariableReference)(VariableDefinition)current.Operand).Index; switch (index) { case 0: MakeMacro(current, OpCodes.Ldloc_0); break; case 1: MakeMacro(current, OpCodes.Ldloc_1); break; case 2: MakeMacro(current, OpCodes.Ldloc_2); break; case 3: MakeMacro(current, OpCodes.Ldloc_3); break; default: if (index < 256) { ExpandMacro(current, OpCodes.Ldloc_S, current.Operand); } break; } break; } case 5: { int index = ((VariableReference)(VariableDefinition)current.Operand).Index; switch (index) { case 0: MakeMacro(current, OpCodes.Stloc_0); break; case 1: MakeMacro(current, OpCodes.Stloc_1); break; case 2: MakeMacro(current, OpCodes.Stloc_2); break; case 3: MakeMacro(current, OpCodes.Stloc_3); break; default: if (index < 256) { ExpandMacro(current, OpCodes.Stloc_S, current.Operand); } break; } break; } case 1: { int index = ((ParameterReference)(ParameterDefinition)current.Operand).Index; if (index == -1 && current.Operand == self.ThisParameter) { index = 0; } else if (((MethodReference)method).HasThis) { index++; } if (index < 256) { ExpandMacro(current, OpCodes.Ldarga_S, current.Operand); } break; } case 4: if (((VariableReference)(VariableDefinition)current.Operand).Index < 256) { ExpandMacro(current, OpCodes.Ldloca_S, current.Operand); } break; } continue; } int num = (int)current.Operand; switch (num) { case -1: MakeMacro(current, OpCodes.Ldc_I4_M1); continue; case 0: MakeMacro(current, OpCodes.Ldc_I4_0); continue; case 1: MakeMacro(current, OpCodes.Ldc_I4_1); continue; case 2: MakeMacro(current, OpCodes.Ldc_I4_2); continue; case 3: MakeMacro(current, OpCodes.Ldc_I4_3); continue; case 4: MakeMacro(current, OpCodes.Ldc_I4_4); continue; case 5: MakeMacro(current, OpCodes.Ldc_I4_5); continue; case 6: MakeMacro(current, OpCodes.Ldc_I4_6); continue; case 7: MakeMacro(current, OpCodes.Ldc_I4_7); continue; case 8: MakeMacro(current, OpCodes.Ldc_I4_8); continue; } if (num >= -128 && num < 128) { ExpandMacro(current, OpCodes.Ldc_I4_S, (sbyte)num); } } } finally { ((IDisposable)enumerator).Dispose(); } OptimizeBranches(self); } private static void OptimizeBranches(MethodBody body) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) ComputeOffsets(body); Enumerator<Instruction> enumerator = body.Instructions.GetEnumerator(); try { while (enumerator.MoveNext()) { Instruction current = enumerator.Current; OpCode opCode = current.OpCode; if ((int)((OpCode)(ref opCode)).OperandType == 0 && OptimizeBranch(current)) { ComputeOffsets(body); } } } finally { ((IDisposable)enumerator).Dispose(); } } private static bool OptimizeBranch(Instruction instruction) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected I4, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Invalid comparison between Unknown and I4 //IL_0147: Unknown result type (might be due to invalid IL or missing references) int offset = ((Instruction)instruction.Operand).Offset; int offset2 = instruction.Offset; OpCode opCode = instruction.OpCode; int num = offset - (offset2 + ((OpCode)(ref opCode)).Size + 4); if (num < -128 || num > 127) { return false; } opCode = instruction.OpCode; Code code = ((OpCode)(ref opCode)).Code; switch (code - 55) { default: if ((int)code == 187) { instruction.OpCode = OpCodes.Leave_S; } break; case 0: instruction.OpCode = OpCodes.Br_S; break; case 1: instruction.OpCode = OpCodes.Brfalse_S; break; case 2: instruction.OpCode = OpCodes.Brtrue_S; break; case 3: instruction.OpCode = OpCodes.Beq_S; break; case 4: instruction.OpCode = OpCodes.Bge_S; break; case 5: instruction.OpCode = OpCodes.Bgt_S; break; case 6: instruction.OpCode = OpCodes.Ble_S; break; case 7: instruction.OpCode = OpCodes.Blt_S; break; case 8: instruction.OpCode = OpCodes.Bne_Un_S; break; case 9: instruction.OpCode = OpCodes.Bge_Un_S; break; case 10: instruction.OpCode = OpCodes.Bgt_Un_S; break; case 11: instruction.OpCode = OpCodes.Ble_Un_S; break; case 12: instruction.OpCode = OpCodes.Blt_Un_S; break; } return true; } private static void ComputeOffsets(MethodBody body) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) int num = 0; Enumerator<Instruction> enumerator = body.Instructions.GetEnumerator(); try { while (enumerator.MoveNext()) { Instruction current = enumerator.Current; current.Offset = num; num += current.GetSize(); } } finally { ((IDisposable)enumerator).Dispose(); } } } public static class MethodDefinitionRocks { public static MethodDefinition GetBaseMethod(this MethodDefinition self) { if (self == null) { throw new ArgumentNullException("self"); } if (!self.IsVirtual) { return self; } if (self.IsNewSlot) { return self; } for (TypeDefinition val = ResolveBaseType(self.DeclaringType); val != null; val = ResolveBaseType(val)) { MethodDefinition matchingMethod = GetMatchingMethod(val, self); if (matchingMethod != null) { return matchingMethod; } } return self; } public static MethodDefinition GetOriginalBaseMethod(this MethodDefinition self) { if (self == null) { throw new ArgumentNullException("self"); } while (true) { MethodDefinition baseMethod = self.GetBaseMethod(); if (baseMethod == self) { break; } self = baseMethod; } return self; } private static TypeDefinition ResolveBaseType(TypeDefinition type) { if (type == null) { return null; } TypeReference baseType = type.BaseType; if (baseType == null) { return null; } return baseType.Resolve(); } private static MethodDefinition GetMatchingMethod(TypeDefinition type, MethodDefinition method) { return MetadataResolver.GetMethod(type.Methods, (MethodReference)(object)method); } } public static class ModuleDefinitionRocks { public static IEnumerable<TypeDefinition> GetAllTypes(this ModuleDefinition self) { if (self == null) { throw new ArgumentNullException("self"); } return ((IEnumerable<TypeDefinition>)self.Types).SelectMany(Functional.Y((Func<TypeDefinition, IEnumerable<TypeDefinition>> f) => (TypeDefinition type) => ((IEnumerable<TypeDefinition>)type.NestedTypes).SelectMany(f).Prepend(type))); } } public static class ParameterReferenceRocks { public static int GetSequence(this ParameterReference self) { return self.Index + 1; } } public static class SecurityDeclarationRocks { public static PermissionSet ToPermissionSet(this SecurityDeclaration self) { if (self == null) { throw new ArgumentNullException("self"); } if (TryProcessPermissionSetAttribute(self, out var set)) { return set; } return CreatePermissionSet(self); } private static bool TryProcessPermissionSetAttribute(SecurityDeclaration declaration, out PermissionSet set) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected I4, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) set = null; if (!declaration.HasSecurityAttributes && declaration.SecurityAttributes.Count != 1) { return false; } SecurityAttribute val = declaration.SecurityAttributes[0]; if (!Mixin.IsTypeOf(val.AttributeType, "System.Security.Permissions", "PermissionSetAttribute")) { return false; } PermissionSetAttribute val2 = new PermissionSetAttribute((SecurityAction)declaration.Action); CustomAttributeNamedArgument val3 = val.Properties[0]; CustomAttributeArgument argument = ((CustomAttributeNamedArgument)(ref val3)).Argument; string text = (string)((CustomAttributeArgument)(ref argument)).Value; string name = ((CustomAttributeNamedArgument)(ref val3)).Name; if (!(name == "XML")) { if (!(name == "Name")) { throw new NotImplementedException(((CustomAttributeNamedArgument)(ref val3)).Name); } val2.Name = text; } else { val2.XML = text; } set = val2.CreatePermissionSet(); return true; } private static PermissionSet CreatePermissionSet(SecurityDeclaration declaration) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) PermissionSet permissionSet = new PermissionSet(PermissionState.None); Enumerator<SecurityAttribute> enumerator = declaration.SecurityAttributes.GetEnumerator(); try { while (enumerator.MoveNext()) { SecurityAttribute current = enumerator.Current; IPermission perm = CreatePermission(declaration, current); permissionSet.AddPermission(perm); } return permissionSet; } finally { ((IDisposable)enumerator).Dispose(); } } private static IPermission CreatePermission(SecurityDeclaration declaration, SecurityAttribute attribute) { SecurityAttribute obj = CreateSecurityAttribute(Type.GetType(((MemberReference)attribute.AttributeType).FullName) ?? throw new ArgumentException("attribute"), declaration) ?? throw new InvalidOperationException(); CompleteSecurityAttribute(obj, attribute); return obj.CreatePermission(); } private static void CompleteSecurityAttribute(SecurityAttribute security_attribute, SecurityAttribute attribute) { if (attribute.HasFields) { CompleteSecurityAttributeFields(security_attribute, attribute); } if (attribute.HasProperties) { CompleteSecurityAttributeProperties(security_attribute, attribute); } } private static void CompleteSecurityAttributeFields(SecurityAttribute security_attribute, SecurityAttribute attribute) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) Type type = security_attribute.GetType(); Enumerator<CustomAttributeNamedArgument> enumerator = attribute.Fields.GetEnumerator(); try { while (enumerator.MoveNext()) { CustomAttributeNamedArgument current = enumerator.Current; FieldInfo? field = type.GetField(((CustomAttributeNamedArgument)(ref current)).Name); CustomAttributeArgument argument = ((CustomAttributeNamedArgument)(ref current)).Argument; field.SetValue(security_attribute, ((CustomAttributeArgument)(ref argument)).Value); } } finally { ((IDisposable)enumerator).Dispose(); } } private static void CompleteSecurityAttributeProperties(SecurityAttribute security_attribute, SecurityAttribute attribute) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) Type type = security_attribute.GetType(); Enumerator<CustomAttributeNamedArgument> enumerator = attribute.Properties.GetEnumerator(); try { while (enumerator.MoveNext()) { CustomAttributeNamedArgument current = enumerator.Current; PropertyInfo? property = type.GetProperty(((CustomAttributeNamedArgument)(ref current)).Name); CustomAttributeArgument argument = ((CustomAttributeNamedArgument)(ref current)).Argument; property.SetValue(security_attribute, ((CustomAttributeArgument)(ref argument)).Value, null); } } finally { ((IDisposable)enumerator).Dispose(); } } private static SecurityAttribute CreateSecurityAttribute(Type attribute_type, SecurityDeclaration declaration) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown try { return (SecurityAttribute)Activator.CreateInstance(attribute_type, (SecurityAction)declaration.Action); } catch (MissingMethodException) { return (SecurityAttribute)Activator.CreateInstance(attribute_type, new object[0]); } } public static SecurityDeclaration ToSecurityDeclaration(this PermissionSet self, SecurityAction action, ModuleDefinition module) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown if (self == null) { throw new ArgumentNullException("self"); } if (module == null) { throw new ArgumentNullException("module"); } SecurityDeclaration val = new SecurityDeclaration(action); SecurityAttribute val2 = new SecurityAttribute(module.TypeSystem.LookupType("System.Security.Permissions", "PermissionSetAttribute")); val2.Properties.Add(new CustomAttributeNamedArgument("XML", new CustomAttributeArgument(module.TypeSystem.String, (object)self.ToXml().ToString()))); val.SecurityAttributes.Add(val2); return val; } } public static class TypeDefinitionRocks { public static IEnumerable<MethodDefinition> GetConstructors(this TypeDefinition self) { if (self == null) { throw new ArgumentNullException("self"); } if (!self.HasMethods) { return Empty<MethodDefinition>.Array; } return ((IEnumerable<MethodDefinition>)self.Methods).Where((MethodDefinition method) => method.IsConstructor); } public static MethodDefinition GetStaticConstructor(this TypeDefinition self) { if (self == null) { throw new ArgumentNullException("self"); } if (!self.HasMethods) { return null; } return self.GetConstructors().FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition ctor) => ctor.IsStatic)); } public static IEnumerable<MethodDefinition> GetMethods(this TypeDefinition self) { if (self == null) { throw new ArgumentNullException("self"); } if (!self.HasMethods) { return Empty<MethodDefinition>.Array; } return ((IEnumerable<MethodDefinition>)self.Methods).Where((MethodDefinition method) => !method.IsConstructor); } public static TypeReference GetEnumUnderlyingType(this TypeDefinition self) { if (self == null) { throw new ArgumentNullException("self"); } if (!self.IsEnum) { throw new ArgumentException(); } return Mixin.GetEnumUnderlyingType(self); } } public static class TypeReferenceRocks { public static ArrayType MakeArrayType(this TypeReference self) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return new ArrayType(self); } public static ArrayType MakeArrayType(this TypeReference self, int rank) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (rank == 0) { throw new ArgumentOutOfRangeException("rank"); } ArrayType val = new ArrayType(self); for (int i = 1; i < rank; i++) { val.Dimensions.Add(default(ArrayDimension)); } return val; } public static PointerType MakePointerType(this TypeReference self) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return new PointerType(self); } public static ByReferenceType MakeByReferenceType(this TypeReference self) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return new ByReferenceType(self); } public static OptionalModifierType MakeOptionalModifierType(this TypeReference self, TypeReference modifierType) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown return new OptionalModifierType(modifierType, self); } public static RequiredModifierType MakeRequiredModifierType(this TypeReference self, TypeReference modifierType) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown return new RequiredModifierType(modifierType, self); } public static GenericInstanceType MakeGenericInstanceType(this TypeReference self, params TypeReference[] arguments) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown if (self == null) { throw new ArgumentNullException("self"); } if (arguments == null) { throw new ArgumentNullException("arguments"); } if (arguments.Length == 0) { throw new ArgumentException(); } if (self.GenericParameters.Count != arguments.Length) { throw new ArgumentException(); } GenericInstanceType val = new GenericInstanceType(self); foreach (TypeReference val2 in arguments) { val.GenericArguments.Add(val2); } return val; } public static PinnedType MakePinnedType(this TypeReference self) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return new PinnedType(self); } public static SentinelType MakeSentinelType(this TypeReference self) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return new SentinelType(self); } }
BepInEx/core/MonoMod.RuntimeDetour.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Net; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Cil; using MonoMod.RuntimeDetour.HookGen; using MonoMod.RuntimeDetour.Platforms; using MonoMod.Utils; using MonoMod.Utils.Cil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("0x0ade")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2022 0x0ade")] [assembly: AssemblyDescription("Flexible and easily extensible runtime detouring library. Wrap, replace and manipulate (Mono.Cecil) methods at runtime.")] [assembly: AssemblyFileVersion("22.1.29.1")] [assembly: AssemblyInformationalVersion("22.01.29.01")] [assembly: AssemblyProduct("MonoMod.RuntimeDetour")] [assembly: AssemblyTitle("MonoMod.RuntimeDetour")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("22.1.29.1")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } internal static class MultiTargetShims { private static readonly object[] _NoArgs = new object[0]; public static string Replace(this string self, string oldValue, string newValue, StringComparison comparison) { return self.Replace(oldValue, newValue); } public static bool Contains(this string self, string value, StringComparison comparison) { return self.Contains(value); } public static int GetHashCode(this string self, StringComparison comparison) { return self.GetHashCode(); } public static int IndexOf(this string self, char value, StringComparison comparison) { return self.IndexOf(value); } public static int IndexOf(this string self, string value, StringComparison comparison) { return self.IndexOf(value); } public static TypeReference GetConstraintType(this TypeReference type) { return type; } } namespace MonoMod { internal static class MMDbgLog { public static readonly string Tag; public static TextWriter Writer; public static bool Debugging; static MMDbgLog() { Tag = typeof(MMDbgLog).Assembly.GetName().Name; if (!(Environment.GetEnvironmentVariable("MONOMOD_DBGLOG") == "1")) { string? environmentVariable = Environment.GetEnvironmentVariable("MONOMOD_DBGLOG"); bool? obj; if (environmentVariable == null) { obj = null; } else { string text = environmentVariable.ToLower(CultureInfo.InvariantCulture); obj = ((text != null) ? new bool?(MultiTargetShims.Contains(text, Tag.ToLower(CultureInfo.InvariantCulture), StringComparison.Ordinal)) : null); } bool? flag = obj; if (!flag.GetValueOrDefault()) { return; } } Start(); } public static void WaitForDebugger() { if (!Debugging) { Debugging = true; Debugger.Launch(); Thread.Sleep(6000); Debugger.Break(); } } public static void Start() { if (Writer != null) { return; } string text = Environment.GetEnvironmentVariable("MONOMOD_DBGLOG_PATH"); if (text == "-") { Writer = Console.Out; return; } if (string.IsNullOrEmpty(text)) { text = "mmdbglog.txt"; } text = Path.GetFullPath(Path.GetFileNameWithoutExtension(text) + "-" + Tag + Path.GetExtension(text)); try { if (File.Exists(text)) { File.Delete(text); } } catch { } try { string directoryName = Path.GetDirectoryName(text); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } Writer = new StreamWriter(new FileStream(text, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete), Encoding.UTF8); } catch { } } public static void Log(string str) { TextWriter writer = Writer; if (writer != null) { writer.WriteLine(str); writer.Flush(); } } public static T Log<T>(string str, T value) { TextWriter writer = Writer; if (writer == null) { return value; } writer.WriteLine(string.Format(CultureInfo.InvariantCulture, str, new object[1] { value })); writer.Flush(); return value; } } } namespace MonoMod.RuntimeDetour { public struct DetourConfig { public bool ManualApply; public int Priority; public string ID; public IEnumerable<string> Before; public IEnumerable<string> After; } public class Detour : ISortableDetour, IDetour, IDisposable { private static Dictionary<MethodBase, List<Detour>> _DetourMap = new Dictionary<MethodBase, List<Detour>>((IEqualityComparer<MethodBase>?)new GenericMethodInstantiationComparer()); private static Dictionary<MethodBase, MethodInfo> _BackupMethods = new Dictionary<MethodBase, MethodInfo>(); private static uint _GlobalIndexNext = 0u; public static Func<Detour, MethodBase, MethodBase, bool> OnDetour; public static Func<Detour, bool> OnUndo; public static Func<Detour, MethodBase, MethodBase> OnGenerateTrampoline; private readonly uint _GlobalIndex; private int _Priority; private string _ID; private List<string> _Before = new List<string>(); private ReadOnlyCollection<string> _BeforeRO; private List<string> _After = new List<string>(); private ReadOnlyCollection<string> _AfterRO; public readonly MethodBase Method; public readonly MethodBase Target; public readonly MethodBase TargetReal; private NativeDetour _TopDetour; private MethodInfo _ChainedTrampoline; private static int compileMethodSubscribed = 0; private List<Detour> _DetourChain { get { if (!_DetourMap.TryGetValue(Method, out var value)) { return null; } return value; } } public bool IsValid => Index != -1; public bool IsApplied { get; private set; } private bool IsTop => _TopDetour != null; public int Index => _DetourChain?.IndexOf(this) ?? (-1); public int MaxIndex => _DetourChain?.Count ?? (-1); public uint GlobalIndex => _GlobalIndex; public int Priority { get { return _Priority; } set { if (_Priority != value) { _Priority = value; _RefreshChain(Method); } } } public string ID { get { return _ID; } set { if (string.IsNullOrEmpty(value)) { value = Extensions.GetID(Target, (string)null, (string)null, true, false, true); } if (!(_ID == value)) { _ID = value; _RefreshChain(Method); } } } public IEnumerable<string> Before { get { return _BeforeRO ?? (_BeforeRO = _Before.AsReadOnly()); } set { lock (_Before) { _Before.Clear(); if (value != null) { foreach (string item in value) { _Before.Add(item); } } _RefreshChain(Method); } } } public IEnumerable<string> After { get { return _AfterRO ?? (_AfterRO = _After.AsReadOnly()); } set { lock (_After) { _After.Clear(); if (value != null) { foreach (string item in value) { _After.Add(item); } } _RefreshChain(Method); } } } public Detour(MethodBase from, MethodBase to, ref DetourConfig config) { //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Expected O, but got Unknown from = from.GetIdentifiable(); if (from.Equals(to)) { throw new ArgumentException("Cannot detour a method to itself!"); } MMDbgLog.Log("detour from " + Extensions.GetID(from, (string)null, (string)null, true, false, false) + " to " + Extensions.GetID(to, (string)null, (string)null, true, false, false)); Method = from; Target = to.Pin(); TargetReal = DetourHelper.Runtime.GetDetourTarget(from, to); _GlobalIndex = _GlobalIndexNext++; _Priority = config.Priority; _ID = config.ID; if (config.Before != null) { foreach (string item in config.Before) { _Before.Add(item); } } if (config.After != null) { foreach (string item2 in config.After) { _After.Add(item2); } } lock (_BackupMethods) { if ((!_BackupMethods.TryGetValue(Method, out var value) || (object)value == null) && (object)(value = Method.CreateILCopy()) != null) { _BackupMethods[Method] = value.Pin(); } } ParameterInfo[] parameters = Method.GetParameters(); Type[] array; if (!Method.IsStatic) { array = new Type[parameters.Length + 1]; array[0] = Extensions.GetThisParamType(Method); for (int i = 0; i < parameters.Length; i++) { array[i + 1] = parameters[i].ParameterType; } } else { array = new Type[parameters.Length]; for (int j = 0; j < parameters.Length; j++) { array[j] = parameters[j].ParameterType; } } DynamicMethodDefinition val = new DynamicMethodDefinition($"Chain<{Extensions.GetID(Method, (string)null, (string)null, true, false, true)}>?{GetHashCode()}", (Method as MethodInfo)?.ReturnType ?? typeof(void), array); try { _ChainedTrampoline = val.StubCriticalDetour().Generate().Pin(); } finally { ((IDisposable)val)?.Dispose(); } List<Detour> value2; lock (_DetourMap) { if (!_DetourMap.TryGetValue(Method, out value2)) { value2 = (_DetourMap[Method] = new List<Detour>()); } } lock (value2) { value2.Add(this); } if (!config.ManualApply) { Apply(); } } public Detour(MethodBase from, MethodBase to, DetourConfig config) : this(from, to, ref config) { } public Detour(MethodBase from, MethodBase to) : this(from, to, DetourContext.Current?.DetourConfig ?? default(DetourConfig)) { } public Detour(MethodBase method, IntPtr to, ref DetourConfig config) : this(method, DetourHelper.GenerateNativeProxy(to, method), ref config) { } public Detour(MethodBase method, IntPtr to, DetourConfig config) : this(method, DetourHelper.GenerateNativeProxy(to, method), ref config) { } public Detour(MethodBase method, IntPtr to) : this(method, DetourHelper.GenerateNativeProxy(to, method)) { } public Detour(Delegate from, IntPtr to, ref DetourConfig config) : this(from.Method, to, ref config) { } public Detour(Delegate from, IntPtr to, DetourConfig config) : this(from.Method, to, ref config) { } public Detour(Delegate from, IntPtr to) : this(from.Method, to) { } public Detour(Delegate from, Delegate to, ref DetourConfig config) : this(from.Method, to.Method, ref config) { } public Detour(Delegate from, Delegate to, DetourConfig config) : this(from.Method, to.Method, ref config) { } public Detour(Delegate from, Delegate to) : this(from.Method, to.Method) { } public Detour(Expression from, IntPtr to, ref DetourConfig config) : this(((MethodCallExpression)from).Method, to, ref config) { } public Detour(Expression from, IntPtr to, DetourConfig config) : this(((MethodCallExpression)from).Method, to, ref config) { } public Detour(Expression from, IntPtr to) : this(((MethodCallExpression)from).Method, to) { } public Detour(Expression from, Expression to, ref DetourConfig config) : this(((MethodCallExpression)from).Method, ((MethodCallExpression)to).Method, ref config) { } public Detour(Expression from, Expression to, DetourConfig config) : this(((MethodCallExpression)from).Method, ((MethodCallExpression)to).Method, ref config) { } public Detour(Expression from, Expression to) : this(((MethodCallExpression)from).Method, ((MethodCallExpression)to).Method) { } public Detour(Expression<Action> from, IntPtr to, ref DetourConfig config) : this(from.Body, to, ref config) { } public Detour(Expression<Action> from, IntPtr to, DetourConfig config) : this(from.Body, to, ref config) { } public Detour(Expression<Action> from, IntPtr to) : this(from.Body, to) { } public Detour(Expression<Action> from, Expression<Action> to, ref DetourConfig config) : this(from.Body, to.Body, ref config) { } public Detour(Expression<Action> from, Expression<Action> to, DetourConfig config) : this(from.Body, to.Body, ref config) { } public Detour(Expression<Action> from, Expression<Action> to) : this(from.Body, to.Body) { } public void Apply() { if (!IsValid) { throw new ObjectDisposedException("Detour"); } if (!IsApplied) { Func<Detour, MethodBase, MethodBase, bool> onDetour = OnDetour; if (onDetour == null || Extensions.InvokeWhileTrue((MulticastDelegate)onDetour, new object[3] { this, Method, Target })) { IsApplied = true; _RefreshChain(Method); } } } public void Undo() { if (!IsValid) { throw new ObjectDisposedException("Detour"); } if (IsApplied) { Func<Detour, bool> onUndo = OnUndo; if (onUndo == null || Extensions.InvokeWhileTrue((MulticastDelegate)onUndo, new object[1] { this })) { IsApplied = false; _RefreshChain(Method); } } } public void Free() { if (!IsValid) { return; } Undo(); List<Detour> detourChain = _DetourChain; lock (detourChain) { detourChain.Remove(this); if (detourChain.Count == 0) { lock (_BackupMethods) { if (_BackupMethods.TryGetValue(Method, out var value)) { value.Unpin(); _BackupMethods.Remove(Method); } } lock (_DetourMap) { _DetourMap.Remove(Method); } } } _ChainedTrampoline.Unpin(); Target.Unpin(); } public void Dispose() { if (IsValid) { Undo(); Free(); } } public MethodBase GenerateTrampoline(MethodBase signature = null) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) Func<Detour, MethodBase, MethodBase> onGenerateTrampoline = OnGenerateTrampoline; MethodBase methodBase = ((onGenerateTrampoline != null) ? Extensions.InvokeWhileNull<MethodBase>((MulticastDelegate)onGenerateTrampoline, new object[2] { this, signature }) : null); if ((object)methodBase != null) { return methodBase; } if ((object)signature == null) { signature = Target; } Type type = (signature as MethodInfo)?.ReturnType ?? typeof(void); ParameterInfo[] parameters = signature.GetParameters(); Type[] array = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = parameters[i].ParameterType; } DynamicMethodDefinition val = new DynamicMethodDefinition($"Trampoline<{Extensions.GetID(Method, (string)null, (string)null, true, false, true)}>?{GetHashCode()}", type, array); try { ILProcessor iLProcessor = val.GetILProcessor(); for (int j = 0; j < 32; j++) { iLProcessor.Emit(OpCodes.Nop); } for (int k = 0; k < array.Length; k++) { iLProcessor.Emit(OpCodes.Ldarg, k); } Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)_ChainedTrampoline); iLProcessor.Emit(OpCodes.Ret); return val.Generate(); } finally { ((IDisposable)val)?.Dispose(); } } public T GenerateTrampoline<T>() where T : Delegate { if (!typeof(Delegate).IsAssignableFrom(typeof(T))) { throw new InvalidOperationException($"Type {typeof(T)} not a delegate type."); } return Extensions.CreateDelegate(GenerateTrampoline(typeof(T).GetMethod("Invoke")), typeof(T)) as T; } private void _TopUndo() { if (_TopDetour != null) { _TopDetour.Undo(); _TopDetour.Free(); _TopDetour = null; Method.Unpin(); TargetReal.Unpin(); } } private void _TopApply() { if (_TopDetour == null) { _TopDetour = new NativeDetour(Method.Pin().GetNativeStart(), TargetReal.Pin().GetNativeStart()); } } private static void _OnCompileMethod(MethodBase method, IntPtr codeStart, ulong codeLen) { if ((object)method == null) { return; } MMDbgLog.Log("compiling: " + Extensions.GetID(method, (string)null, (string)null, true, false, false)); if (_DetourMap.TryGetValue(method, out var value)) { value.FindLast((Detour d) => d.IsTop)?._TopDetour?.ChangeSource(codeStart); } } private static void _RefreshChain(MethodBase method) { if (Interlocked.CompareExchange(ref compileMethodSubscribed, 1, 0) == 0) { DetourHelper.Runtime.OnMethodCompiled += _OnCompileMethod; } MMDbgLog.Log("detours applying for " + Extensions.GetID(method, (string)null, (string)null, true, false, false)); List<Detour> list = _DetourMap[method]; lock (list) { DetourSorter<Detour>.Sort(list); Detour detour = list.FindLast((Detour d) => d.IsTop); Detour detour2 = list.FindLast((Detour d) => d.IsApplied); if (detour != detour2) { detour?._TopUndo(); } if (list.Count == 0) { return; } MethodBase method2 = _BackupMethods[method]; foreach (Detour item in list) { if (item.IsApplied) { _ = item._ChainedTrampoline; using (NativeDetour nativeDetour = new NativeDetour(item._ChainedTrampoline.GetNativeStart(), method2.GetNativeStart())) { nativeDetour.Free(); } method2 = item.Target; } } if (detour != detour2) { detour2?._TopApply(); } } } } public class Detour<T> : Detour where T : Delegate { public Detour(T from, IntPtr to, ref DetourConfig config) : base(from, to, ref config) { } public Detour(T from, IntPtr to, DetourConfig config) : base(from, to, ref config) { } public Detour(T from, IntPtr to) : base(from, to) { } public Detour(T from, T to, ref DetourConfig config) : base(from, to, ref config) { } public Detour(T from, T to, DetourConfig config) : base(from, to, ref config) { } public Detour(T from, T to) : base(from, to) { } } public sealed class DetourContext : IDisposable { [ThreadStatic] private static List<DetourContext> _Contexts; [ThreadStatic] private static DetourContext Last; private MethodBase Creator; public int Priority; private readonly string _FallbackID; private string _ID; public List<string> Before = new List<string>(); public List<string> After = new List<string>(); private bool IsDisposed; private static List<DetourContext> Contexts => _Contexts ?? (_Contexts = new List<DetourContext>()); internal static DetourContext Current { get { DetourContext last = Last; if (last != null && last.IsValid) { return Last; } List<DetourContext> contexts = Contexts; int num = contexts.Count - 1; while (num > -1) { DetourContext detourContext = contexts[num]; if (!detourContext.IsValid) { contexts.RemoveAt(num); num--; continue; } return Last = detourContext; } return null; } } public string ID { get { return _ID ?? _FallbackID; } set { _ID = (string.IsNullOrEmpty(value) ? null : value); } } public DetourConfig DetourConfig { get { DetourConfig result = default(DetourConfig); result.Priority = Priority; result.ID = ID; result.Before = Before; result.After = After; return result; } } public HookConfig HookConfig { get { HookConfig result = default(HookConfig); result.Priority = Priority; result.ID = ID; result.Before = Before; result.After = After; return result; } } public ILHookConfig ILHookConfig { get { ILHookConfig result = default(ILHookConfig); result.Priority = Priority; result.ID = ID; result.Before = Before; result.After = After; return result; } } internal bool IsValid { get { if (IsDisposed) { return false; } if ((object)Creator == null) { return true; } StackTrace stackTrace = new StackTrace(); int frameCount = stackTrace.FrameCount; for (int i = 0; i < frameCount; i++) { if ((object)stackTrace.GetFrame(i).GetMethod() == Creator) { return true; } } return false; } } public DetourContext(int priority, string id) { StackTrace stackTrace = new StackTrace(); int frameCount = stackTrace.FrameCount; for (int i = 0; i < frameCount; i++) { MethodBase method = stackTrace.GetFrame(i).GetMethod(); if ((object)method?.DeclaringType != typeof(DetourContext)) { Creator = method; break; } } object obj = Creator?.DeclaringType?.Assembly?.GetName().Name; if (obj == null) { MethodBase creator = Creator; obj = (((object)creator != null) ? Extensions.GetID(creator, (string)null, (string)null, true, false, true) : null); } _FallbackID = (string)obj; Last = this; Contexts.Add(this); Priority = priority; ID = id; } public DetourContext(string id) : this(0, id) { } public DetourContext(int priority) : this(priority, null) { } public DetourContext() : this(0, null) { } public void Dispose() { if (IsDisposed) { IsDisposed = true; Last = null; Contexts.Remove(this); } } } public sealed class DetourModManager : IDisposable { private readonly Dictionary<IDetour, Assembly> DetourOwners = new Dictionary<IDetour, Assembly>(); private readonly Dictionary<Assembly, List<IDetour>> OwnedDetourLists = new Dictionary<Assembly, List<IDetour>>(); public HashSet<Assembly> Ignored = new HashSet<Assembly>(); private bool Disposed; private static readonly string[] HookTypeNames = new string[4] { "MonoMod.RuntimeDetour.NativeDetour", "MonoMod.RuntimeDetour.Detour", "MonoMod.RuntimeDetour.Hook", "MonoMod.RuntimeDetour.ILHook" }; public event Action<Assembly, MethodBase, Manipulator> OnILHook; public event Action<Assembly, MethodBase, MethodBase, object> OnHook; public event Action<Assembly, MethodBase, MethodBase> OnDetour; public event Action<Assembly, MethodBase, IntPtr, IntPtr> OnNativeDetour; public DetourModManager() { Ignored.Add(typeof(DetourModManager).Assembly); ILHook.OnDetour = (Func<ILHook, MethodBase, Manipulator, bool>)Delegate.Combine(ILHook.OnDetour, new Func<ILHook, MethodBase, Manipulator, bool>(RegisterILHook)); ILHook.OnUndo = (Func<ILHook, bool>)Delegate.Combine(ILHook.OnUndo, new Func<ILHook, bool>(UnregisterDetour)); Hook.OnDetour = (Func<Hook, MethodBase, MethodBase, object, bool>)Delegate.Combine(Hook.OnDetour, new Func<Hook, MethodBase, MethodBase, object, bool>(RegisterHook)); Hook.OnUndo = (Func<Hook, bool>)Delegate.Combine(Hook.OnUndo, new Func<Hook, bool>(UnregisterDetour)); Detour.OnDetour = (Func<Detour, MethodBase, MethodBase, bool>)Delegate.Combine(Detour.OnDetour, new Func<Detour, MethodBase, MethodBase, bool>(RegisterDetour)); Detour.OnUndo = (Func<Detour, bool>)Delegate.Combine(Detour.OnUndo, new Func<Detour, bool>(UnregisterDetour)); NativeDetour.OnDetour = (Func<NativeDetour, MethodBase, IntPtr, IntPtr, bool>)Delegate.Combine(NativeDetour.OnDetour, new Func<NativeDetour, MethodBase, IntPtr, IntPtr, bool>(RegisterNativeDetour)); NativeDetour.OnUndo = (Func<NativeDetour, bool>)Delegate.Combine(NativeDetour.OnUndo, new Func<NativeDetour, bool>(UnregisterDetour)); } public void Dispose() { if (!Disposed) { Disposed = true; OwnedDetourLists.Clear(); ILHook.OnDetour = (Func<ILHook, MethodBase, Manipulator, bool>)Delegate.Remove(ILHook.OnDetour, new Func<ILHook, MethodBase, Manipulator, bool>(RegisterILHook)); ILHook.OnUndo = (Func<ILHook, bool>)Delegate.Remove(ILHook.OnUndo, new Func<ILHook, bool>(UnregisterDetour)); Hook.OnDetour = (Func<Hook, MethodBase, MethodBase, object, bool>)Delegate.Remove(Hook.OnDetour, new Func<Hook, MethodBase, MethodBase, object, bool>(RegisterHook)); Hook.OnUndo = (Func<Hook, bool>)Delegate.Remove(Hook.OnUndo, new Func<Hook, bool>(UnregisterDetour)); Detour.OnDetour = (Func<Detour, MethodBase, MethodBase, bool>)Delegate.Remove(Detour.OnDetour, new Func<Detour, MethodBase, MethodBase, bool>(RegisterDetour)); Detour.OnUndo = (Func<Detour, bool>)Delegate.Remove(Detour.OnUndo, new Func<Detour, bool>(UnregisterDetour)); NativeDetour.OnDetour = (Func<NativeDetour, MethodBase, IntPtr, IntPtr, bool>)Delegate.Remove(NativeDetour.OnDetour, new Func<NativeDetour, MethodBase, IntPtr, IntPtr, bool>(RegisterNativeDetour)); NativeDetour.OnUndo = (Func<NativeDetour, bool>)Delegate.Remove(NativeDetour.OnUndo, new Func<NativeDetour, bool>(UnregisterDetour)); } } public void Unload(Assembly asm) { if ((object)asm == null || Ignored.Contains(asm)) { return; } HookEndpointManager.RemoveAllOwnedBy(asm); if (OwnedDetourLists.TryGetValue(asm, out var value)) { IDetour[] array = value.ToArray(); for (int i = 0; i < array.Length; i++) { array[i].Dispose(); } if (value.Count > 0) { throw new Exception("Some detours failed to unregister in " + asm.FullName); } OwnedDetourLists.Remove(asm); } } internal Assembly GetHookOwner(StackTrace stack = null) { if (stack == null) { stack = new StackTrace(); } Assembly assembly = null; int frameCount = stack.FrameCount; string text = null; for (int i = 0; i < frameCount; i++) { MethodBase method = stack.GetFrame(i).GetMethod(); if ((object)method?.DeclaringType == null) { continue; } string fullName = method.DeclaringType.FullName; if (text == null) { if (HookTypeNames.Contains(fullName)) { text = method.DeclaringType.FullName; } } else if (!(fullName == text)) { assembly = method?.DeclaringType.Assembly; break; } } if (Ignored.Contains(assembly)) { return null; } return assembly; } internal void TrackDetour(Assembly owner, IDetour detour) { if (!OwnedDetourLists.TryGetValue(owner, out var value)) { value = (OwnedDetourLists[owner] = new List<IDetour>()); } value.Add(detour); DetourOwners[detour] = owner; } internal bool RegisterILHook(ILHook _detour, MethodBase from, Manipulator manipulator) { Assembly hookOwner = GetHookOwner(); if ((object)hookOwner == null) { return true; } this.OnILHook?.Invoke(hookOwner, from, manipulator); TrackDetour(hookOwner, _detour); return true; } internal bool RegisterHook(Hook _detour, MethodBase from, MethodBase to, object target) { Assembly hookOwner = GetHookOwner(); if ((object)hookOwner == null) { return true; } this.OnHook?.Invoke(hookOwner, from, to, target); TrackDetour(hookOwner, _detour); return true; } internal bool RegisterDetour(Detour _detour, MethodBase from, MethodBase to) { Assembly hookOwner = GetHookOwner(); if ((object)hookOwner == null) { return true; } this.OnDetour?.Invoke(hookOwner, from, to); TrackDetour(hookOwner, _detour); return true; } internal bool RegisterNativeDetour(NativeDetour _detour, MethodBase method, IntPtr from, IntPtr to) { Assembly hookOwner = GetHookOwner(); if ((object)hookOwner == null) { return true; } this.OnNativeDetour?.Invoke(hookOwner, method, from, to); TrackDetour(hookOwner, _detour); return true; } internal bool UnregisterDetour(IDetour _detour) { if (DetourOwners.TryGetValue(_detour, out var value)) { DetourOwners.Remove(_detour); OwnedDetourLists[value].Remove(_detour); } return true; } } public static class HarmonyDetourBridge { public enum Type { Auto, Basic, AsOriginal, Override } private class DetourToRDAttribute : Attribute { public string Type { get; } public int SkipParams { get; } public string Name { get; } public DetourToRDAttribute(string type, int skipParams = 0, string name = null) { Type = type; SkipParams = skipParams; Name = name; } } private class DetourToHAttribute : Attribute { public string Type { get; } public int SkipParams { get; } public string Name { get; } public DetourToHAttribute(string type, int skipParams = 0, string name = null) { Type = type; SkipParams = skipParams; Name = name; } } private class TranspileAttribute : Attribute { public string Type { get; } public string Name { get; } public TranspileAttribute(string type, string name = null) { Type = type; Name = name; } } private class CriticalAttribute : Attribute { } private static Type CurrentType; private static Assembly _HarmonyASM; private static readonly HashSet<IDisposable> _Detours; private static readonly Dictionary<System.Type, MethodInfo> _Emitters; [ThreadStatic] private static DynamicMethodDefinition _LastWrapperDMD; private static Assembly _SharedStateASM; private static DetourConfig _DetourConfig; public static bool Initialized { get; private set; } static HarmonyDetourBridge() { _Detours = new HashSet<IDisposable>(); _Emitters = new Dictionary<System.Type, MethodInfo>(); System.Type typeFromHandle = typeof(OpCode); System.Type proxyType = ILGeneratorShim.GetProxyType<CecilILGenerator>(); MethodInfo[] methods = proxyType.GetMethods(); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "Emit") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 2 && (object)parameters[0].ParameterType == typeFromHandle) { System.Type parameterType = parameters[1].ParameterType; if (!_Emitters.ContainsKey(parameterType) || (object)methodInfo.DeclaringType == proxyType) { _Emitters[parameterType] = methodInfo; } } } } public static bool Init(bool forceLoad = true, Type type = Type.Auto) { //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Expected O, but got Unknown //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Expected O, but got Unknown if ((object)_HarmonyASM == null) { _HarmonyASM = _FindHarmony(); } if ((object)_HarmonyASM == null && forceLoad) { _HarmonyASM = Assembly.Load(new AssemblyName { Name = "0Harmony" }); } if ((object)_HarmonyASM == null) { return false; } if (Initialized) { return true; } Initialized = true; if (type == Type.Auto) { type = Type.AsOriginal; } DetourConfig detourConfig = default(DetourConfig); detourConfig.Priority = type switch { Type.Override => 536870911, Type.AsOriginal => -536870912, _ => 0, }; _DetourConfig = detourConfig; CurrentType = type; try { MethodInfo[] methods = typeof(HarmonyDetourBridge).GetMethods(BindingFlags.Static | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { bool flag = methodInfo.GetCustomAttributes(typeof(CriticalAttribute), inherit: false).Any(); object[] customAttributes = methodInfo.GetCustomAttributes(typeof(DetourToRDAttribute), inherit: false); for (int j = 0; j < customAttributes.Length; j++) { DetourToRDAttribute detourToRDAttribute = (DetourToRDAttribute)customAttributes[j]; foreach (MethodInfo item in GetHarmonyMethod(methodInfo, detourToRDAttribute.Type, detourToRDAttribute.SkipParams, detourToRDAttribute.Name)) { flag = false; _Detours.Add(new Hook(item, methodInfo)); } } customAttributes = methodInfo.GetCustomAttributes(typeof(DetourToHAttribute), inherit: false); for (int j = 0; j < customAttributes.Length; j++) { DetourToHAttribute detourToHAttribute = (DetourToHAttribute)customAttributes[j]; foreach (MethodInfo item2 in GetHarmonyMethod(methodInfo, detourToHAttribute.Type, detourToHAttribute.SkipParams, detourToHAttribute.Name)) { flag = false; _Detours.Add(new Detour(methodInfo, item2)); } } customAttributes = methodInfo.GetCustomAttributes(typeof(TranspileAttribute), inherit: false); for (int j = 0; j < customAttributes.Length; j++) { TranspileAttribute transpileAttribute = (TranspileAttribute)customAttributes[j]; foreach (MethodInfo item3 in GetHarmonyMethod(methodInfo, transpileAttribute.Type, -1, transpileAttribute.Name)) { DynamicMethodDefinition val = new DynamicMethodDefinition((MethodBase)item3); try { flag = false; ILContext val2 = new ILContext(val.Definition) { ReferenceBag = (IILReferenceBag)(object)RuntimeILReferenceBag.Instance }; _Detours.Add((IDisposable)val2); val2.Invoke(Extensions.CreateDelegate<Manipulator>((MethodBase)methodInfo)); if (val2.IsReadOnly) { val2.Dispose(); _Detours.Remove((IDisposable)val2); } else { _Detours.Add(new Detour(item3, val.Generate())); } } finally { ((IDisposable)val)?.Dispose(); } } } if (flag) { throw new Exception("Cannot apply HarmonyDetourBridge rule " + methodInfo.Name); } } } catch { _EarlyReset(); throw; } return true; } private static bool _EarlyReset() { foreach (IDisposable detour in _Detours) { detour.Dispose(); } _Detours.Clear(); return false; } public static void Reset() { if (Initialized) { Initialized = false; _EarlyReset(); } } private static System.Type GetHarmonyType(string typeName) { return _HarmonyASM.GetType(typeName) ?? _HarmonyASM.GetType("HarmonyLib." + typeName) ?? _HarmonyASM.GetType("Harmony." + typeName) ?? _HarmonyASM.GetType("Harmony.ILCopying." + typeName); } private static IEnumerable<MethodInfo> GetHarmonyMethod(MethodInfo ctx, string typeName, int skipParams, string name) { System.Type harmonyType = GetHarmonyType(typeName); if ((object)harmonyType == null) { return null; } if (string.IsNullOrEmpty(name)) { name = ctx.Name; } if (skipParams < 0) { return from method in harmonyType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where method.Name == name select method; } return new MethodInfo[1] { harmonyType.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, (from p in ctx.GetParameters().Skip(skipParams) select p.ParameterType).ToArray(), null) }; } private static DynamicMethodDefinition CreateDMD(MethodBase original, string suffix) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown if ((object)original == null) { throw new ArgumentNullException("original"); } ParameterInfo[] parameters = original.GetParameters(); System.Type[] array; if (!original.IsStatic) { array = new System.Type[parameters.Length + 1]; array[0] = Extensions.GetThisParamType(original); for (int i = 0; i < parameters.Length; i++) { array[i + 1] = parameters[i].ParameterType; } } else { array = new System.Type[parameters.Length]; for (int j = 0; j < parameters.Length; j++) { array[j] = parameters[j].ParameterType; } } return new DynamicMethodDefinition(MultiTargetShims.Replace(original.Name + suffix, "<>", "", StringComparison.Ordinal), (original as MethodInfo)?.ReturnType ?? typeof(void), array); } [DetourToRD("Memory", 0, null)] private static long GetMethodStart(MethodBase method, out Exception exception) { exception = null; try { _Detours.Add((IDisposable)new LazyDisposable<MethodBase>(method, (Action<MethodBase>)delegate(MethodBase m) { m.Unpin(); })); return (long)method.Pin().GetNativeStart(); } catch (Exception ex) { exception = ex; return 0L; } } [DetourToRD("Memory", 0, null)] [Critical] private static string WriteJump(long memory, long destination) { _Detours.Add(new NativeDetour((IntPtr)memory, (IntPtr)destination)); return null; } [DetourToRD("Memory", 0, null)] [Critical] private static string DetourMethod(MethodBase original, MethodBase replacement) { if ((object)replacement == null) { replacement = _LastWrapperDMD.Generate(); _LastWrapperDMD.Dispose(); _LastWrapperDMD = null; } _Detours.Add(new Detour(original, replacement, ref _DetourConfig)); return null; } [DetourToRD("MethodBodyReader", 1, null)] private static MethodInfo EmitMethodForType(object self, System.Type type) { foreach (KeyValuePair<System.Type, MethodInfo> emitter in _Emitters) { if ((object)emitter.Key == type) { return emitter.Value; } } foreach (KeyValuePair<System.Type, MethodInfo> emitter2 in _Emitters) { if (emitter2.Key.IsAssignableFrom(type)) { return emitter2.Value; } } return null; } [DetourToRD("PatchProcessor", 2, null)] [Critical] private static List<DynamicMethod> Patch(Func<object, List<DynamicMethod>> orig, object self) { orig(self); return new List<DynamicMethod>(); } [Transpile("PatchFunctions", null)] [Critical] private static void UpdateWrapper(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); val.GotoNext(new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchThrow(i) }); val.Next.OpCode = OpCodes.Pop; } [Transpile("MethodPatcher", null)] [Critical] private static void CreatePatchedMethod(ILContext il) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); System.Type t_DynamicTools = GetHarmonyType("DynamicTools"); if (!val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCall(i, t_DynamicTools, "CreateDynamicMethod") })) { il.MakeReadOnly(); return; } val.Next.OpCode = OpCodes.Call; val.Next.Operand = il.Import((MethodBase)typeof(HarmonyDetourBridge).GetMethod("CreateDMD", BindingFlags.Static | BindingFlags.NonPublic)); int varDMDi = -1; val.GotoNext(new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchStloc(i, ref varDMDi) }); ((VariableReference)il.Body.Variables[varDMDi]).VariableType = il.Import(typeof(DynamicMethodDefinition)); val.GotoNext(new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCallvirt<DynamicMethod>(i, "GetILGenerator") }); val.Next.OpCode = OpCodes.Call; val.Next.Operand = il.Import((MethodBase)typeof(DynamicMethodDefinition).GetMethod("GetILGenerator", BindingFlags.Instance | BindingFlags.Public)); val.GotoNext(new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCall(i, t_DynamicTools, "PrepareDynamicMethod") }); val.Next.OpCode = OpCodes.Pop; val.Next.Operand = null; val.GotoNext(new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchLdloc(i, varDMDi) }); int index = val.Index; val.Index = index + 1; val.EmitDelegate<Func<DynamicMethodDefinition, DynamicMethod>>((Func<DynamicMethodDefinition, DynamicMethod>)delegate(DynamicMethodDefinition dmd) { _LastWrapperDMD = dmd; return null; }); } [DetourToRD("HarmonySharedState", 1, null)] private static Assembly SharedStateAssembly(Func<Assembly> orig) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown Assembly assembly = orig(); if ((object)assembly != null) { return assembly; } if ((object)_SharedStateASM != null) { return _SharedStateASM; } string text = (string)GetHarmonyType("HarmonySharedState").GetField("name", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); ModuleDefinition val = ModuleDefinition.CreateModule("MonoMod.RuntimeDetour." + text, new ModuleParameters { Kind = (ModuleKind)0, ReflectionImporterProvider = MMReflectionImporter.Provider }); try { TypeDefinition val2 = new TypeDefinition("", text, (TypeAttributes)385) { BaseType = val.TypeSystem.Object }; val.Types.Add(val2); val2.Fields.Add(new FieldDefinition("state", (FieldAttributes)22, val.ImportReference(typeof(Dictionary<MethodBase, byte[]>)))); val2.Fields.Add(new FieldDefinition("version", (FieldAttributes)22, val.ImportReference(typeof(int)))); return _SharedStateASM = ReflectionHelper.Load(val); } finally { ((IDisposable)val)?.Dispose(); } } private static Assembly _FindHarmony() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name == "0Harmony" || assembly.GetName().Name == "Harmony" || (object)assembly.GetType("Harmony.HarmonyInstance") != null || (object)assembly.GetType("HarmonyLib.Harmony") != null) { return assembly; } } object obj = System.Type.GetType("Harmony.HarmonyInstance", throwOnError: false, ignoreCase: false)?.Assembly; if (obj == null) { System.Type? type = System.Type.GetType("HarmonyLib.Harmony", throwOnError: false, ignoreCase: false); if ((object)type == null) { return null; } obj = type.Assembly; } return (Assembly)obj; } } public struct HookConfig { public bool ManualApply; public int Priority; public string ID; public IEnumerable<string> Before; public IEnumerable<string> After; } public class Hook : IDetour, IDisposable { public static Func<Hook, MethodBase, MethodBase, object, bool> OnDetour; public static Func<Hook, bool> OnUndo; public static Func<Hook, MethodBase, MethodBase> OnGenerateTrampoline; public readonly MethodBase Method; public readonly MethodBase Target; public readonly MethodBase TargetReal; public readonly object DelegateTarget; private Detour _Detour; private readonly Type _OrigDelegateType; private readonly MethodInfo _OrigDelegateInvoke; private int? _RefTarget; private int? _RefTrampoline; private int? _RefTrampolineTmp; public bool IsValid => _Detour.IsValid; public bool IsApplied => _Detour.IsApplied; public Detour Detour => _Detour; public Hook(MethodBase from, MethodInfo to, object target, ref HookConfig config) { //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Expected O, but got Unknown //IL_025b: Expected O, but got Unknown //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Expected O, but got Unknown //IL_0379: Expected O, but got Unknown //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) from = from.GetIdentifiable(); Method = from; Target = to; DelegateTarget = target; Type type = (from as MethodInfo)?.ReturnType ?? typeof(void); if ((object)to.ReturnType != type && !Extensions.IsCompatible(to.ReturnType, type)) { throw new InvalidOperationException($"Return type of hook for {from} doesn't match, must be {((from as MethodInfo)?.ReturnType ?? typeof(void)).FullName}"); } if (target == null && !to.IsStatic) { throw new InvalidOperationException($"Hook for method {from} must be static, or you must pass a target instance."); } ParameterInfo[] parameters = Target.GetParameters(); ParameterInfo[] parameters2 = Method.GetParameters(); Type[] array; if (!Method.IsStatic) { array = new Type[parameters2.Length + 1]; array[0] = Extensions.GetThisParamType(Method); for (int i = 0; i < parameters2.Length; i++) { array[i + 1] = parameters2[i].ParameterType; } } else { array = new Type[parameters2.Length]; for (int j = 0; j < parameters2.Length; j++) { array[j] = parameters2[j].ParameterType; } } Type type2 = null; if (parameters.Length == array.Length + 1 && typeof(Delegate).IsAssignableFrom(parameters[0].ParameterType)) { type2 = (_OrigDelegateType = parameters[0].ParameterType); } else if (parameters.Length != array.Length) { throw new InvalidOperationException($"Parameter count of hook for {from} doesn't match, must be {array.Length}"); } for (int k = 0; k < array.Length; k++) { Type type3 = array[k]; Type parameterType = parameters[k + (((object)type2 != null) ? 1 : 0)].ParameterType; if (!Extensions.IsCompatible(type3, parameterType)) { throw new InvalidOperationException($"Parameter #{k} of hook for {from} doesn't match, must be {type3.FullName} or related"); } } MethodInfo methodInfo = (_OrigDelegateInvoke = type2?.GetMethod("Invoke")); DynamicMethodDefinition val = new DynamicMethodDefinition($"Hook<{Extensions.GetID(Method, (string)null, (string)null, true, false, true)}>?{GetHashCode()}", (Method as MethodInfo)?.ReturnType ?? typeof(void), array); DynamicMethodDefinition val2 = val; DynamicMethodDefinition val3 = val; try { ILProcessor iLProcessor = val2.GetILProcessor(); if (target != null) { _RefTarget = DynamicMethodHelper.EmitReference<object>(iLProcessor, target); } if ((object)type2 != null) { _RefTrampoline = DynamicMethodHelper.EmitReference<Delegate>(iLProcessor, (Delegate)null); } for (int l = 0; l < array.Length; l++) { iLProcessor.Emit(OpCodes.Ldarg, l); } Extensions.Emit(iLProcessor, OpCodes.Call, Target); iLProcessor.Emit(OpCodes.Ret); TargetReal = val2.Generate().Pin(); } finally { ((IDisposable)val3)?.Dispose(); } if ((object)type2 != null) { ParameterInfo[] parameters3 = methodInfo.GetParameters(); Type[] array2 = new Type[parameters3.Length]; for (int m = 0; m < parameters3.Length; m++) { array2[m] = parameters3[m].ParameterType; } DynamicMethodDefinition val4 = new DynamicMethodDefinition($"Chain:TMP<{Extensions.GetID(Method, (string)null, (string)null, true, false, true)}>?{GetHashCode()}", methodInfo?.ReturnType ?? typeof(void), array2); val2 = val4; val3 = val4; try { ILProcessor iLProcessor = val2.GetILProcessor(); _RefTrampolineTmp = DynamicMethodHelper.EmitReference<Delegate>(iLProcessor, (Delegate)null); iLProcessor.Emit(OpCodes.Brfalse, iLProcessor.Body.Instructions[0]); DynamicMethodHelper.EmitGetReference<Delegate>(iLProcessor, _RefTrampolineTmp.Value); for (int n = 0; n < array.Length; n++) { iLProcessor.Emit(OpCodes.Ldarg, n); } Extensions.Emit(iLProcessor, OpCodes.Callvirt, (MethodBase)methodInfo); iLProcessor.Emit(OpCodes.Ret); DynamicMethodHelper.SetReference(_RefTrampoline.Value, (object)Extensions.CreateDelegate((MethodBase)val2.Generate(), type2)); } finally { ((IDisposable)val3)?.Dispose(); } } _Detour = new Detour(Method, TargetReal, new DetourConfig { ManualApply = true, Priority = config.Priority, ID = config.ID, Before = config.Before, After = config.After }); _UpdateOrig(null); if (!config.ManualApply) { Apply(); } } public Hook(MethodBase from, MethodInfo to, object target, HookConfig config) : this(from, to, target, ref config) { } public Hook(MethodBase from, MethodInfo to, object target) : this(from, to, target, DetourContext.Current?.HookConfig ?? default(HookConfig)) { } public Hook(MethodBase from, MethodInfo to, ref HookConfig config) : this(from, to, null, ref config) { } public Hook(MethodBase from, MethodInfo to, HookConfig config) : this(from, to, null, ref config) { } public Hook(MethodBase from, MethodInfo to) : this(from, to, null) { } public Hook(MethodBase method, IntPtr to, ref HookConfig config) : this(method, DetourHelper.GenerateNativeProxy(to, method), null, ref config) { } public Hook(MethodBase method, IntPtr to, HookConfig config) : this(method, DetourHelper.GenerateNativeProxy(to, method), null, ref config) { } public Hook(MethodBase method, IntPtr to) : this(method, DetourHelper.GenerateNativeProxy(to, method), null) { } public Hook(MethodBase method, Delegate to, ref HookConfig config) : this(method, to.Method, to.Target, ref config) { } public Hook(MethodBase method, Delegate to, HookConfig config) : this(method, to.Method, to.Target, ref config) { } public Hook(MethodBase method, Delegate to) : this(method, to.Method, to.Target) { } public Hook(Delegate from, IntPtr to, ref HookConfig config) : this(from.Method, to, ref config) { } public Hook(Delegate from, IntPtr to, HookConfig config) : this(from.Method, to, ref config) { } public Hook(Delegate from, IntPtr to) : this(from.Method, to) { } public Hook(Delegate from, Delegate to, ref HookConfig config) : this(from.Method, to, ref config) { } public Hook(Delegate from, Delegate to, HookConfig config) : this(from.Method, to, ref config) { } public Hook(Delegate from, Delegate to) : this(from.Method, to) { } public Hook(Expression from, IntPtr to, ref HookConfig config) : this(((MethodCallExpression)from).Method, to, ref config) { } public Hook(Expression from, IntPtr to, HookConfig config) : this(((MethodCallExpression)from).Method, to, ref config) { } public Hook(Expression from, IntPtr to) : this(((MethodCallExpression)from).Method, to) { } public Hook(Expression from, Delegate to, ref HookConfig config) : this(((MethodCallExpression)from).Method, to, ref config) { } public Hook(Expression from, Delegate to, HookConfig config) : this(((MethodCallExpression)from).Method, to, ref config) { } public Hook(Expression from, Delegate to) : this(((MethodCallExpression)from).Method, to) { } public Hook(Expression<Action> from, IntPtr to, ref HookConfig config) : this(from.Body, to, ref config) { } public Hook(Expression<Action> from, IntPtr to, HookConfig config) : this(from.Body, to, ref config) { } public Hook(Expression<Action> from, IntPtr to) : this(from.Body, to) { } public Hook(Expression<Action> from, Delegate to, ref HookConfig config) : this(from.Body, to, ref config) { } public Hook(Expression<Action> from, Delegate to, HookConfig config) : this(from.Body, to, ref config) { } public Hook(Expression<Action> from, Delegate to) : this(from.Body, to) { } public void Apply() { if (!IsValid) { throw new ObjectDisposedException("Hook"); } if (!IsApplied) { Func<Hook, MethodBase, MethodBase, object, bool> onDetour = OnDetour; if (onDetour != null && !Extensions.InvokeWhileTrue((MulticastDelegate)onDetour, new object[4] { this, Method, Target, DelegateTarget })) { return; } } _Detour.Apply(); } public void Undo() { if (!IsValid) { throw new ObjectDisposedException("Hook"); } if (IsApplied) { Func<Hook, bool> onUndo = OnUndo; if (onUndo != null && !Extensions.InvokeWhileTrue((MulticastDelegate)onUndo, new object[1] { this })) { return; } } _Detour.Undo(); if (!IsValid) { _Free(); } } public void Free() { if (IsValid) { _Detour.Free(); _Free(); } } public void Dispose() { if (IsValid) { Undo(); Free(); } } private void _Free() { if (_RefTarget.HasValue) { DynamicMethodHelper.FreeReference(_RefTarget.Value); } if (_RefTrampoline.HasValue) { DynamicMethodHelper.FreeReference(_RefTrampoline.Value); } if (_RefTrampolineTmp.HasValue) { DynamicMethodHelper.FreeReference(_RefTrampolineTmp.Value); } TargetReal.Unpin(); } public MethodBase GenerateTrampoline(MethodBase signature = null) { Func<Hook, MethodBase, MethodBase> onGenerateTrampoline = OnGenerateTrampoline; MethodBase methodBase = ((onGenerateTrampoline != null) ? Extensions.InvokeWhileNull<MethodBase>((MulticastDelegate)onGenerateTrampoline, new object[2] { this, signature }) : null); if ((object)methodBase != null) { return methodBase; } return _Detour.GenerateTrampoline(signature); } public T GenerateTrampoline<T>() where T : Delegate { if (!typeof(Delegate).IsAssignableFrom(typeof(T))) { throw new InvalidOperationException($"Type {typeof(T)} not a delegate type."); } return Extensions.CreateDelegate(GenerateTrampoline(typeof(T).GetMethod("Invoke")), typeof(T)) as T; } internal void _UpdateOrig(MethodBase invoke) { if ((object)_OrigDelegateType != null) { Delegate @delegate = Extensions.CreateDelegate(invoke ?? GenerateTrampoline(_OrigDelegateInvoke), _OrigDelegateType); DynamicMethodHelper.SetReference(_RefTrampoline.Value, (object)@delegate); DynamicMethodHelper.SetReference(_RefTrampolineTmp.Value, (object)@delegate); } } } public class Hook<T> : Hook { public Hook(Expression<Action> from, T to, ref HookConfig config) : base(from.Body, to as Delegate, ref config) { } public Hook(Expression<Action> from, T to, HookConfig config) : base(from.Body, to as Delegate, ref config) { } public Hook(Expression<Action> from, T to) : base(from.Body, to as Delegate) { } public Hook(Expression<Func<T>> from, IntPtr to, ref HookConfig config) : base(from.Body, to, ref config) { } public Hook(Expression<Func<T>> from, IntPtr to, HookConfig config) : base(from.Body, to, ref config) { } public Hook(Expression<Func<T>> from, IntPtr to) : base(from.Body, to) { } public Hook(Expression<Func<T>> from, Delegate to, ref HookConfig config) : base(from.Body, to, ref config) { } public Hook(Expression<Func<T>> from, Delegate to, HookConfig config) : base(from.Body, to, ref config) { } public Hook(Expression<Func<T>> from, Delegate to) : base(from.Body, to) { } public Hook(T from, IntPtr to, ref HookConfig config) : base(from as Delegate, to, ref config) { } public Hook(T from, IntPtr to, HookConfig config) : base(from as Delegate, to, ref config) { } public Hook(T from, IntPtr to) : base(from as Delegate, to) { } public Hook(T from, T to, ref HookConfig config) : base(from as Delegate, to as Delegate, ref config) { } public Hook(T from, T to, HookConfig config) : base(from as Delegate, to as Delegate, ref config) { } public Hook(T from, T to) : base(from as Delegate, to as Delegate) { } } public class Hook<TFrom, TTo> : Hook { public Hook(Expression<Func<TFrom>> from, TTo to, ref HookConfig config) : base(from.Body, to as Delegate) { } public Hook(Expression<Func<TFrom>> from, TTo to, HookConfig config) : base(from.Body, to as Delegate) { } public Hook(Expression<Func<TFrom>> from, TTo to) : base(from.Body, to as Delegate) { } public Hook(TFrom from, TTo to, ref HookConfig config) : base(from as Delegate, to as Delegate) { } public Hook(TFrom from, TTo to, HookConfig config) : base(from as Delegate, to as Delegate) { } public Hook(TFrom from, TTo to) : base(from as Delegate, to as Delegate) { } } public interface IDetour : IDisposable { bool IsValid { get; } bool IsApplied { get; } void Apply(); void Undo(); void Free(); MethodBase GenerateTrampoline(MethodBase signature = null); T GenerateTrampoline<T>() where T : Delegate; } public interface ISortableDetour : IDetour, IDisposable { uint GlobalIndex { get; } int Priority { get; set; } string ID { get; set; } IEnumerable<string> Before { get; set; } IEnumerable<string> After { get; set; } } public struct ILHookConfig { public bool ManualApply; public int Priority; public string ID; public IEnumerable<string> Before; public IEnumerable<string> After; } public class ILHook : ISortableDetour, IDetour, IDisposable { private class Context { public List<ILHook> Chain = new List<ILHook>(); public HashSet<ILContext> Active = new HashSet<ILContext>(); public MethodBase Method; public Detour Detour; public Context(MethodBase method) { Method = method; } public void Add(ILHook hook) { List<ILHook> chain = Chain; lock (chain) { chain.Add(hook); } } public void Remove(ILHook hook) { List<ILHook> chain = Chain; lock (chain) { chain.Remove(hook); if (chain.Count == 0) { Refresh(); lock (_Map) { _Map.Remove(Method); return; } } } } public void Refresh() { //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown List<ILHook> chain = Chain; lock (chain) { foreach (ILContext item in Active) { item.Dispose(); } Active.Clear(); Detour?.Dispose(); Detour = null; if (chain.Count == 0) { return; } bool flag = false; foreach (ILHook item2 in chain) { if (item2.IsApplied) { flag = true; break; } } if (!flag) { return; } DetourSorter<ILHook>.Sort(chain); DynamicMethodDefinition val = new DynamicMethodDefinition(Method); MethodBase to; try { MethodDefinition definition = val.Definition; foreach (ILHook item3 in chain) { if (item3.IsApplied) { InvokeManipulator(definition, item3.Manipulator); } } to = val.Generate(); } finally { ((IDisposable)val)?.Dispose(); } Detour = new Detour(Method, to, ref ILDetourConfig); } } private void InvokeManipulator(MethodDefinition def, Manipulator cb) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ILContext val = new ILContext(def); val.ReferenceBag = (IILReferenceBag)(object)RuntimeILReferenceBag.Instance; val.Invoke(cb); if (val.IsReadOnly) { val.Dispose(); return; } val.MakeReadOnly(); Active.Add(val); } } public static Func<ILHook, MethodBase, Manipulator, bool> OnDetour; public static Func<ILHook, bool> OnUndo; private static DetourConfig ILDetourConfig = new DetourConfig { Priority = -268435456, Before = new string[1] { "*" } }; private static Dictionary<MethodBase, Context> _Map = new Dictionary<MethodBase, Context>(); private static uint _GlobalIndexNext = 0u; private readonly uint _GlobalIndex; private int _Priority; private string _ID; private List<string> _Before = new List<string>(); private ReadOnlyCollection<string> _BeforeRO; private List<string> _After = new List<string>(); private ReadOnlyCollection<string> _AfterRO; public readonly MethodBase Method; public readonly Manipulator Manipulator; private Context _Ctx { get { if (!_Map.TryGetValue(Method, out var value)) { return null; } return value; } } public bool IsValid => Index != -1; public bool IsApplied { get; private set; } public int Index => _Ctx?.Chain.IndexOf(this) ?? (-1); public int MaxIndex => _Ctx?.Chain.Count ?? (-1); public uint GlobalIndex => _GlobalIndex; public int Priority { get { return _Priority; } set { if (_Priority != value) { _Priority = value; _Ctx.Refresh(); } } } public string ID { get { return _ID; } set { if (string.IsNullOrEmpty(value)) { MethodInfo method = ((Delegate)(object)Manipulator).Method; value = (((object)method != null) ? Extensions.GetID((MethodBase)method, (string)null, (string)null, true, false, true) : null) ?? GetHashCode().ToString(CultureInfo.InvariantCulture); } if (!(_ID == value)) { _ID = value; _Ctx.Refresh(); } } } public IEnumerable<string> Before { get { return _BeforeRO ?? (_BeforeRO = _Before.AsReadOnly()); } set { lock (_Before) { _Before.Clear(); if (value != null) { foreach (string item in value) { _Before.Add(item); } } _Ctx.Refresh(); } } } public IEnumerable<string> After { get { return _AfterRO ?? (_AfterRO = _After.AsReadOnly()); } set { lock (_After) { _After.Clear(); if (value != null) { foreach (string item in value) { _After.Add(item); } } _Ctx.Refresh(); } } } public ILHook(MethodBase from, Manipulator manipulator, ref ILHookConfig config) { from = from.GetIdentifiable(); Method = from.Pin(); Manipulator = manipulator; _GlobalIndex = _GlobalIndexNext++; _Priority = config.Priority; _ID = config.ID; if (config.Before != null) { foreach (string item in config.Before) { _Before.Add(item); } } if (config.After != null) { foreach (string item2 in config.After) { _After.Add(item2); } } Context value; lock (_Map) { if (!_Map.TryGetValue(Method, out value)) { value = (_Map[Method] = new Context(Method)); } } lock (value) { value.Add(this); } if (!config.ManualApply) { Apply(); } } public ILHook(MethodBase from, Manipulator manipulator, ILHookConfig config) : this(from, manipulator, ref config) { } public ILHook(MethodBase from, Manipulator manipulator) : this(from, manipulator, DetourContext.Current?.ILHookConfig ?? default(ILHookConfig)) { } public void Apply() { if (!IsValid) { throw new ObjectDisposedException("ILHook"); } if (!IsApplied) { Func<ILHook, MethodBase, Manipulator, bool> onDetour = OnDetour; if (onDetour == null || Extensions.InvokeWhileTrue((MulticastDelegate)onDetour, new object[3] { this, Method, Manipulator })) { IsApplied = true; _Ctx.Refresh(); } } } public void Undo() { if (!IsValid) { throw new ObjectDisposedException("ILHook"); } if (IsApplied) { Func<ILHook, bool> onUndo = OnUndo; if (onUndo == null || Extensions.InvokeWhileTrue((MulticastDelegate)onUndo, new object[1] { this })) { IsApplied = false; _Ctx.Refresh(); } } } public void Free() { if (IsValid) { Undo(); _Ctx.Remove(this); Method.Unpin(); } } public void Dispose() { if (IsValid) { Undo(); Free(); } } public MethodBase GenerateTrampoline(MethodBase signature = null) { throw new NotSupportedException(); } public T GenerateTrampoline<T>() where T : Delegate { throw new NotSupportedException(); } } public struct NativeDetourConfig { public bool ManualApply; public bool SkipILCopy; } public class NativeDetour : IDetour, IDisposable { public static Func<NativeDetour, MethodBase, IntPtr, IntPtr, bool> OnDetour; public static Func<NativeDetour, bool> OnUndo; public static Func<NativeDetour, MethodBase, MethodBase> OnGenerateTrampoline; private NativeDetourData _Data; public readonly MethodBase Method; private readonly MethodInfo _BackupMethod; private readonly IntPtr _BackupNative; private HashSet<MethodBase> _Pinned = new HashSet<MethodBase>(); public bool IsValid { get; private set; } public bool IsApplied { get; private set; } public NativeDetourData Data => _Data; public NativeDetour(MethodBase method, IntPtr from, IntPtr to, ref NativeDetourConfig config) { if (from == to) { throw new InvalidOperationException($"Cannot detour from a location to itself! (from: {from:X16} to: {to:X16} method: {method})"); } method = method?.GetIdentifiable(); Method = method; Func<NativeDetour, MethodBase, IntPtr, IntPtr, bool> onDetour = OnDetour; if (onDetour == null || Extensions.InvokeWhileTrue((MulticastDelegate)onDetour, new object[4] { this, method, from, to })) { IsValid = true; _Data = DetourHelper.Native.Create(from, to); if (!config.SkipILCopy) { method?.TryCreateILCopy(out _BackupMethod); } _BackupNative = DetourHelper.Native.MemAlloc(_Data.Size); if (!config.ManualApply) { Apply(); } } } public NativeDetour(MethodBase method, IntPtr from, IntPtr to, NativeDetourConfig config) : this(method, from, to, ref config) { } public NativeDetour(MethodBase method, IntPtr from, IntPtr to) : this(method, from, to, default(NativeDetourConfig)) { } public NativeDetour(IntPtr from, IntPtr to, ref NativeDetourConfig config) : this(null, from, to, ref config) { } public NativeDetour(IntPtr from, IntPtr to, NativeDetourConfig config) : this(null, from, to, ref config) { } public NativeDetour(IntPtr from, IntPtr to) : this(null, from, to) { } public NativeDetour(MethodBase from, IntPtr to, ref NativeDetourConfig config) : this(from, from.Pin().GetNativeStart(), to, ref config) { _Pinned.Add(from); } public NativeDetour(MethodBase from, IntPtr to, NativeDetourConfig config) : this(from, from.Pin().GetNativeStart(), to, ref config) { _Pinned.Add(from); } public NativeDetour(MethodBase from, IntPtr to) : this(from, from.Pin().GetNativeStart(), to) { _Pinned.Add(from); } public NativeDetour(IntPtr from, MethodBase to, ref NativeDetourConfig config) : this(from, to.Pin().GetNativeStart(), ref config) { _Pinned.Add(to); } public NativeDetour(IntPtr from, MethodBase to, NativeDetourConfig config) : this(from, to.Pin().GetNativeStart(), ref config) { _Pinned.Add(to); } public NativeDetour(IntPtr from, MethodBase to) : this(from, to.Pin().GetNativeStart()) { _Pinned.Add(to); } public NativeDetour(MethodBase from, MethodBase to, ref NativeDetourConfig config) : this(from.Pin().GetNativeStart(), DetourHelper.Runtime.GetDetourTarget(from, to), ref config) { _Pinned.Add(from); } public NativeDetour(MethodBase from, MethodBase to, NativeDetourConfig config) : this(from.Pin().GetNativeStart(), DetourHelper.Runtime.GetDetourTarget(from, to), ref config) { _Pinned.Add(from); } public NativeDetour(MethodBase from, MethodBase to) : this(from.Pin().GetNativeStart(), DetourHelper.Runtime.GetDetourTarget(from, to)) { _Pinned.Add(from); } public NativeDetour(Delegate from, IntPtr to, ref NativeDetourConfig config) : this(from.Method, to, ref config) { } public NativeDetour(Delegate from, IntPtr to, NativeDetourConfig config) : this(from.Method, to, ref config) { } public NativeDetour(Delegate from, IntPtr to) : this(from.Method, to) { } public NativeDetour(IntPtr from, Delegate to, ref NativeDetourConfig config) : this(from, to.Method, ref config) { } public NativeDetour(IntPtr from, Delegate to, NativeDetourConfig config) : this(from, to.Method, ref config) { } public NativeDetour(IntPtr from, Delegate to) : this(from, to.Method) { } public NativeDetour(Delegate from, Delegate to, ref NativeDetourConfig config) : this(from.Method, to.Method, ref config) { } public NativeDetour(Delegate from, Delegate to, NativeDetourConfig config) : this(from.Method, to.Method, ref config) { } public NativeDetour(Delegate from, Delegate to) : this(from.Method, to.Method) { } public void Apply() { if (!IsValid) { throw new ObjectDisposedException("NativeDetour"); } if (!IsApplied) { IsApplied = true; DetourHelper.Native.Copy(_Data.Method, _BackupNative, _Data.Type); DetourHelper.Native.MakeWritable(_Data); DetourHelper.Native.Apply(_Data); DetourHelper.Native.MakeExecutable(_Data); DetourHelper.Native.FlushICache(_Data); } } public void Undo() { if (!IsValid) { throw new ObjectDisposedException("NativeDetour"); } Func<NativeDetour, bool> onUndo = OnUndo; if ((onUndo == null || Extensions.InvokeWhileTrue((MulticastDelegate)onUndo, new object[1] { this })) && IsApplied) { IsApplied = false; DetourHelper.Native.MakeWritable(_Data); DetourHelper.Native.Copy(_BackupNative, _Data.Method, _Data.Type); DetourHelper.Native.MakeExecutable(_Data); DetourHelper.Native.FlushICache(_Data); } } public void ChangeSource(IntPtr newSource) { if (!IsValid) { throw new ObjectDisposedException("NativeDetour"); } NativeDetourData data = _Data; _Data = DetourHelper.Native.Create(newSource, _Data.Target); IsApplied = false; Apply(); DetourHelper.Native.Free(data); } public void ChangeTarget(IntPtr newTarget) { if (!IsValid) { throw new ObjectDisposedException("NativeDetour"); } NativeDetourData data = _Data; _Data = DetourHelper.Native.Create(_Data.Method, newTarget); IsApplied = false; Apply(); DetourHelper.Native.Free(data); } public void Free() { if (!IsValid) { return; } IsValid = false; DetourHelper.Native.MemFree(_BackupNative); DetourHelper.Native.Free(_Data); if (IsApplied) { return; } foreach (MethodBase item in _Pinned) { item.Unpin(); } _Pinned.Clear(); } public void Dispose() { if (IsValid) { Undo(); Free(); } } public MethodBase GenerateTrampoline(MethodBase signature = null) { //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Expected O, but got Unknown //IL_0198: Expected O, but got Unknown //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) Func<NativeDetour, MethodBase, MethodBase> onGenerateTrampoline = OnGenerateTrampoline; MethodBase methodBase = ((onGenerateTrampoline != null) ? Extensions.InvokeWhileNull<MethodBase>((MulticastDelegate)onGenerateTrampoline, new object[2] { this, signature }) : null); if ((object)methodBase != null) { return methodBase; } if (!IsValid) { throw new ObjectDisposedException("NativeDetour"); } if ((object)_BackupMethod != null) { return _BackupMethod; } if ((object)signature == null) { throw new ArgumentNullException("A signature must be given if the NativeDetour doesn't hold a reference to a managed method."); } MethodBase methodBase2 = Method; if ((object)methodBase2 == null) { methodBase2 = DetourHelper.GenerateNativeProxy(_Data.Method, signature); } Type type = (signature as MethodInfo)?.ReturnType ?? typeof(void); ParameterInfo[] parameters = signature.GetParameters(); Type[] array = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = parameters[i].ParameterType; } MethodBase method = Method; DynamicMethodDefinition val = new DynamicMethodDefinition(string.Format("Trampoline:Native<{0}>?{1}", (((object)method != null) ? Extensions.GetID(method, (string)null, (string)null, true, false, true) : null) ?? ((long)_Data.Method).ToString("X16", CultureInfo.InvariantCulture), GetHashCode()), type, array); try { ILProcessor iLProcessor = val.GetILProcessor(); ExceptionHandler val2 = new ExceptionHandler((ExceptionHandlerType)2); iLProcessor.Body.ExceptionHandlers.Add(val2); iLProcessor.EmitDetourCopy(_BackupNative, _Data.Method, _Data.Type); VariableDefinition val3 = null; if ((object)type != typeof(void)) { Collection<VariableDefinition> variables = iLProcessor.Body.Variables; VariableDefinition val4 = new VariableDefinition(Extensions.Import(iLProcessor, type)); val3 = val4; variables.Add(val4); } int count = iLProcessor.Body.Instructions.Count; for (int j = 0; j < array.Length; j++) { iLProcessor.Emit(OpCodes.Ldarg, j); } if (methodBase2 is MethodInfo) { Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)(MethodInfo)methodBase2); } else { if (!(methodBase2 is ConstructorInfo)) { throw new NotSupportedException("Method type " + methodBase2.GetType().FullName + " not supported."); } Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)(ConstructorInfo)methodBase2); } if (val3 != null) { iLProcessor.Emit(OpCodes.Stloc, val3); } Extensions.Emit(iLProcessor, OpCodes.Leave, (object)null); Instruction obj = iLProcessor.Body.Instructions[iLProcessor.Body.Instructions.Count - 1]; int count2 = iLProcessor.Body.Instructions.Count; _ = iLProcessor.Body.Instructions.Count; iLProcessor.EmitDetourApply(_Data); int count3 = iLProcessor.Body.Instructions.Count; Instruction val5 = null; if (val3 != null) { iLProcessor.Emit(OpCodes.Ldloc, val3); val5 = iLProcessor.Body.Instructions[iLProcessor.Body.Instructions.Count - 1]; } iLProcessor.Emit(OpCodes.Ret); val5 = val5 ?? iLProcessor.Body.Instructions[iLProcessor.Body.Instructions.Count - 1]; obj.Operand = val5; val2.TryStart = iLProcessor.Body.Instructions[count]; val2.TryEnd = iLProcessor.Body.Instructions[count2]; val2.HandlerStart = iLProcessor.Body.Instructions[count2]; val2.HandlerEnd = iLProcessor.Body.Instructions[count3]; return val.Generate(); } finally { ((IDisposable)val)?.Dispose(); } } public T GenerateTrampoline<T>() where T : Delegate { if (!typeof(Delegate).IsAssignableFrom(typeof(T))) { throw new InvalidOperationException($"Type {typeof(T)} not a delegate type."); } return Extensions.CreateDelegate(GenerateTrampoline(typeof(T).GetMethod("Invoke")), typeof(T)) as T; } } internal static class DetourSorter<T> where T : ISortableDetour { private sealed class Group { public readonly string StepName; public List<T> Items = new List<T>(); public List<Group> Children = new List<Group>(); public List<Group> NonMatching = new List<Group>(); public Group(string stepName) { StepName = stepName; } public Group(string stepName, List<T> items) : this(stepName) { Items.AddRange(items); } public void Step(Step step) { if (Children.Count != 0) { foreach (Group child in Children) { child.Step(step); } return; } if (Items.Count <= 1) { return; } if ((Items.Count == 2 && !((!step.IsFlat) ?? false)) || step.IsFlat.GetValueOrDefault()) { Items.Sort(step); return; } string name = step.GetType().Name; Group group = new Group(name, new List<T> { Items[0] }); Children.Add(group); for (int i = 1; i < Items.Count; i++) { T val = Items[i]; if (step.Any(group.Items, val)) { Group group2 = group; group = null; if (Children.Count > 1) { foreach (Group child2 in Children) { if (child2 != group2 && !step.Any(child2.Items, val) && !step.Any(child2.NonMatching, val)) { group = child2; break; } } } if (group == null) { group = new Group(name); Children.Add(group); group.NonMatching.Add(group2); group2.NonMatching.Add(group); } } group.Items.Add(val); } if (Children.Count == 1) { Children.Clear(); } else { Children.Sort(step.ForGroup); } } public void Flatten() { if (Children.Count != 0) { Items.Clear(); Flatten(Items); } } public void Flatten(List<T> total) { if (Children.Count == 0) { total.AddRange(Items); return; } foreach (Group child in Children) { child.Flatten(total); } } } private abstract class Step : IComparer<T> { public abstract GroupComparer ForGroup { get; } public virtual bool? IsFlat => null; public abstract int Compare(T x, T y); public bool Any(List<T> xlist, T y) { foreach (T item in xlist) { if (Compare(item, y) != 0) { return true; } } return false; } public bool Any(List<Group> groups, T y) { foreach (Group group in groups) { if (Any(group.Items, y)) { return true; } } return false; } } private sealed class GroupComparer : IComparer<Group> { public Step Step; public GroupComparer(Step step) { Step = step; } public int Compare(Group xg, Group yg) { foreach (T item in xg.Items) { foreach (T item2 in yg.Items) { int result; if ((result = Step.Compare(item, item2)) != 0) { return result; } } } return 0; } } private sealed class BeforeAfterAll : Step { public static readonly BeforeAfterAll _ = new BeforeAfterAll(); public static readonly GroupComparer Group = new GroupComparer(_); public override GroupComparer ForGroup => Group; public override bool? IsFlat => false; public override int Compare(T a, T b) { if (a.Before.Contains("*") && !b.Before.Contains("*")) { return -1; } if (!a.Before.Contains("*") && b.Before.Contains("*")) { return 1; } if (a.After.Contains("*") && !b.After.Contains("*")) { return 1; } if (!a.After.Contains("*") && b.After.Contains("*")) { return -1; } return 0; } } private sealed class BeforeAfter : Step { public static readonly BeforeAfter _ = new BeforeAfter(); public static readonly GroupComparer Group = new GroupComparer(_); public override GroupComparer ForGroup => Group; public override int Compare(T a, T b) { if (a.Before.Contains(b.ID)) { return -1; } if (a.After.Contains(b.ID)) { return 1; } if (b.Before.Contains(a.ID)) { return 1; } if (b.After.Contains(a.ID)) { return -1; } return 0; } } private sealed class Priority : Step { public static readonly Priority _ = new Priority(); public static readonly GroupComparer Group = new GroupComparer(_); public override GroupComparer ForGroup => Group; public override int Compare(T a, T b) { int num = a.Priority - b.Priority; if (num != 0) { return num; } return 0; } } private sealed class GlobalIndex : Step { public static readonly GlobalIndex _ = new GlobalIndex(); public static readonly GroupComparer Group = new GroupComparer(_); public override GroupComparer ForGroup => Group; public override int Compare(T a, T b) { return a.GlobalIndex.CompareTo(b.GlobalIndex); } } public static void Sort(List<T> detours) { lock (detours) { if (detours.Count > 1) { detours.Sort(GlobalIndex._); Group group = new Group("Init", detours); group.Step(BeforeAfterAll._); group.Step(BeforeAfter._); group.Step(Priority._); group.Step(GlobalIndex._); detours.Clear(); group.Flatten(detours); } } } } public static class DetourHelper { private static readonly object _RuntimeLock = new object(); private static bool _RuntimeInit = false; private static IDetourRuntimePlatform _Runtime; private static readonly object _NativeLock = new object(); private static bool _NativeInit = false; private static IDetourNativePlatform _Native; private static readonly FieldInfo _f_Native = typeof(DetourHelper).GetField("_Native", BindingFlags.Static | BindingFlags.NonPublic); private static readonly MethodInfo _m_ToNativeDetourData = typeof(DetourHelper).GetMethod("ToNativeDetourData", BindingFlags.Static | BindingFlags.NonPublic); private static readonly MethodInfo _m_Copy = typeof(IDetourNativePlatform).GetMethod("Copy"); private static readonly MethodInfo _m_Apply = typeof(IDetourNativePlatform).GetMethod("Apply"); private static readonly ConstructorInfo _ctor_Exception = typeof(Exception).GetConstructor(new Type[1] { typeof(string) }); public static IDetourRuntimePlatform Runtime { get { if (_Runtime != null) { return _Runtime; } lock (_RuntimeLock) { if (_Runtime != null) { return _Runtime; } if (_RuntimeInit) { return null; } _RuntimeInit = true; if ((object)Type.GetType("Mono.Runtime") != null) { _Runtime = new DetourRuntimeMonoPlatform(); } else if (typeof(object).Assembly.GetName().Name == "System.Private.CoreLib") { _Runtime = DetourRuntimeNETCorePlatform.Create(); } else { _Runtime = new DetourRuntimeNETPlatform(); } return _Runtime; } } set { _Runtime = value; } } public static IDetourNativePlatform Native { get { if (_Native != null) { return _Native; } lock (_NativeLock) { if (_Native != null) { return _Native; } if (_NativeInit) { return null; } _NativeInit = true; IDetourNativePlatform detourNativePlatform = ((!PlatformHelper.Is((Platform)65536)) ? ((IDetourNativePlatform)new DetourNativeX86Platform()) : ((IDetourNativePlatform)new DetourNativeARMPlatform())); if (PlatformHelper.Is((Platform)37)) { return _Native = new DetourNativeWindowsPlatform(detourNativePlatform); } if ((object)Type.GetType("Mono.Runtime") != null) { try { return _Native = new DetourNativeMonoPlatform(detourNativePlatform, "libmonosgen-2.0." + PlatformHelper.LibrarySuffix); } catch { } } string environmentVariable = Environment.GetEnvironmentVariable("MONOMOD_RUNTIMEDETOUR_MONOPOSIXHELPER"); if (((object)Type.GetType("Mono.Runtime") != null && environmentVariable != "0") || environmentVariable == "1") { try { return _Native = new DetourNativeMonoPosixPlatform(detourNativePlatform); } catch { } } try { return _Native = new DetourNativeLibcPlatform(detourNativePlatform); } catch { } return detourNativePlatform; } } set { _Native = value; } } public static void MakeWritable(this IDetourNativePlatform plat, NativeDetourData detour) { plat.MakeWritable(detour.Method, detour.Size); } public static void MakeExecutable(this IDetourNativePlatform plat, NativeDetourData detour) { plat.MakeExecutable(detour.Method, detour.Size); } public static void FlushICache(this IDetourNativePlatform plat, NativeDetourData detour) { plat.FlushICache(detour.Method, detour.Size); } public unsafe static void Write(this IntPtr to, ref int offs, byte value) { *(byte*)((long)to + offs) = value; offs++; } public unsafe static void Write(this IntPtr to, ref int offs, ushort value) { *(ushort*)((long)to + offs) = value; offs += 2; } public unsafe static void Write(this IntPtr to, ref int offs, uint value) { *(uint*)((long)to + offs) = value; offs += 4; } public unsafe static void Write(this IntPtr to, ref int offs, ulong value) { *(ulong*)((long)to + offs) = value; offs += 8; } public static MethodBase GetIdentifiable(this MethodBase method) { return Runtime.GetIdentifiable(method); } public static IntPtr GetNativeStart(this MethodBase method) { return Runtime.GetNativeStart(method); } public static IntPtr GetNativeStart(this Delegate method) { return method.Method.GetNativeStart(); } public static IntPtr GetNativeStart(this Expression method) { return ((MethodCallExpression)method).Method.GetNativeStart(); } public static MethodInfo CreateILCopy(this MethodBase method) { return Runtime.CreateCopy(method); } public static bool TryCreateILCopy(this MethodBase method, out MethodInfo dm) { return Runtime.TryCreateCopy(method, out dm); } public static T Pin<T>(this T method) where T : MethodBase { Runtime.Pin(method); return method; } public static T Unpin<T>(this T method) where T : MethodBase { Runtime.Unpin(method); return method; } public static MethodInfo GenerateNativeProxy(IntPtr target, MethodBase signature) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown Type type = (signature as MethodInfo)?.ReturnType ?? typeof(void); ParameterInfo[] parameters = signature.GetParameters(); Type[] array = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = parameters[i].ParameterType; } DynamicMethodDefinition val = new DynamicMethodDefinition("Native<" + ((long)target).ToString("X16", CultureInfo.InvariantCulture) + ">", type, array); MethodInfo methodInfo; try { methodInfo = val.StubCriticalDetour().Generate().Pin(); } finally { ((IDisposable)val)?.Dispose(); } NativeDetourData detour = Native.Create(methodInfo.GetNativeStart(), target); Native.MakeWritable(detour); Native.Apply(detour); Native.MakeExecutable(detour); Native.FlushICache(detour); Native.Free(detour); return methodInfo; } private static NativeDetourData ToNativeDetourData(IntPtr method, IntPtr target, uint size, byte type, IntPtr extra) { NativeDetourData result = default(NativeDetourData); result.Method = method; result.Target = target; result.Size = size; result.Type = type; result.Extra = extra; return result; } public static DynamicMethodDefinition StubCriticalDetour(this DynamicMethodDefinition dm) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) ILProcessor iLProcessor = dm.GetILProcessor(); ModuleDefinition module = ((MemberReference)iLProcessor.Body.Method).Module; for (int i = 0; i < 32; i++) { iLProcessor.Emit(OpCodes.Nop); } iLProcessor.Emit(OpCodes.Ldstr, ((MemberReference)dm.Definition).Name + " should've been detoured!"); iLProcessor.Emit(OpCodes.Newobj, module.ImportReference((MethodBase)_ctor_Exception)); iLProcessor.Emit(OpCodes.Throw); return dm; } public static void EmitDetourCopy(this ILProcessor il, IntPtr src, IntPtr dst, byte type) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) ModuleDefinition module = ((MemberReference)il.Body.Method).Module; il.Emit(OpCodes.Ldsfld, module.ImportReference(_f_Native)); il.Emit(OpCodes.Ldc_I8, (long)src); il.Emit(OpCodes.Conv_I); il.Emit(OpCodes.Ldc_I8, (long)dst); il.Emit(OpCodes.Conv_I); il.Emit(OpCodes.Ldc_I4, (int)type); il.Emit(OpCodes.Conv_U1); il.Emit(OpCodes.Callvirt, module.ImportReference((MethodBase)_m_Copy)); } public static void EmitDetourApply(this ILProcessor il, NativeDetourData data) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) ModuleDefinition module = ((MemberReference)il.Body.Method).Module; il.Emit(OpCodes.Ldsfld, module.ImportReference(_f_Native)); il.Emit(OpCodes.Ldc_I8, (long)data.Method); il.Emit(OpCodes.Conv_I); il.Emit(OpCodes.Ldc_I8, (long)data.Target); il.Emit(OpCodes.Conv_I); il.Emit(OpCodes.Ldc_I4, (int)data.Size); il.Emit(OpCodes.Ldc_I4, (int)data.Type); il.Emit(OpCodes.Conv_U1); il.Emit(OpCodes.Ldc_I8, (long)data.Extra); il.Emit(OpCodes.Conv_I); il.Emit(OpCodes.Call, module.ImportReference((MethodBase)_m_ToNativeDetourData)); il.Emit(OpCodes.Callvirt, module.ImportReference((MethodBase)_m_Apply)); } } public interface IDetourNativePlatform { NativeDetourData Create(IntPtr from, IntPtr to, byte? type = null); void Free(NativeDetourData detour); void Apply(NativeDetourData detour); void Copy(IntPtr src, IntPtr dst, byte type); void MakeWritable(IntPtr src, uint size); void MakeExecutable(IntPtr src, uint size); void MakeReadWriteExecutable(IntPtr src, uint size); void FlushICache(IntPtr src, uint size); IntPtr MemAlloc(uint size); void MemFree(IntPtr ptr); } public interface IDetourRuntimePlatform { bool OnMethodCompiledWillBeCalled { get; } event OnMethodCompiledEvent OnMethodCompiled; MethodBase GetIdentifiable(MethodBase method); IntPtr GetNativeStart(MethodBase method); MethodInfo CreateCopy(MethodBase method); bool TryCreateCopy(MethodBase method, out MethodInfo dm); void Pin(MethodBase method); void Unpin(MethodBase method); MethodBase GetDetourTarget(MethodBase from, MethodBase to); uint TryMemAllocScratchCloseTo(IntPtr target, out IntPtr ptr, int size); } public delegate void OnMethodCompiledEvent(MethodBase method, IntPtr codeStart, ulong codeSize); public struct NativeDetourData { public IntPtr Method; public IntPtr Target; public byte Type; public uint Size; public IntPtr Extra; } } namespace MonoMod.RuntimeDetour.Platforms { public class DetourNativeARMPlatform : IDetourNativePlatform { public enum DetourType : byte { Thumb, ThumbBX, AArch32, AArch32BX, AArch64 } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate int d_flushicache(IntPtr code, ulong size); private static readonly uint[] DetourSizes = new uint[5] { 8u, 12u, 8u, 12u, 16u }; public bool ShouldFlushICache = true; private readonly byte[] _FlushCache32 = new byte[44] { 128, 64, 45, 233, 0, 48, 160, 225, 1, 192, 128, 224, 20, 224, 159, 229, 3, 0, 160, 225, 12, 16, 160, 225, 14, 112, 160, 225, 0, 32, 160, 227, 0, 0, 0, 239, 128, 128, 189, 232, 2, 0, 15, 0 }; private readonly byte[] _FlushCache64 = new byte[76] { 1, 0, 1, 139, 0, 244, 126, 146, 63, 0, 0, 235, 201, 0, 0, 84, 226, 3, 0, 170, 34, 126, 11, 213, 66, 16, 0, 145, 63, 0, 2, 235, 168, 255, 255, 84, 159, 59, 3, 213, 63, 0, 0, 235, 169, 0, 0, 84, 32, 117, 11, 213, 0, 16, 0, 145, 63, 0, 0, 235, 168, 255, 255, 84, 159, 59, 3, 213, 223, 63, 3, 213, 192, 3, 95, 214 }; private static DetourType GetDetourType(IntPtr from, IntPtr to) { if (IntPtr.Size >= 8) { return DetourType.AArch64; } bool num = ((long)from & 1) == 1; bool flag = ((long)to & 1) == 1; if (num) { if (flag) { return DetourType.Thumb; } return DetourType.ThumbBX; } if (flag) { return DetourType.AArch32BX; } return DetourType.AArch32; } public NativeDetourData Create(IntPtr from, IntPtr to, byte? type) { NativeDetourData nativeDetourData = default(NativeDetourData); nativeDetourData.Method = (IntPtr)((long)from & -2); nativeDetourData.Target = (IntPtr)((long)to & -2); NativeDetourData result = nativeDetourData; uint[] detourSizes = DetourSizes; int num = ((int?)type) ?? ((int)GetDetourType(from, to)); byte b = (byte)num; result.Type = (byte)num; result.Size = detourSizes[b]; return result; } public void Free(NativeDetourData detour) { } public void Apply(NativeDetourData detour) { int offs = 0; switch ((DetourType)detour.Type) { case DetourType.Thumb: detour.Method.Write(ref offs, 223); detour.Method.Write(ref offs, 248); detour.Method.Write(ref offs, 0); detour.Method.Write(ref offs, 240); detour.Method.Write(ref offs, (uint)(int)detour.Target | 1u); break; case DetourType.ThumbBX: detour.Method.Write(ref offs, 223); detour.Method.Write(ref offs, 248); detour.Method.Write(ref offs, 4); detour.Method.Write(ref offs, 160); detour.Method.Write(ref offs, 80); detour.Method.Write(ref offs, 71); detour.Method.Write(ref offs, 0); detour.Method.Write(ref offs, 191); detour.Method.Write(ref offs, (uint)(int)detour.Target | 0u); break; case DetourType.AArch32: detour.Method.Write(ref offs, 4); detour.Method.Write(ref offs, 240); detour.Method.Write(ref offs, 31); detour.Method.Write(ref offs, 229); detour.Method.Write(ref offs, (uint)(int)detour.Target | 0u); break; case DetourType.AArch32BX: detour.Method.Write(ref offs, 0); detour.Method.Write(ref offs, 128); detour.Method.Write(ref offs, 159); detour.Method.Write(ref offs, 229); detour.Method.Write(ref offs, 24); detour.Method.Write(ref offs, byte.MaxValue); detour.Method.Write(ref offs, 47); detour.Method.Write(ref offs, 225); detour.Method.Write(ref offs, (uint)(int)detour.Target | 1u); break; case DetourType.AArch64: detour.Method.Write(ref offs, 79); detour.Method.Write(ref offs, 0); detour.Method.Write(ref offs, 0); detour.Method.Write(ref offs, 88); detour.Method.Write(ref offs, 224); detour.Method.Write(ref offs, 1); detour.Method.Write(ref offs, 31); detour.Method.Write(ref offs, 214); detour.Method.Write(ref offs, (ulong)(long)detour.Target); break; default: throw new NotSupportedException($"Unknown detour type {detour.Type}"); } } public unsafe void Copy(IntPtr src, IntPtr dst, byte type) { switch ((DetourType)type) { case DetourType.Thumb: *(int*)(long)dst = *(int*)(long)src; *(int*)((long)dst + 4) = *(int*)((long)src + 4); break; case DetourType.ThumbBX: *(int*)(long)dst = *(int*)(long)src; *(short*)((long)dst + 4) = *(short*)((long)src + 4); *(short*)((long)dst + 6) = *(short*)((long)src + 6); *(int*)((long)dst + 8) = *(int*)((long)src + 8); break; case DetourType.AArch32: *(int*)(long)dst = *(int*)(long)src; *(int*)((long)dst + 4) = *(int*)((long)src + 4); break; case DetourType.AArch32BX: *(int*)(long)dst = *(int*)(long)src; *(int*)((long)dst + 4) = *(int*)((long)src + 4); *(int*)((long)dst + 8) = *(int*)((long)src + 8); break; case DetourType.AArch64: *(int*)(long)dst = *(int*)(long)src; *(int*)((long)dst + 4) = *(int*)((long)src + 4); *(long*)((long)dst + 8) = *(long*)((long)src + 8); break; default: throw new NotSupportedException($"Unknown detour type {type}"); } } public void MakeWritable(IntPtr src, uint size) { } public void MakeExecutable(IntPtr src, uint size) { } public void MakeReadWriteExecutable(IntPtr src, uint size) { } public unsafe void FlushICache(IntPtr src, uint size) { if (ShouldFlushICache) { byte[] array = ((IntPtr.Size >= 8) ? _FlushCache64 : _FlushCache32); fixed (byte* ptr = array) { DetourHelper.Native.MakeExecutable((IntPtr)ptr, (uint)array.Length); (Marshal.GetDelegateForFunctionPointer((IntPtr)ptr, typeof(d_flushicache)) as d_flushicache)(src, size); } } } public IntPtr MemAlloc(uint size) { return Marshal.AllocHGlobal((int)size); } public void MemFree(IntPtr ptr) { Marshal.FreeHGlobal(ptr); } } public class DetourNativeLibcPlatform : IDetourNativePlatform { [Flags] private enum MmapProts { PROT_READ = 1, PROT_WRITE = 2, PROT_EXEC = 4, PROT_NONE = 0, PROT_GROWSDOWN = 0x1000000, PROT_GROWSUP = 0x2000000 } private readonly IDetourNativePlatform Inner; private readonly long _Pagesize; public DetourNativeLibcPlatform(IDetourNativePlatform inner) { Inner = inner; PropertyInfo property = typeof(Environment).GetProperty("SystemPageSize"); if ((object)property == null) { throw new NotSupportedException("Unsupported runtime"); } _Pagesize = (int)property.GetValue(null, new object[0]); } private void SetMemPerms(IntPtr start, ulong len, MmapProts prot) { long pagesize = _Pagesize; long num = (long)start & ~(pagesize - 1); long num2 = ((long)start + (long)len + pagesize - 1) & ~(pagesize - 1); if (mprotect((IntPtr)num, (IntPtr)(num2 - num), prot) != 0) { throw new Win32Exception(); } } public void MakeWritable(IntPtr src, uint size) { SetMemPerms(src, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC); } public void MakeExecutable(IntPtr src, uint size) { SetMemPerms(src, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC); } public void MakeReadWriteExecutable(IntPtr
BepInEx/core/MonoMod.Utils.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.SymbolStore; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Utils; using MonoMod.Utils.Cil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("MonoMod.Utils.Cil.ILGeneratorProxy")] [assembly: AssemblyCompany("0x0ade")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2022 0x0ade")] [assembly: AssemblyDescription("Utilities and smaller MonoMod \"components\" (f.e. ModInterop, DynDll, DynData). Can be used for your own mods. Required by all other MonoMod components.")] [assembly: AssemblyFileVersion("22.1.29.1")] [assembly: AssemblyInformationalVersion("22.01.29.01")] [assembly: AssemblyProduct("MonoMod.Utils")] [assembly: AssemblyTitle("MonoMod.Utils")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("22.1.29.1")] [module: UnverifiableCode] internal static class MultiTargetShims { private static readonly object[] _NoArgs = new object[0]; public static string Replace(this string self, string oldValue, string newValue, StringComparison comparison) { return self.Replace(oldValue, newValue); } public static bool Contains(this string self, string value, StringComparison comparison) { return self.Contains(value); } public static int GetHashCode(this string self, StringComparison comparison) { return self.GetHashCode(); } public static int IndexOf(this string self, char value, StringComparison comparison) { return self.IndexOf(value); } public static int IndexOf(this string self, string value, StringComparison comparison) { return self.IndexOf(value); } public static TypeReference GetConstraintType(this TypeReference type) { return type; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public class IgnoresAccessChecksToAttribute : Attribute { public string AssemblyName { get; } public IgnoresAccessChecksToAttribute(string assemblyName) { AssemblyName = assemblyName; } } } namespace MonoMod { internal static class MMDbgLog { public static readonly string Tag; public static TextWriter Writer; public static bool Debugging; static MMDbgLog() { Tag = typeof(MMDbgLog).Assembly.GetName().Name; if (!(Environment.GetEnvironmentVariable("MONOMOD_DBGLOG") == "1")) { string? environmentVariable = Environment.GetEnvironmentVariable("MONOMOD_DBGLOG"); bool? obj; if (environmentVariable == null) { obj = null; } else { string text = environmentVariable.ToLower(CultureInfo.InvariantCulture); obj = ((text != null) ? new bool?(MultiTargetShims.Contains(text, Tag.ToLower(CultureInfo.InvariantCulture), StringComparison.Ordinal)) : null); } bool? flag = obj; if (!flag.GetValueOrDefault()) { return; } } Start(); } public static void WaitForDebugger() { if (!Debugging) { Debugging = true; Debugger.Launch(); Thread.Sleep(6000); Debugger.Break(); } } public static void Start() { if (Writer != null) { return; } string text = Environment.GetEnvironmentVariable("MONOMOD_DBGLOG_PATH"); if (text == "-") { Writer = Console.Out; return; } if (string.IsNullOrEmpty(text)) { text = "mmdbglog.txt"; } text = Path.GetFullPath(Path.GetFileNameWithoutExtension(text) + "-" + Tag + Path.GetExtension(text)); try { if (File.Exists(text)) { File.Delete(text); } } catch { } try { string directoryName = Path.GetDirectoryName(text); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } Writer = new StreamWriter(new FileStream(text, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete), Encoding.UTF8); } catch { } } public static void Log(string str) { TextWriter writer = Writer; if (writer != null) { writer.WriteLine(str); writer.Flush(); } } public static T Log<T>(string str, T value) { TextWriter writer = Writer; if (writer == null) { return value; } writer.WriteLine(string.Format(CultureInfo.InvariantCulture, str, new object[1] { value })); writer.Flush(); return value; } } } namespace MonoMod.ModInterop { [AttributeUsage(AttributeTargets.Class)] public sealed class ModExportNameAttribute : Attribute { public string Name; public ModExportNameAttribute(string name) { Name = name; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field)] public sealed class ModImportNameAttribute : Attribute { public string Name; public ModImportNameAttribute(string name) { Name = name; } } public static class ModInteropManager { private static HashSet<Type> Registered = new HashSet<Type>(); private static Dictionary<string, List<MethodInfo>> Methods = new Dictionary<string, List<MethodInfo>>(); private static List<FieldInfo> Fields = new List<FieldInfo>(); public static void ModInterop(this Type type) { if (Registered.Contains(type)) { return; } Registered.Add(type); string name = type.Assembly.GetName().Name; object[] customAttributes = type.GetCustomAttributes(typeof(ModExportNameAttribute), inherit: false); for (int i = 0; i < customAttributes.Length; i++) { name = ((ModExportNameAttribute)customAttributes[i]).Name; } FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (typeof(Delegate).IsAssignableFrom(fieldInfo.FieldType)) { Fields.Add(fieldInfo); } } MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo method in methods) { method.RegisterModExport(); method.RegisterModExport(name); } foreach (FieldInfo field in Fields) { if (!Methods.TryGetValue(field.GetModImportName(), out var value)) { field.SetValue(null, null); continue; } bool flag = false; foreach (MethodInfo item in value) { try { field.SetValue(null, Delegate.CreateDelegate(field.FieldType, null, item)); flag = true; } catch { continue; } break; } if (!flag) { field.SetValue(null, null); } } } public static void RegisterModExport(this MethodInfo method, string prefix = null) { if (!method.IsPublic || !method.IsStatic) { throw new MemberAccessException("Utility must be public static"); } string text = method.Name; if (!string.IsNullOrEmpty(prefix)) { text = prefix + "." + text; } if (!Methods.TryGetValue(text, out var value)) { value = (Methods[text] = new List<MethodInfo>()); } if (!value.Contains(method)) { value.Add(method); } } private static string GetModImportName(this FieldInfo field) { object[] customAttributes = field.GetCustomAttributes(typeof(ModImportNameAttribute), inherit: false); int num = 0; if (num < customAttributes.Length) { return ((ModImportNameAttribute)customAttributes[num]).Name; } customAttributes = field.DeclaringType.GetCustomAttributes(typeof(ModImportNameAttribute), inherit: false); num = 0; if (num < customAttributes.Length) { return ((ModImportNameAttribute)customAttributes[num]).Name + "." + field.Name; } return field.Name; } } } namespace MonoMod.Utils { public sealed class DynData<TTarget> : IDisposable where TTarget : class { private class _Data_ : IDisposable { public readonly Dictionary<string, Func<TTarget, object>> Getters = new Dictionary<string, Func<TTarget, object>>(); public readonly Dictionary<string, Action<TTarget, object>> Setters = new Dictionary<string, Action<TTarget, object>>(); public readonly Dictionary<string, object> Data = new Dictionary<string, object>(); public readonly HashSet<string> Disposable = new HashSet<string>(); ~_Data_() { Dispose(); } public void Dispose() { lock (Data) { if (Data.Count == 0) { return; } foreach (string item in Disposable) { if (Data.TryGetValue(item, out var value) && value is IDisposable disposable) { disposable.Dispose(); } } Disposable.Clear(); Data.Clear(); } } } private static int CreationsInProgress; private static readonly object[] _NoArgs; private static readonly _Data_ _DataStatic; private static readonly Dictionary<WeakReference, _Data_> _DataMap; private static readonly HashSet<WeakReference> _DataMapDead; private static readonly Dictionary<string, Func<TTarget, object>> _SpecialGetters; private static readonly Dictionary<string, Action<TTarget, object>> _SpecialSetters; private readonly WeakReference Weak; private TTarget KeepAlive; private readonly _Data_ _Data; public Dictionary<string, Func<TTarget, object>> Getters => _Data.Getters; public Dictionary<string, Action<TTarget, object>> Setters => _Data.Setters; public Dictionary<string, object> Data => _Data.Data; public bool IsAlive { get { if (Weak != null) { return Weak.SafeGetIsAlive(); } return true; } } public TTarget Target => Weak?.SafeGetTarget() as TTarget; public object this[string name] { get { if (_SpecialGetters.TryGetValue(name, out var value) || Getters.TryGetValue(name, out value)) { return value(Weak?.SafeGetTarget() as TTarget); } if (Data.TryGetValue(name, out var value2)) { return value2; } return null; } set { if (_SpecialSetters.TryGetValue(name, out var value2) || Setters.TryGetValue(name, out value2)) { value2(Weak?.SafeGetTarget() as TTarget, value); return; } object obj; if (_Data.Disposable.Contains(name) && (obj = this[name]) != null && obj is IDisposable disposable) { disposable.Dispose(); } Data[name] = value; } } public static event Action<DynData<TTarget>, TTarget> OnInitialize; static DynData() { CreationsInProgress = 0; _NoArgs = new object[0]; _DataStatic = new _Data_(); _DataMap = new Dictionary<WeakReference, _Data_>(new WeakReferenceComparer()); _DataMapDead = new HashSet<WeakReference>(); _SpecialGetters = new Dictionary<string, Func<TTarget, object>>(); _SpecialSetters = new Dictionary<string, Action<TTarget, object>>(); GCListener.OnCollect += delegate { if (CreationsInProgress != 0) { return; } lock (_DataMap) { foreach (KeyValuePair<WeakReference, _Data_> item in _DataMap) { if (!item.Key.SafeGetIsAlive()) { _DataMapDead.Add(item.Key); item.Value.Dispose(); } } foreach (WeakReference item2 in _DataMapDead) { _DataMap.Remove(item2); } _DataMapDead.Clear(); } }; FieldInfo[] fields = typeof(TTarget).GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { string name = field.Name; _SpecialGetters[name] = (TTarget obj) => field.GetValue(obj); _SpecialSetters[name] = delegate(TTarget obj, object value) { field.SetValue(obj, value); }; } PropertyInfo[] properties = typeof(TTarget).GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { string name2 = propertyInfo.Name; MethodInfo get = propertyInfo.GetGetMethod(nonPublic: true); if ((object)get != null) { _SpecialGetters[name2] = (TTarget obj) => get.Invoke(obj, _NoArgs); } MethodInfo set = propertyInfo.GetSetMethod(nonPublic: true); if ((object)set != null) { _SpecialSetters[name2] = delegate(TTarget obj, object value) { set.Invoke(obj, new object[1] { value }); }; } } } public DynData() : this((TTarget)null, keepAlive: false) { } public DynData(TTarget obj) : this(obj, keepAlive: true) { } public DynData(TTarget obj, bool keepAlive) { if (obj != null) { WeakReference weakReference = new WeakReference(obj); WeakReference key = weakReference; CreationsInProgress++; lock (_DataMap) { if (!_DataMap.TryGetValue(key, out _Data)) { _Data = new _Data_(); _DataMap.Add(key, _Data); } } CreationsInProgress--; Weak = weakReference; if (keepAlive) { KeepAlive = obj; } } else { _Data = _DataStatic; } DynData<TTarget>.OnInitialize?.Invoke(this, obj); } public T Get<T>(string name) { return (T)this[name]; } public void Set<T>(string name, T value) { this[name] = value; } public void RegisterProperty(string name, Func<TTarget, object> getter, Action<TTarget, object> setter) { Getters[name] = getter; Setters[name] = setter; } public void UnregisterProperty(string name) { Getters.Remove(name); Setters.Remove(name); } private void Dispose(bool disposing) { KeepAlive = null; } ~DynData() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } public static class Extensions { private static readonly Type t_StateMachineAttribute = typeof(object).Assembly.GetType("System.Runtime.CompilerServices.StateMachineAttribute"); private static readonly PropertyInfo p_StateMachineType = t_StateMachineAttribute?.GetProperty("StateMachineType"); private static readonly Type t_Code = typeof(Code); private static readonly Type t_OpCodes = typeof(OpCodes); private static readonly Dictionary<int, OpCode> _ToLongOp = new Dictionary<int, OpCode>(); private static readonly Dictionary<int, OpCode> _ToShortOp = new Dictionary<int, OpCode>(); private static readonly object[] _NoArgs = new object[0]; private static readonly Dictionary<Type, FieldInfo> fmap_mono_assembly = new Dictionary<Type, FieldInfo>(); private static readonly bool _MonoAssemblyNameHasArch = new AssemblyName("Dummy, ProcessorArchitecture=MSIL").ProcessorArchitecture == ProcessorArchitecture.MSIL; private static readonly Type _RTDynamicMethod = typeof(DynamicMethod).GetNestedType("RTDynamicMethod", BindingFlags.Public | BindingFlags.NonPublic); private static readonly Type t_ParamArrayAttribute = typeof(ParamArrayAttribute); private static readonly FieldInfo f_GenericParameter_position = typeof(GenericParameter).GetField("position", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo f_GenericParameter_type = typeof(GenericParameter).GetField("type", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly Dictionary<Type, int> _GetManagedSizeCache = new Dictionary<Type, int> { { typeof(void), 0 } }; private static MethodInfo _GetManagedSizeHelper; private static readonly Dictionary<MethodBase, Func<IntPtr>> _GetLdftnPointerCache = new Dictionary<MethodBase, Func<IntPtr>>(); public static string ToHexadecimalString(this byte[] data) { return MultiTargetShims.Replace(BitConverter.ToString(data), "-", string.Empty, StringComparison.Ordinal); } public static T InvokePassing<T>(this MulticastDelegate md, T val, params object[] args) { if ((object)md == null) { return val; } object[] array = new object[args.Length + 1]; array[0] = val; Array.Copy(args, 0, array, 1, args.Length); Delegate[] invocationList = md.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { array[0] = invocationList[i].DynamicInvoke(array); } return (T)array[0]; } public static bool InvokeWhileTrue(this MulticastDelegate md, params object[] args) { if ((object)md == null) { return true; } Delegate[] invocationList = md.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { if (!(bool)invocationList[i].DynamicInvoke(args)) { return false; } } return true; } public static bool InvokeWhileFalse(this MulticastDelegate md, params object[] args) { if ((object)md == null) { return false; } Delegate[] invocationList = md.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { if ((bool)invocationList[i].DynamicInvoke(args)) { return true; } } return false; } public static T InvokeWhileNull<T>(this MulticastDelegate md, params object[] args) where T : class { if ((object)md == null) { return null; } Delegate[] invocationList = md.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { T val = (T)invocationList[i].DynamicInvoke(args); if (val != null) { return val; } } return null; } public static string SpacedPascalCase(this string input) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < input.Length; i++) { char c = input[i]; if (i > 0 && char.IsUpper(c)) { stringBuilder.Append(' '); } stringBuilder.Append(c); } return stringBuilder.ToString(); } public static string ReadNullTerminatedString(this BinaryReader stream) { string text = ""; char c; while ((c = stream.ReadChar()) != 0) { text += c; } return text; } public static void WriteNullTerminatedString(this BinaryWriter stream, string text) { if (text != null) { foreach (char ch in text) { stream.Write(ch); } } stream.Write('\0'); } public static T CastDelegate<T>(this Delegate source) where T : class { return source.CastDelegate(typeof(T)) as T; } public static Delegate CastDelegate(this Delegate source, Type type) { if ((object)source == null) { return null; } Delegate[] invocationList = source.GetInvocationList(); if (invocationList.Length == 1) { return CreateDelegate(invocationList[0].Method, type, invocationList[0].Target); } Delegate[] array = new Delegate[invocationList.Length]; for (int i = 0; i < invocationList.Length; i++) { array[i] = invocationList[i].CastDelegate(type); } return Delegate.Combine(array); } public static bool TryCastDelegate<T>(this Delegate source, out T result) where T : class { if (source is T val) { result = val; return true; } Delegate result2; bool result3 = source.TryCastDelegate(typeof(T), out result2); result = result2 as T; return result3; } public static bool TryCastDelegate(this Delegate source, Type type, out Delegate result) { result = null; if ((object)source == null) { return false; } try { Delegate[] invocationList = source.GetInvocationList(); if (invocationList.Length == 1) { result = CreateDelegate(invocationList[0].Method, type, invocationList[0].Target); return true; } Delegate[] array = new Delegate[invocationList.Length]; for (int i = 0; i < invocationList.Length; i++) { array[i] = invocationList[i].CastDelegate(type); } result = Delegate.Combine(array); return true; } catch { return false; } } public static void LogDetailed(this Exception e, string tag = null) { if (tag == null) { Console.WriteLine("--------------------------------"); Console.WriteLine("Detailed exception log:"); } for (Exception ex = e; ex != null; ex = ex.InnerException) { Console.WriteLine("--------------------------------"); Console.WriteLine(ex.GetType().FullName + ": " + ex.Message + "\n" + ex.StackTrace); if (ex is ReflectionTypeLoadException ex2) { for (int i = 0; i < ex2.Types.Length; i++) { Console.WriteLine("ReflectionTypeLoadException.Types[" + i + "]: " + ex2.Types[i]); } for (int j = 0; j < ex2.LoaderExceptions.Length; j++) { ex2.LoaderExceptions[j].LogDetailed(tag + ((tag == null) ? "" : ", ") + "rtle:" + j); } } if (ex is TypeLoadException) { Console.WriteLine("TypeLoadException.TypeName: " + ((TypeLoadException)ex).TypeName); } if (ex is BadImageFormatException) { Console.WriteLine("BadImageFormatException.FileName: " + ((BadImageFormatException)ex).FileName); } } } public static MethodInfo GetStateMachineTarget(this MethodInfo method) { if ((object)p_StateMachineType == null) { return null; } object[] customAttributes = method.GetCustomAttributes(inherit: false); for (int i = 0; i < customAttributes.Length; i++) { Attribute attribute = (Attribute)customAttributes[i]; if (t_StateMachineAttribute.IsCompatible(attribute.GetType())) { return (p_StateMachineType.GetValue(attribute, null) as Type)?.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } return null; } public static MethodBase GetActualGenericMethodDefinition(this MethodInfo method) { return (method.IsGenericMethod ? method.GetGenericMethodDefinition() : method).GetUnfilledMethodOnGenericType(); } public static MethodBase GetUnfilledMethodOnGenericType(this MethodBase method) { if ((object)method.DeclaringType != null && method.DeclaringType.IsGenericType) { Type genericTypeDefinition = method.DeclaringType.GetGenericTypeDefinition(); method = MethodBase.GetMethodFromHandle(method.MethodHandle, genericTypeDefinition.TypeHandle); } return method; } public static bool Is(this MemberReference member, string fullName) { if (member == null) { return false; } return MultiTargetShims.Replace(member.FullName, "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(fullName, "+", "/", StringComparison.Ordinal); } public static bool Is(this MemberReference member, string typeFullName, string name) { if (member == null) { return false; } if (MultiTargetShims.Replace(((MemberReference)member.DeclaringType).FullName, "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(typeFullName, "+", "/", StringComparison.Ordinal)) { return member.Name == name; } return false; } public static bool Is(this MemberReference member, Type type, string name) { if (member == null) { return false; } if (MultiTargetShims.Replace(((MemberReference)member.DeclaringType).FullName, "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(type.FullName, "+", "/", StringComparison.Ordinal)) { return member.Name == name; } return false; } public static bool Is(this MethodReference method, string fullName) { if (method == null) { return false; } if (MultiTargetShims.Contains(fullName, " ", StringComparison.Ordinal)) { if (MultiTargetShims.Replace(method.GetID(null, null, withType: true, simple: true), "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(fullName, "+", "/", StringComparison.Ordinal)) { return true; } if (MultiTargetShims.Replace(method.GetID(), "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(fullName, "+", "/", StringComparison.Ordinal)) { return true; } } return MultiTargetShims.Replace(((MemberReference)method).FullName, "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(fullName, "+", "/", StringComparison.Ordinal); } public static bool Is(this MethodReference method, string typeFullName, string name) { if (method == null) { return false; } if (MultiTargetShims.Contains(name, " ", StringComparison.Ordinal) && MultiTargetShims.Replace(((MemberReference)((MemberReference)method).DeclaringType).FullName, "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(typeFullName, "+", "/", StringComparison.Ordinal) && MultiTargetShims.Replace(method.GetID(null, null, withType: false), "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(name, "+", "/", StringComparison.Ordinal)) { return true; } if (MultiTargetShims.Replace(((MemberReference)((MemberReference)method).DeclaringType).FullName, "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(typeFullName, "+", "/", StringComparison.Ordinal)) { return ((MemberReference)method).Name == name; } return false; } public static bool Is(this MethodReference method, Type type, string name) { if (method == null) { return false; } if (MultiTargetShims.Contains(name, " ", StringComparison.Ordinal) && MultiTargetShims.Replace(((MemberReference)((MemberReference)method).DeclaringType).FullName, "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(type.FullName, "+", "/", StringComparison.Ordinal) && MultiTargetShims.Replace(method.GetID(null, null, withType: false), "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(name, "+", "/", StringComparison.Ordinal)) { return true; } if (MultiTargetShims.Replace(((MemberReference)((MemberReference)method).DeclaringType).FullName, "+", "/", StringComparison.Ordinal) == MultiTargetShims.Replace(type.FullName, "+", "/", StringComparison.Ordinal)) { return ((MemberReference)method).Name == name; } return false; } public static void ReplaceOperands(this ILProcessor il, object from, object to) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) Enumerator<Instruction> enumerator = il.Body.Instructions.GetEnumerator(); try { while (enumerator.MoveNext()) { Instruction current = enumerator.Current; if (current.Operand?.Equals(from) ?? (from == null)) { current.Operand = to; } } } finally { ((IDisposable)enumerator).Dispose(); } } public static FieldReference Import(this ILProcessor il, FieldInfo field) { return ((MemberReference)il.Body.Method).Module.ImportReference(field); } public static MethodReference Import(this ILProcessor il, MethodBase method) { return ((MemberReference)il.Body.Method).Module.ImportReference(method); } public static TypeReference Import(this ILProcessor il, Type type) { return ((MemberReference)il.Body.Method).Module.ImportReference(type); } public static MemberReference Import(this ILProcessor il, MemberInfo member) { if ((object)member == null) { throw new ArgumentNullException("member"); } if (!(member is FieldInfo field)) { if (!(member is MethodBase method)) { if (member is Type type) { return (MemberReference)(object)il.Import(type); } throw new NotSupportedException("Unsupported member type " + member.GetType().FullName); } return (MemberReference)(object)il.Import(method); } return (MemberReference)(object)il.Import(field); } public static Instruction Create(this ILProcessor il, OpCode opcode, FieldInfo field) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return il.Create(opcode, il.Import(field)); } public static Instruction Create(this ILProcessor il, OpCode opcode, MethodBase method) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (method is DynamicMethod) { return il.Create(opcode, (object)method); } return il.Create(opcode, il.Import(method)); } public static Instruction Create(this ILProcessor il, OpCode opcode, Type type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return il.Create(opcode, il.Import(type)); } public static Instruction Create(this ILProcessor il, OpCode opcode, object operand) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Instruction obj = il.Create(OpCodes.Nop); obj.OpCode = opcode; obj.Operand = operand; return obj; } public static Instruction Create(this ILProcessor il, OpCode opcode, MemberInfo member) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if ((object)member == null) { throw new ArgumentNullException("member"); } if (!(member is FieldInfo field)) { if (!(member is MethodBase method)) { if (member is Type type) { return il.Create(opcode, type); } throw new NotSupportedException("Unsupported member type " + member.GetType().FullName); } return il.Create(opcode, method); } return il.Create(opcode, field); } public static void Emit(this ILProcessor il, OpCode opcode, FieldInfo field) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) il.Emit(opcode, il.Import(field)); } public static void Emit(this ILProcessor il, OpCode opcode, MethodBase method) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (method is DynamicMethod) { il.Emit(opcode, (object)method); } else { il.Emit(opcode, il.Import(method)); } } public static void Emit(this ILProcessor il, OpCode opcode, Type type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) il.Emit(opcode, il.Import(type)); } public static void Emit(this ILProcessor il, OpCode opcode, MemberInfo member) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if ((object)member == null) { throw new ArgumentNullException("member"); } if (!(member is FieldInfo field)) { if (!(member is MethodBase method)) { if (!(member is Type type)) { throw new NotSupportedException("Unsupported member type " + member.GetType().FullName); } il.Emit(opcode, type); } else { il.Emit(opcode, method); } } else { il.Emit(opcode, field); } } public static void Emit(this ILProcessor il, OpCode opcode, object operand) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) il.Append(il.Create(opcode, operand)); } public static TypeDefinition SafeResolve(this TypeReference r) { try { return r.Resolve(); } catch { return null; } } public static FieldDefinition SafeResolve(this FieldReference r) { try { return r.Resolve(); } catch { return null; } } public static MethodDefinition SafeResolve(this MethodReference r) { try { return r.Resolve(); } catch { return null; } } public static PropertyDefinition SafeResolve(this PropertyReference r) { try { return r.Resolve(); } catch { return null; } } public static CustomAttribute GetCustomAttribute(this ICustomAttributeProvider cap, string attribute) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (cap == null || !cap.HasCustomAttributes) { return null; } Enumerator<CustomAttribute> enumerator = cap.CustomAttributes.GetEnumerator(); try { while (enumerator.MoveNext()) { CustomAttribute current = enumerator.Current; if (((MemberReference)current.AttributeType).FullName == attribute) { return current; } } } finally { ((IDisposable)enumerator).Dispose(); } return null; } public static bool HasCustomAttribute(this ICustomAttributeProvider cap, string attribute) { return cap.GetCustomAttribute(attribute) != null; } public static int GetInt(this Instruction instr) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) OpCode opCode = instr.OpCode; if (opCode == OpCodes.Ldc_I4_M1) { return -1; } if (opCode == OpCodes.Ldc_I4_0) { return 0; } if (opCode == OpCodes.Ldc_I4_1) { return 1; } if (opCode == OpCodes.Ldc_I4_2) { return 2; } if (opCode == OpCodes.Ldc_I4_3) { return 3; } if (opCode == OpCodes.Ldc_I4_4) { return 4; } if (opCode == OpCodes.Ldc_I4_5) { return 5; } if (opCode == OpCodes.Ldc_I4_6) { return 6; } if (opCode == OpCodes.Ldc_I4_7) { return 7; } if (opCode == OpCodes.Ldc_I4_8) { return 8; } if (opCode == OpCodes.Ldc_I4_S) { return (sbyte)instr.Operand; } return (int)instr.Operand; } public static int? GetIntOrNull(this Instruction instr) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) OpCode opCode = instr.OpCode; if (opCode == OpCodes.Ldc_I4_M1) { return -1; } if (opCode == OpCodes.Ldc_I4_0) { return 0; } if (opCode == OpCodes.Ldc_I4_1) { return 1; } if (opCode == OpCodes.Ldc_I4_2) { return 2; } if (opCode == OpCodes.Ldc_I4_3) { return 3; } if (opCode == OpCodes.Ldc_I4_4) { return 4; } if (opCode == OpCodes.Ldc_I4_5) { return 5; } if (opCode == OpCodes.Ldc_I4_6) { return 6; } if (opCode == OpCodes.Ldc_I4_7) { return 7; } if (opCode == OpCodes.Ldc_I4_8) { return 8; } if (opCode == OpCodes.Ldc_I4_S) { return (sbyte)instr.Operand; } if (opCode == OpCodes.Ldc_I4) { return (int)instr.Operand; } return null; } public static bool IsBaseMethodCall(this MethodBody body, MethodReference called) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) MethodDefinition method = body.Method; if (called == null) { return false; } TypeReference val = ((MemberReference)called).DeclaringType; while (val is TypeSpecification) { val = ((TypeSpecification)val).ElementType; } string patchFullName = ((MemberReference)(object)val).GetPatchFullName(); bool flag = false; try { TypeDefinition val2 = method.DeclaringType; while ((val2 = val2.BaseType?.SafeResolve()) != null) { if (((MemberReference)(object)val2).GetPatchFullName() == patchFullName) { flag = true; break; } } } catch { flag = ((MemberReference)(object)method.DeclaringType).GetPatchFullName() == patchFullName; } if (!flag) { return false; } return true; } public static bool IsCallvirt(this MethodReference method) { if (!method.HasThis) { return false; } if (((MemberReference)method).DeclaringType.IsValueType) { return false; } return true; } public static bool IsStruct(this TypeReference type) { if (!type.IsValueType) { return false; } if (type.IsPrimitive) { return false; } return true; } public static OpCode ToLongOp(this OpCode op) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected I4, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected I4, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) string name = Enum.GetName(t_Code, ((OpCode)(ref op)).Code); if (!name.EndsWith("_S", StringComparison.Ordinal)) { return op; } lock (_ToLongOp) { if (_ToLongOp.TryGetValue((int)((OpCode)(ref op)).Code, out var value)) { return value; } return _ToLongOp[(int)((OpCode)(ref op)).Code] = (OpCode)(((??)(OpCode?)t_OpCodes.GetField(name.Substring(0, name.Length - 2))?.GetValue(null)) ?? op); } } public static OpCode ToShortOp(this OpCode op) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected I4, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected I4, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) string name = Enum.GetName(t_Code, ((OpCode)(ref op)).Code); if (name.EndsWith("_S", StringComparison.Ordinal)) { return op; } lock (_ToShortOp) { if (_ToShortOp.TryGetValue((int)((OpCode)(ref op)).Code, out var value)) { return value; } return _ToShortOp[(int)((OpCode)(ref op)).Code] = (OpCode)(((??)(OpCode?)t_OpCodes.GetField(name + "_S")?.GetValue(null)) ?? op); } } public static void RecalculateILOffsets(this MethodDefinition method) { if (method.HasBody) { int num = 0; for (int i = 0; i < method.Body.Instructions.Count; i++) { Instruction val = method.Body.Instructions[i]; val.Offset = num; num += val.GetSize(); } } } public static void FixShortLongOps(this MethodDefinition method) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (!method.HasBody) { return; } for (int i = 0; i < method.Body.Instructions.Count; i++) { Instruction val = method.Body.Instructions[i]; if (val.Operand is Instruction) { val.OpCode = val.OpCode.ToLongOp(); } } method.RecalculateILOffsets(); bool flag; do { flag = false; for (int j = 0; j < method.Body.Instructions.Count; j++) { Instruction val2 = method.Body.Instructions[j]; object operand = val2.Operand; Instruction val3 = (Instruction)((operand is Instruction) ? operand : null); if (val3 != null) { int num = val3.Offset - (val2.Offset + val2.GetSize()); if (num == (sbyte)num) { OpCode opCode = val2.OpCode; val2.OpCode = val2.OpCode.ToShortOp(); flag = opCode != val2.OpCode; } } } } while (flag); } public static bool Is(this MemberInfo minfo, MemberReference mref) { return mref.Is(minfo); } public static bool Is(this MemberReference mref, MemberInfo minfo) { if (mref == null) { return false; } TypeReference val = mref.DeclaringType; if (((val != null) ? ((MemberReference)val).FullName : null) == "<Module>") { val = null; } GenericParameter val2 = (GenericParameter)(object)((mref is GenericParameter) ? mref : null); if (val2 != null) { if (!(minfo is Type type)) { return false; } if (!type.IsGenericParameter) { IGenericParameterProvider owner = val2.Owner; IGenericInstance val3 = (IGenericInstance)(object)((owner is IGenericInstance) ? owner : null); if (val3 != null) { return ((MemberReference)(object)val3.GenericArguments[val2.Position]).Is(type); } return false; } return val2.Position == type.GenericParameterPosition; } if ((object)minfo.DeclaringType != null) { if (val == null) { return false; } Type type2 = minfo.DeclaringType; if (minfo is Type && type2.IsGenericType && !type2.IsGenericTypeDefinition) { type2 = type2.GetGenericTypeDefinition(); } if (!((MemberReference)(object)val).Is(type2)) { return false; } } else if (val != null) { return false; } if (!(mref is TypeSpecification) && mref.Name != minfo.Name) { return false; } TypeReference val4 = (TypeReference)(object)((mref is TypeReference) ? mref : null); if (val4 != null) { if (!(minfo is Type type3)) { return false; } if (type3.IsGenericParameter) { return false; } GenericInstanceType val5 = (GenericInstanceType)(object)((mref is GenericInstanceType) ? mref : null); if (val5 != null) { if (!type3.IsGenericType) { return false; } Collection<TypeReference> genericArguments = val5.GenericArguments; Type[] genericArguments2 = type3.GetGenericArguments(); if (genericArguments.Count != genericArguments2.Length) { return false; } for (int i = 0; i < genericArguments.Count; i++) { if (!((MemberReference)(object)genericArguments[i]).Is(genericArguments2[i])) { return false; } } return ((MemberReference)(object)((TypeSpecification)val5).ElementType).Is(type3.GetGenericTypeDefinition()); } if (val4.HasGenericParameters) { if (!type3.IsGenericType) { return false; } Collection<GenericParameter> genericParameters = val4.GenericParameters; Type[] genericArguments3 = type3.GetGenericArguments(); if (genericParameters.Count != genericArguments3.Length) { return false; } for (int j = 0; j < genericParameters.Count; j++) { if (!((MemberReference)(object)genericParameters[j]).Is(genericArguments3[j])) { return false; } } } else if (type3.IsGenericType) { return false; } ArrayType val6 = (ArrayType)(object)((mref is ArrayType) ? mref : null); if (val6 != null) { if (!type3.IsArray) { return false; } if (val6.Dimensions.Count == type3.GetArrayRank()) { return ((MemberReference)(object)((TypeSpecification)val6).ElementType).Is(type3.GetElementType()); } return false; } ByReferenceType val7 = (ByReferenceType)(object)((mref is ByReferenceType) ? mref : null); if (val7 != null) { if (!type3.IsByRef) { return false; } return ((MemberReference)(object)((TypeSpecification)val7).ElementType).Is(type3.GetElementType()); } PointerType val8 = (PointerType)(object)((mref is PointerType) ? mref : null); if (val8 != null) { if (!type3.IsPointer) { return false; } return ((MemberReference)(object)((TypeSpecification)val8).ElementType).Is(type3.GetElementType()); } TypeSpecification val9 = (TypeSpecification)(object)((mref is TypeSpecification) ? mref : null); if (val9 != null) { return ((MemberReference)(object)val9.ElementType).Is(type3.HasElementType ? type3.GetElementType() : type3); } if (val != null) { return mref.Name == type3.Name; } return mref.FullName == MultiTargetShims.Replace(type3.FullName, "+", "/", StringComparison.Ordinal); } if (minfo is Type) { return false; } MethodReference methodRef = (MethodReference)(object)((mref is MethodReference) ? mref : null); if (methodRef != null) { if (!(minfo is MethodBase methodBase)) { return false; } Collection<ParameterDefinition> parameters = methodRef.Parameters; ParameterInfo[] parameters2 = methodBase.GetParameters(); if (parameters.Count != parameters2.Length) { return false; } GenericInstanceMethod val10 = (GenericInstanceMethod)(object)((mref is GenericInstanceMethod) ? mref : null); if (val10 != null) { if (!methodBase.IsGenericMethod) { return false; } Collection<TypeReference> genericArguments4 = val10.GenericArguments; Type[] genericArguments5 = methodBase.GetGenericArguments(); if (genericArguments4.Count != genericArguments5.Length) { return false; } for (int k = 0; k < genericArguments4.Count; k++) { if (!((MemberReference)(object)genericArguments4[k]).Is(genericArguments5[k])) { return false; } } return ((MemberReference)(object)((MethodSpecification)val10).ElementMethod).Is((methodBase as MethodInfo)?.GetGenericMethodDefinition() ?? methodBase); } if (methodRef.HasGenericParameters) { if (!methodBase.IsGenericMethod) { return false; } Collection<GenericParameter> genericParameters2 = methodRef.GenericParameters; Type[] genericArguments6 = methodBase.GetGenericArguments(); if (genericParameters2.Count != genericArguments6.Length) { return false; } for (int l = 0; l < genericParameters2.Count; l++) { if (!((MemberReference)(object)genericParameters2[l]).Is(genericArguments6[l])) { return false; } } } else if (methodBase.IsGenericMethod) { return false; } Relinker relinker = null; relinker = delegate(IMetadataTokenProvider paramMemberRef, IGenericParameterProvider ctx) { TypeReference val15 = (TypeReference)(object)((paramMemberRef is TypeReference) ? paramMemberRef : null); return (IMetadataTokenProvider)((val15 == null) ? ((object)paramMemberRef) : ((object)ResolveParameter(val15))); }; if (!((MemberReference)(object)methodRef.ReturnType.Relink(relinker, null)).Is((methodBase as MethodInfo)?.ReturnType ?? typeof(void)) && !((MemberReference)(object)methodRef.ReturnType).Is((methodBase as MethodInfo)?.ReturnType ?? typeof(void))) { return false; } for (int m = 0; m < parameters.Count; m++) { if (!((MemberReference)(object)((ParameterReference)parameters[m]).ParameterType.Relink(relinker, null)).Is(parameters2[m].ParameterType) && !((MemberReference)(object)((ParameterReference)parameters[m]).ParameterType).Is(parameters2[m].ParameterType)) { return false; } } return true; } if (minfo is MethodInfo) { return false; } if (mref is FieldReference != minfo is FieldInfo) { return false; } if (mref is PropertyReference != minfo is PropertyInfo) { return false; } if (mref is EventReference != minfo is EventInfo) { return false; } return true; TypeReference ResolveParameter(TypeReference paramTypeRef) { GenericParameter val11 = (GenericParameter)(object)((paramTypeRef is GenericParameter) ? paramTypeRef : null); if (val11 != null) { if (val11.Owner is MethodReference) { MethodReference obj = methodRef; GenericInstanceMethod val12 = (GenericInstanceMethod)(object)((obj is GenericInstanceMethod) ? obj : null); if (val12 != null) { return val12.GenericArguments[val11.Position]; } } IGenericParameterProvider owner2 = val11.Owner; TypeReference val13 = (TypeReference)(object)((owner2 is TypeReference) ? owner2 : null); if (val13 != null) { TypeReference declaringType = ((MemberReference)methodRef).DeclaringType; GenericInstanceType val14 = (GenericInstanceType)(object)((declaringType is GenericInstanceType) ? declaringType : null); if (val14 != null && ((MemberReference)val13).FullName == ((MemberReference)((TypeSpecification)val14).ElementType).FullName) { return val14.GenericArguments[val11.Position]; } } return paramTypeRef; } if (paramTypeRef == ((MemberReference)methodRef).DeclaringType.GetElementType()) { return ((MemberReference)methodRef).DeclaringType; } return paramTypeRef; } } public static IMetadataTokenProvider ImportReference(this ModuleDefinition mod, IMetadataTokenProvider mtp) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if (mtp is TypeReference) { return (IMetadataTokenProvider)(object)mod.ImportReference((TypeReference)mtp); } if (mtp is FieldReference) { return (IMetadataTokenProvider)(object)mod.ImportReference((FieldReference)mtp); } if (mtp is MethodReference) { return (IMetadataTokenProvider)(object)mod.ImportReference((MethodReference)mtp); } return mtp; } public static void AddRange<T>(this Collection<T> list, IEnumerable<T> other) { foreach (T item in other) { list.Add(item); } } public static void AddRange(this IDictionary dict, IDictionary other) { foreach (DictionaryEntry item in other) { dict.Add(item.Key, item.Value); } } public static void AddRange<K, V>(this IDictionary<K, V> dict, IDictionary<K, V> other) { foreach (KeyValuePair<K, V> item in other) { dict.Add(item.Key, item.Value); } } public static void AddRange<K, V>(this Dictionary<K, V> dict, Dictionary<K, V> other) { foreach (KeyValuePair<K, V> item in other) { dict.Add(item.Key, item.Value); } } public static void InsertRange<T>(this Collection<T> list, int index, IEnumerable<T> other) { foreach (T item in other) { list.Insert(index++, item); } } public static bool IsCompatible(this Type type, Type other) { if (!type._IsCompatible(other)) { return other._IsCompatible(type); } return true; } private static bool _IsCompatible(this Type type, Type other) { if ((object)type == other) { return true; } if (type.IsAssignableFrom(other)) { return true; } if (other.IsEnum && type.IsCompatible(Enum.GetUnderlyingType(other))) { return true; } if ((other.IsPointer || other.IsByRef) && (object)type == typeof(IntPtr)) { return true; } return false; } public static T GetDeclaredMember<T>(this T member) where T : MemberInfo { if ((object)member.DeclaringType == member.ReflectedType) { return member; } int metadataToken = member.MetadataToken; MemberInfo[] members = member.DeclaringType.GetMembers((BindingFlags)(-1)); foreach (MemberInfo memberInfo in members) { if (memberInfo.MetadataToken == metadataToken) { return (T)memberInfo; } } return member; } public unsafe static void SetMonoCorlibInternal(this Assembly asm, bool value) { if ((object)Type.GetType("Mono.Runtime") == null) { return; } Type type = asm?.GetType(); if ((object)type == null) { return; } FieldInfo value2; lock (fmap_mono_assembly) { if (!fmap_mono_assembly.TryGetValue(type, out value2)) { value2 = type.GetField("_mono_assembly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("dynamic_assembly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); fmap_mono_assembly[type] = value2; } } if ((object)value2 == null) { return; } AssemblyName assemblyName = new AssemblyName(asm.FullName); lock (ReflectionHelper.AssemblyCache) { WeakReference value3 = new WeakReference(asm); ReflectionHelper.AssemblyCache[asm.GetRuntimeHashedFullName()] = value3; ReflectionHelper.AssemblyCache[assemblyName.FullName] = value3; ReflectionHelper.AssemblyCache[assemblyName.Name] = value3; } long num = 0L; object value4 = value2.GetValue(asm); if (!(value4 is IntPtr intPtr)) { if (value4 is UIntPtr uIntPtr) { num = (long)(ulong)uIntPtr; } } else { num = (long)intPtr; } int num2 = IntPtr.Size + IntPtr.Size + IntPtr.Size + IntPtr.Size + IntPtr.Size + IntPtr.Size + 20 + 4 + 4 + 4 + (_MonoAssemblyNameHasArch ? ((!(typeof(object).Assembly.GetName().Name == "System.Private.CoreLib")) ? ((IntPtr.Size == 4) ? 12 : 16) : ((IntPtr.Size == 4) ? 20 : 24)) : ((typeof(object).Assembly.GetName().Name == "System.Private.CoreLib") ? 16 : 8)) + IntPtr.Size + IntPtr.Size + 1 + 1 + 1; byte* ptr = (byte*)(num + num2); *ptr = (byte)(value ? 1 : 0); } public static bool IsDynamicMethod(this MethodBase method) { if ((object)_RTDynamicMethod != null) { if (!(method is DynamicMethod)) { return (object)method.GetType() == _RTDynamicMethod; } return true; } if (method is DynamicMethod) { return true; } if (method.MetadataToken != 0 || !method.IsStatic || !method.IsPublic || (method.Attributes & MethodAttributes.PrivateScope) != 0) { return false; } MethodInfo[] methods = method.DeclaringType.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if ((object)method == methodInfo) { return false; } } return true; } public static object SafeGetTarget(this WeakReference weak) { try { return weak.Target; } catch (InvalidOperationException) { return null; } } public static bool SafeGetIsAlive(this WeakReference weak) { try { return weak.IsAlive; } catch (InvalidOperationException) { return false; } } public static T CreateDelegate<T>(this MethodBase method) where T : Delegate { return (T)method.CreateDelegate(typeof(T), null); } public static T CreateDelegate<T>(this MethodBase method, object target) where T : Delegate { return (T)method.CreateDelegate(typeof(T), target); } public static Delegate CreateDelegate(this MethodBase method, Type delegateType) { return method.CreateDelegate(delegateType, null); } public static Delegate CreateDelegate(this MethodBase method, Type delegateType, object target) { if (!typeof(Delegate).IsAssignableFrom(delegateType)) { throw new ArgumentException("Type argument must be a delegate type!"); } if (method is DynamicMethod dynamicMethod) { return dynamicMethod.CreateDelegate(delegateType, target); } RuntimeMethodHandle methodHandle = method.MethodHandle; RuntimeHelpers.PrepareMethod(methodHandle); IntPtr functionPointer = methodHandle.GetFunctionPointer(); return (Delegate)Activator.CreateInstance(delegateType, target, functionPointer); } public static MethodDefinition FindMethod(this TypeDefinition type, string id, bool simple = true) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) Enumerator<MethodDefinition> enumerator; if (simple && !MultiTargetShims.Contains(id, " ", StringComparison.Ordinal)) { enumerator = type.Methods.GetEnumerator(); try { while (enumerator.MoveNext()) { MethodDefinition current = enumerator.Current; if (((MethodReference)(object)current).GetID(null, null, withType: true, simple: true) == id) { return current; } } } finally { ((IDisposable)enumerator).Dispose(); } enumerator = type.Methods.GetEnumerator(); try { while (enumerator.MoveNext()) { MethodDefinition current2 = enumerator.Current; if (((MethodReference)(object)current2).GetID(null, null, withType: false, simple: true) == id) { return current2; } } } finally { ((IDisposable)enumerator).Dispose(); } } enumerator = type.Methods.GetEnumerator(); try { while (enumerator.MoveNext()) { MethodDefinition current3 = enumerator.Current; if (((MethodReference)(object)current3).GetID() == id) { return current3; } } } finally { ((IDisposable)enumerator).Dispose(); } enumerator = type.Methods.GetEnumerator(); try { while (enumerator.MoveNext()) { MethodDefinition current4 = enumerator.Current; if (((MethodReference)(object)current4).GetID(null, null, withType: false) == id) { return current4; } } } finally { ((IDisposable)enumerator).Dispose(); } return null; } public static MethodDefinition FindMethodDeep(this TypeDefinition type, string id, bool simple = true) { MethodDefinition obj = type.FindMethod(id, simple); if (obj == null) { TypeReference baseType = type.BaseType; if (baseType == null) { return null; } TypeDefinition obj2 = baseType.Resolve(); if (obj2 == null) { return null; } obj = obj2.FindMethodDeep(id, simple); } return obj; } public static MethodInfo FindMethod(this Type type, string id, bool simple = true) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array; if (simple && !MultiTargetShims.Contains(id, " ", StringComparison.Ordinal)) { array = methods; foreach (MethodInfo methodInfo in array) { if (methodInfo.GetID(null, null, withType: true, proxyMethod: false, simple: true) == id) { return methodInfo; } } array = methods; foreach (MethodInfo methodInfo2 in array) { if (methodInfo2.GetID(null, null, withType: false, proxyMethod: false, simple: true) == id) { return methodInfo2; } } } array = methods; foreach (MethodInfo methodInfo3 in array) { if (methodInfo3.GetID(null, null, withType: true, proxyMethod: false, simple: false) == id) { return methodInfo3; } } array = methods; foreach (MethodInfo methodInfo4 in array) { if (methodInfo4.GetID(null, null, withType: false, proxyMethod: false, simple: false) == id) { return methodInfo4; } } return null; } public static MethodInfo FindMethodDeep(this Type type, string id, bool simple = true) { MethodInfo methodInfo = type.FindMethod(id, simple); if ((object)methodInfo == null) { Type? baseType = type.BaseType; if ((object)baseType == null) { return null; } methodInfo = baseType.FindMethodDeep(id, simple); } return methodInfo; } public static PropertyDefinition FindProperty(this TypeDefinition type, string name) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<PropertyDefinition> enumerator = type.Properties.GetEnumerator(); try { while (enumerator.MoveNext()) { PropertyDefinition current = enumerator.Current; if (((MemberReference)current).Name == name) { return current; } } } finally { ((IDisposable)enumerator).Dispose(); } return null; } public static PropertyDefinition FindPropertyDeep(this TypeDefinition type, string name) { PropertyDefinition obj = type.FindProperty(name); if (obj == null) { TypeReference baseType = type.BaseType; if (baseType == null) { return null; } TypeDefinition obj2 = baseType.Resolve(); if (obj2 == null) { return null; } obj = obj2.FindPropertyDeep(name); } return obj; } public static FieldDefinition FindField(this TypeDefinition type, string name) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<FieldDefinition> enumerator = type.Fields.GetEnumerator(); try { while (enumerator.MoveNext()) { FieldDefinition current = enumerator.Current; if (((MemberReference)current).Name == name) { return current; } } } finally { ((IDisposable)enumerator).Dispose(); } return null; } public static FieldDefinition FindFieldDeep(this TypeDefinition type, string name) { FieldDefinition obj = type.FindField(name); if (obj == null) { TypeReference baseType = type.BaseType; if (baseType == null) { return null; } TypeDefinition obj2 = baseType.Resolve(); if (obj2 == null) { return null; } obj = obj2.FindFieldDeep(name); } return obj; } public static EventDefinition FindEvent(this TypeDefinition type, string name) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<EventDefinition> enumerator = type.Events.GetEnumerator(); try { while (enumerator.MoveNext()) { EventDefinition current = enumerator.Current; if (((MemberReference)current).Name == name) { return current; } } } finally { ((IDisposable)enumerator).Dispose(); } return null; } public static EventDefinition FindEventDeep(this TypeDefinition type, string name) { EventDefinition obj = type.FindEvent(name); if (obj == null) { TypeReference baseType = type.BaseType; if (baseType == null) { return null; } TypeDefinition obj2 = baseType.Resolve(); if (obj2 == null) { return null; } obj = obj2.FindEventDeep(name); } return obj; } public static string GetID(this MethodReference method, string name = null, string type = null, bool withType = true, bool simple = false) { StringBuilder stringBuilder = new StringBuilder(); if (simple) { if (withType && (type != null || ((MemberReference)method).DeclaringType != null)) { stringBuilder.Append(type ?? ((MemberReference)(object)((MemberReference)method).DeclaringType).GetPatchFullName()).Append("::"); } stringBuilder.Append(name ?? ((MemberReference)method).Name); return stringBuilder.ToString(); } stringBuilder.Append(((MemberReference)(object)method.ReturnType).GetPatchFullName()).Append(" "); if (withType && (type != null || ((MemberReference)method).DeclaringType != null)) { stringBuilder.Append(type ?? ((MemberReference)(object)((MemberReference)method).DeclaringType).GetPatchFullName()).Append("::"); } stringBuilder.Append(name ?? ((MemberReference)method).Name); GenericInstanceMethod val = (GenericInstanceMethod)(object)((method is GenericInstanceMethod) ? method : null); if (val != null && val.GenericArguments.Count != 0) { stringBuilder.Append("<"); Collection<TypeReference> genericArguments = val.GenericArguments; for (int i = 0; i < genericArguments.Count; i++) { if (i > 0) { stringBuilder.Append(","); } stringBuilder.Append(((MemberReference)(object)genericArguments[i]).GetPatchFullName()); } stringBuilder.Append(">"); } else if (method.GenericParameters.Count != 0) { stringBuilder.Append("<"); Collection<GenericParameter> genericParameters = method.GenericParameters; for (int j = 0; j < genericParameters.Count; j++) { if (j > 0) { stringBuilder.Append(","); } stringBuilder.Append(((MemberReference)genericParameters[j]).Name); } stringBuilder.Append(">"); } stringBuilder.Append("("); if (method.HasParameters) { Collection<ParameterDefinition> parameters = method.Parameters; for (int k = 0; k < parameters.Count; k++) { ParameterDefinition val2 = parameters[k]; if (k > 0) { stringBuilder.Append(","); } if (((ParameterReference)val2).ParameterType.IsSentinel) { stringBuilder.Append("...,"); } stringBuilder.Append(((MemberReference)(object)((ParameterReference)val2).ParameterType).GetPatchFullName()); } } stringBuilder.Append(")"); return stringBuilder.ToString(); } public static string GetID(this CallSite method) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(((MemberReference)(object)method.ReturnType).GetPatchFullName()).Append(" "); stringBuilder.Append("("); if (method.HasParameters) { Collection<ParameterDefinition> parameters = method.Parameters; for (int i = 0; i < parameters.Count; i++) { ParameterDefinition val = parameters[i]; if (i > 0) { stringBuilder.Append(","); } if (((ParameterReference)val).ParameterType.IsSentinel) { stringBuilder.Append("...,"); } stringBuilder.Append(((MemberReference)(object)((ParameterReference)val).ParameterType).GetPatchFullName()); } } stringBuilder.Append(")"); return stringBuilder.ToString(); } public static string GetID(this MethodBase method, string name = null, string type = null, bool withType = true, bool proxyMethod = false, bool simple = false) { while (method is MethodInfo && method.IsGenericMethod && !method.IsGenericMethodDefinition) { method = ((MethodInfo)method).GetGenericMethodDefinition(); } StringBuilder stringBuilder = new StringBuilder(); if (simple) { if (withType && (type != null || (object)method.DeclaringType != null)) { stringBuilder.Append(type ?? method.DeclaringType.FullName).Append("::"); } stringBuilder.Append(name ?? method.Name); return stringBuilder.ToString(); } stringBuilder.Append((method as MethodInfo)?.ReturnType?.FullName ?? "System.Void").Append(" "); if (withType && (type != null || (object)method.DeclaringType != null)) { stringBuilder.Append(type ?? MultiTargetShims.Replace(method.DeclaringType.FullName, "+", "/", StringComparison.Ordinal)).Append("::"); } stringBuilder.Append(name ?? method.Name); if (method.ContainsGenericParameters) { stringBuilder.Append("<"); Type[] genericArguments = method.GetGenericArguments(); for (int i = 0; i < genericArguments.Length; i++) { if (i > 0) { stringBuilder.Append(","); } stringBuilder.Append(genericArguments[i].Name); } stringBuilder.Append(">"); } stringBuilder.Append("("); ParameterInfo[] parameters = method.GetParameters(); for (int j = (proxyMethod ? 1 : 0); j < parameters.Length; j++) { ParameterInfo parameterInfo = parameters[j]; if (j > (proxyMethod ? 1 : 0)) { stringBuilder.Append(","); } bool flag; try { flag = parameterInfo.GetCustomAttributes(t_ParamArrayAttribute, inherit: false).Length != 0; } catch (NotSupportedException) { flag = false; } if (flag) { stringBuilder.Append("...,"); } stringBuilder.Append(parameterInfo.ParameterType.FullName); } stringBuilder.Append(")"); return stringBuilder.ToString(); } public static string GetPatchName(this MemberReference mr) { MemberReference obj = ((mr is ICustomAttributeProvider) ? mr : null); return ((obj != null) ? ((ICustomAttributeProvider)(object)obj).GetPatchName() : null) ?? mr.Name; } public static string GetPatchFullName(this MemberReference mr) { MemberReference obj = ((mr is ICustomAttributeProvider) ? mr : null); return ((obj != null) ? ((ICustomAttributeProvider)(object)obj).GetPatchFullName(mr) : null) ?? mr.FullName; } private static string GetPatchName(this ICustomAttributeProvider cap) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) CustomAttribute customAttribute = cap.GetCustomAttribute("MonoMod.MonoModPatch"); string text; if (customAttribute != null) { CustomAttributeArgument val = customAttribute.ConstructorArguments[0]; text = (string)((CustomAttributeArgument)(ref val)).Value; int num = text.LastIndexOf('.'); if (num != -1 && num != text.Length - 1) { text = text.Substring(num + 1); } return text; } text = ((MemberReference)cap).Name; if (!text.StartsWith("patch_", StringComparison.Ordinal)) { return text; } return text.Substring(6); } private static string GetPatchFullName(this ICustomAttributeProvider cap, MemberReference mr) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Expected O, but got Unknown //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Expected O, but got Unknown //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) TypeReference val = (TypeReference)(object)((cap is TypeReference) ? cap : null); if (val != null) { CustomAttribute customAttribute = cap.GetCustomAttribute("MonoMod.MonoModPatch"); string text; if (customAttribute != null) { CustomAttributeArgument val2 = customAttribute.ConstructorArguments[0]; text = (string)((CustomAttributeArgument)(ref val2)).Value; } else { text = ((MemberReference)cap).Name; text = (text.StartsWith("patch_", StringComparison.Ordinal) ? text.Substring(6) : text); } if (text.StartsWith("global::", StringComparison.Ordinal)) { text = text.Substring(8); } else if (!MultiTargetShims.Contains(text, ".", StringComparison.Ordinal) && !MultiTargetShims.Contains(text, "/", StringComparison.Ordinal)) { if (!string.IsNullOrEmpty(val.Namespace)) { text = val.Namespace + "." + text; } else if (val.IsNested) { text = ((MemberReference)(object)((MemberReference)val).DeclaringType).GetPatchFullName() + "/" + text; } } if (mr is TypeSpecification) { List<TypeSpecification> list = new List<TypeSpecification>(); TypeSpecification val3 = (TypeSpecification)mr; TypeReference elementType; do { list.Add(val3); elementType = val3.ElementType; } while ((val3 = (TypeSpecification)(object)((elementType is TypeSpecification) ? elementType : null)) != null); StringBuilder stringBuilder = new StringBuilder(text.Length + list.Count * 4); stringBuilder.Append(text); for (int num = list.Count - 1; num > -1; num--) { val3 = list[num]; if (((TypeReference)val3).IsByReference) { stringBuilder.Append("&"); } else if (((TypeReference)val3).IsPointer) { stringBuilder.Append("*"); } else if (!((TypeReference)val3).IsPinned && !((TypeReference)val3).IsSentinel) { if (((TypeReference)val3).IsArray) { ArrayType val4 = (ArrayType)val3; if (val4.IsVector) { stringBuilder.Append("[]"); } else { stringBuilder.Append("["); for (int i = 0; i < val4.Dimensions.Count; i++) { if (i > 0) { stringBuilder.Append(","); } ArrayDimension val5 = val4.Dimensions[i]; stringBuilder.Append(((object)(ArrayDimension)(ref val5)).ToString()); } stringBuilder.Append("]"); } } else if (((TypeReference)val3).IsRequiredModifier) { stringBuilder.Append("modreq(").Append(((RequiredModifierType)val3).ModifierType).Append(")"); } else if (((TypeReference)val3).IsOptionalModifier) { stringBuilder.Append("modopt(").Append(((OptionalModifierType)val3).ModifierType).Append(")"); } else if (((TypeReference)val3).IsGenericInstance) { GenericInstanceType val6 = (GenericInstanceType)val3; stringBuilder.Append("<"); for (int j = 0; j < val6.GenericArguments.Count; j++) { if (j > 0) { stringBuilder.Append(","); } stringBuilder.Append(((MemberReference)(object)val6.GenericArguments[j]).GetPatchFullName()); } stringBuilder.Append(">"); } else { if (!((TypeReference)val3).IsFunctionPointer) { throw new NotSupportedException($"MonoMod can't handle TypeSpecification: {((MemberReference)val).FullName} ({((object)val).GetType()})"); } FunctionPointerType val7 = (FunctionPointerType)val3; stringBuilder.Append(" ").Append(((MemberReference)(object)val7.ReturnType).GetPatchFullName()).Append(" *("); if (val7.HasParameters) { for (int k = 0; k < val7.Parameters.Count; k++) { ParameterDefinition val8 = val7.Parameters[k]; if (k > 0) { stringBuilder.Append(","); } if (((ParameterReference)val8).ParameterType.IsSentinel) { stringBuilder.Append("...,"); } stringBuilder.Append(((MemberReference)((ParameterReference)val8).ParameterType).FullName); } } stringBuilder.Append(")"); } } } text = stringBuilder.ToString(); } return text; } FieldReference val9 = (FieldReference)(object)((cap is FieldReference) ? cap : null); if (val9 != null) { return ((MemberReference)(object)val9.FieldType).GetPatchFullName() + " " + ((MemberReference)(object)((MemberReference)val9).DeclaringType).GetPatchFullName() + "::" + cap.GetPatchName(); } if (cap is MethodReference) { throw new InvalidOperationException("GetPatchFullName not supported on MethodReferences - use GetID instead"); } throw new InvalidOperationException($"GetPatchFullName not supported on type {((object)cap).GetType()}"); } public static MethodDefinition Clone(this MethodDefinition o, MethodDefinition c = null) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) if (o == null) { return null; } if (c == null) { c = new MethodDefinition(((MemberReference)o).Name, o.Attributes, ((MethodReference)o).ReturnType); } ((MemberReference)c).Name = ((MemberReference)o).Name; c.Attributes = o.Attributes; ((MethodReference)c).ReturnType = ((MethodReference)o).ReturnType; c.DeclaringType = o.DeclaringType; ((MemberReference)c).MetadataToken = ((MemberReference)c).MetadataToken; c.Body = o.Body?.Clone(c); c.Attributes = o.Attributes; c.ImplAttributes = o.ImplAttributes; c.PInvokeInfo = o.PInvokeInfo; c.IsPreserveSig = o.IsPreserveSig; c.IsPInvokeImpl = o.IsPInvokeImpl; Enumerator<GenericParameter> enumerator = ((MethodReference)o).GenericParameters.GetEnumerator(); try { while (enumerator.MoveNext()) { GenericParameter current = enumerator.Current; ((MethodReference)c).GenericParameters.Add(current.Clone()); } } finally { ((IDisposable)enumerator).Dispose(); } Enumerator<ParameterDefinition> enumerator2 = ((MethodReference)o).Parameters.GetEnumerator(); try { while (enumerator2.MoveNext()) { ParameterDefinition current2 = enumerator2.Current; ((MethodReference)c).Parameters.Add(current2.Clone()); } } finally { ((IDisposable)enumerator2).Dispose(); } Enumerator<CustomAttribute> enumerator3 = o.CustomAttributes.GetEnumerator(); try { while (enumerator3.MoveNext()) { CustomAttribute current3 = enumerator3.Current; c.CustomAttributes.Add(current3.Clone()); } } finally { ((IDisposable)enumerator3).Dispose(); } Enumerator<MethodReference> enumerator4 = o.Overrides.GetEnumerator(); try { while (enumerator4.MoveNext()) { MethodReference current4 = enumerator4.Current; c.Overrides.Add(current4); } } finally { ((IDisposable)enumerator4).Dispose(); } if (c.Body != null) { Enumerator<Instruction> enumerator5 = c.Body.Instructions.GetEnumerator(); try { while (enumerator5.MoveNext()) { Instruction current5 = enumerator5.Current; object operand = current5.Operand; GenericParameter val = (GenericParameter)((operand is GenericParameter) ? operand : null); int num; if (val != null && (num = ((MethodReference)o).GenericParameters.IndexOf(val)) != -1) { current5.Operand = ((MethodReference)c).GenericParameters[num]; continue; } object operand2 = current5.Operand; ParameterDefinition val2 = (ParameterDefinition)((operand2 is ParameterDefinition) ? operand2 : null); if (val2 != null && (num = ((MethodReference)o).Parameters.IndexOf(val2)) != -1) { current5.Operand = ((MethodReference)c).Parameters[num]; } } } finally { ((IDisposable)enumerator5).Dispose(); } } return c; } public static MethodBody Clone(this MethodBody bo, MethodDefinition m) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (bo == null) { return null; } MethodBody bc = new MethodBody(m); bc.MaxStackSize = bo.MaxStackSize; bc.InitLocals = bo.InitLocals; bc.LocalVarToken = bo.LocalVarToken; bc.Instructions.AddRange(((IEnumerable<Instruction>)bo.Instructions).Select(delegate(Instruction o) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Instruction obj = Instruction.Create(OpCodes.Nop); obj.OpCode = o.OpCode; obj.Operand = o.Operand; obj.Offset = o.Offset; return obj; })); Enumerator<Instruction> enumerator = bc.Instructions.GetEnumerator(); try { while (enumerator.MoveNext()) { Instruction current = enumerator.Current; object operand = current.Operand; Instruction val = (Instruction)((operand is Instruction) ? operand : null); if (val != null) { current.Operand = bc.Instructions[bo.Instructions.IndexOf(val)]; } else if (current.Operand is Instruction[] source) { current.Operand = source.Select((Instruction i) => bc.Instructions[bo.Instructions.IndexOf(i)]).ToArray(); } } } finally { ((IDisposable)enumerator).Dispose(); } bc.ExceptionHandlers.AddRange(((IEnumerable<ExceptionHandler>)bo.ExceptionHandlers).Select((Func<ExceptionHandler, ExceptionHandler>)((ExceptionHandler o) => new ExceptionHandler(o.HandlerType) { TryStart = ((o.TryStart == null) ? null : bc.Instructions[bo.Instructions.IndexOf(o.TryStart)]), TryEnd = ((o.TryEnd == null) ? null : bc.Instructions[bo.Instructions.IndexOf(o.TryEnd)]), FilterStart = ((o.FilterStart == null) ? null : bc.Instructions[bo.Instructions.IndexOf(o.FilterStart)]), HandlerStart = ((o.HandlerStart == null) ? null : bc.Instructions[bo.Instructions.IndexOf(o.HandlerStart)]), HandlerEnd = ((o.HandlerEnd == null) ? null : bc.Instructions[bo.Instructions.IndexOf(o.HandlerEnd)]), CatchType = o.CatchType }))); bc.Variables.AddRange(((IEnumerable<VariableDefinition>)bo.Variables).Select((Func<VariableDefinition, VariableDefinition>)((VariableDefinition o) => new VariableDefinition(((VariableReference)o).VariableType)))); m.CustomDebugInformations.AddRange((IEnumerable<CustomDebugInformation>)bo.Method.CustomDebugInformations); m.DebugInformation.SequencePoints.AddRange(((IEnumerable<SequencePoint>)bo.Method.DebugInformation.SequencePoints).Select((Func<SequencePoint, SequencePoint>)((SequencePoint o) => new SequencePoint(((IEnumerable<Instruction>)bc.Instructions).FirstOrDefault((Func<Instruction, bool>)((Instruction i) => i.Offset == o.Offset)), o.Document) { StartLine = o.StartLine, StartColumn = o.StartColumn, EndLine = o.EndLine, EndColumn = o.EndColumn }))); return bc; } public static GenericParameter Update(this GenericParameter param, int position, GenericParameterType type) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) f_GenericParameter_position.SetValue(param, position); f_GenericParameter_type.SetValue(param, type); return param; } public static GenericParameter ResolveGenericParameter(this IGenericParameterProvider provider, GenericParameter orig) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown if (provider is GenericParameter && ((MemberReference)(GenericParameter)provider).Name == ((MemberReference)orig).Name) { return (GenericParameter)provider; } Enumerator<GenericParameter> enumerator = provider.GenericParameters.GetEnumerator(); try { while (enumerator.MoveNext()) { GenericParameter current = enumerator.Current; if (((MemberReference)current).Name == ((MemberReference)orig).Name) { return current; } } } finally { ((IDisposable)enumerator).Dispose(); } int position = orig.Position; if (provider is MethodReference && orig.DeclaringMethod != null) { if (position < provider.GenericParameters.Count) { return provider.GenericParameters[position]; } return orig.Clone().Update(position, (GenericParameterType)1); } if (provider is TypeReference && ((MemberReference)orig).DeclaringType != null) { if (position < provider.GenericParameters.Count) { return provider.GenericParameters[position]; } return orig.Clone().Update(position, (GenericParameterType)0); } IGenericParameterProvider obj = ((provider is TypeSpecification) ? provider : null); object obj2 = ((obj != null) ? ((IGenericParameterProvider)(object)((TypeSpecification)obj).ElementType).ResolveGenericParameter(orig) : null); if (obj2 == null) { IGenericParameterProvider obj3 = ((provider is MemberReference) ? provider : null); if (obj3 == null) { return null; } TypeReference declaringType = ((MemberReference)obj3).DeclaringType; if (declaringType == null) { return null; } obj2 = ((IGenericParameterProvider)(object)declaringType).ResolveGenericParameter(orig); } return (GenericParameter)obj2; } public static IMetadataTokenProvider Relink(this IMetadataTokenProvider mtp, Relinker relinker, IGenericParameterProvider context) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown if (mtp is TypeReference) { return (IMetadataTokenProvider)(object)Extensions.Relink((TypeReference)mtp, relinker, context); } if (mtp is MethodReference) { return Extensions.Relink((MethodReference)mtp, relinker, context); } if (mtp is FieldReference) { return Extensions.Relink((FieldReference)mtp, relinker, context); } if (mtp is ParameterDefinition) { return (IMetadataTokenProvider)(object)Extensions.Relink((ParameterDefinition)mtp, relinker, context); } if (mtp is CallSite) { return (IMetadataTokenProvider)(object)Extensions.Relink((CallSite)mtp, relinker, context); } throw new InvalidOperationException($"MonoMod can't handle metadata token providers of the type {((object)mtp).GetType()}"); } public static TypeReference Relink(this TypeReference type, Relinker relinker, IGenericParameterProvider context) { //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown if (type == null) { return null; } TypeSpecification val = (TypeSpecification)(object)((type is TypeSpecification) ? type : null); if (val != null) { TypeReference val2 = val.ElementType.Relink(relinker, context); if (type.IsSentinel) { return (TypeReference)new SentinelType(val2); } if (type.IsByReference) { return (TypeReference)new ByReferenceType(val2); } if (type.IsPointer) { return (TypeReference)new PointerType(val2); } if (type.IsPinned) { return (TypeReference)new PinnedType(val2); } if (type.IsArray) { ArrayType val3 = new ArrayType(val2, ((ArrayType)type).Rank); for (int i = 0; i < val3.Rank; i++) { val3.Dimensions[i] = ((ArrayType)type).Dimensions[i]; } return (TypeReference)(object)val3; } if (type.IsRequiredModifier) { return (TypeReference)new RequiredModifierType(((RequiredModifierType)type).ModifierType.Relink(relinker, context), val2); } if (type.IsOptionalModifier) { return (TypeReference)new OptionalModifierType(((OptionalModifierType)type).ModifierType.Relink(relinker, context), val2); } if (type.IsGenericInstance) { GenericInstanceType val4 = new GenericInstanceType(val2); Enumerator<TypeReference> enumerator = ((GenericInstanceType)type).GenericArguments.GetEnumerator(); try { while (enumerator.MoveNext()) { TypeReference current = enumerator.Current; val4.GenericArguments.Add(current?.Relink(relinker, context)); } return (TypeReference)(object)val4; } finally { ((IDisposable)enumerator).Dispose(); } } if (type.IsFunctionPointer) { FunctionPointerType val5 = (FunctionPointerType)type; val5.ReturnType = val5.ReturnType.Relink(relinker, context); for (int j = 0; j < val5.Parameters.Count; j++) { ((ParameterReference)val5.Parameters[j]).ParameterType = ((ParameterReference)val5.Parameters[j]).ParameterType.Relink(relinker, context); } return (TypeReference)(object)val5; } throw new NotSupportedException($"MonoMod can't handle TypeSpecification: {((MemberReference)type).FullName} ({((object)type).GetType()})"); } if (!type.IsGenericParameter || context == null) { return (TypeReference)relinker((IMetadataTokenProvider)(object)type, context); } GenericParameter val6 = context.ResolveGenericParameter((GenericParameter)type); if (val6 == null) { throw new RelinkTargetNotFoundException(string.Format("{0} {1} (context: {2})", "MonoMod relinker failed finding", ((MemberReference)type).FullName, context), (IMetadataTokenProvider)(object)type, (IMetadataTokenProvider)(object)context); } for (int k = 0; k < val6.Constraints.Count; k++) { if (!val6.Constraints[k].GetConstraintType().IsGenericInstance) { val6.Constraints[k] = val6.Constraints[k].Relink(relinker, context); } } return (TypeReference)(object)val6; } public static IMetadataTokenProvider Relink(this MethodReference method, Relinker relinker, IGenericParameterProvider context) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown if (method.IsGenericInstance) { GenericInstanceMethod val = (GenericInstanceMethod)method; GenericInstanceMethod val2 = new GenericInstanceMethod((MethodReference)((MethodSpecification)val).ElementMethod.Relink(relinker, context)); Enumerator<TypeReference> enumerator = val.GenericArguments.GetEnumerator(); try { while (enumerator.MoveNext()) { TypeReference current = enumerator.Current; val2.GenericArguments.Add(current.Relink(relinker, context)); } } finally { ((IDisposable)enumerator).Dispose(); } return (IMetadataTokenProvider)(MethodReference)relinker((IMetadataTokenProvider)(object)val2, context); } MethodReference val3 = new MethodReference(((MemberReference)method).Name, method.ReturnType, ((MemberReference)method).DeclaringType.Relink(relinker, context)); val3.CallingConvention = method.CallingConvention; val3.ExplicitThis = method.ExplicitThis; val3.HasThis = method.HasThis; Enumerator<GenericParameter> enumerator2 = method.GenericParameters.GetEnumerator(); try { while (enumerator2.MoveNext()) { GenericParameter current2 = enumerator2.Current; val3.GenericParameters.Add(current2.Relink(relinker, context)); } } finally { ((IDisposable)enumerator2).Dispose(); } val3.ReturnType = val3.ReturnType?.Relink(relinker, (IGenericParameterProvider)(object)val3); Enumerator<ParameterDefinition> enumerator3 = method.Parameters.GetEnumerator(); try { while (enumerator3.MoveNext()) { ParameterDefinition current3 = enumerator3.Current; ((ParameterReference)current3).ParameterType = ((ParameterReference)current3).ParameterType.Relink(relinker, (IGenericParameterProvider)(object)method); val3.Parameters.Add(current3); } } finally { ((IDisposable)enumerator3).Dispose(); } retur
BepInEx/core/XUnity.Common.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Utils; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using XUnity.Common.Constants; using XUnity.Common.Extensions; using XUnity.Common.Logging; using XUnity.Common.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("XUnity.AutoTranslator.Plugin.Core")] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Common dependencies shared between XUnity Auto Translator and Resource Redirector.")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: AssemblyProduct("XUnity.Common")] [assembly: AssemblyTitle("XUnity.Common")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.0")] [module: UnverifiableCode] namespace XUnity.Common.Utilities { public static class ArrayHelper { public static T[] Null<T>() { return null; } } public static class CabHelper { private static string CreateRandomCab() { return "CAB-" + Guid.NewGuid().ToString("N"); } public static void RandomizeCab(byte[] assetBundleData) { string @string = Encoding.ASCII.GetString(assetBundleData, 0, Math.Min(1024, assetBundleData.Length - 4)); int num = @string.IndexOf("CAB-", StringComparison.Ordinal); if (num >= 0) { int num2 = @string.Substring(num).IndexOf('\0'); if (num2 >= 0 && num2 <= 36) { string s = CreateRandomCab(); Buffer.BlockCopy(Encoding.ASCII.GetBytes(s), 36 - num2, assetBundleData, num, num2); } } } public static void RandomizeCabWithAnyLength(byte[] assetBundleData) { FindAndReplaceCab("CAB-", 0, assetBundleData, 2048); } private static void FindAndReplaceCab(string ansiStringToStartWith, byte byteToEndWith, byte[] data, int maxIterations = -1) { int num = Math.Min(data.Length, maxIterations); if (num == -1) { num = data.Length; } int num2 = 0; int length = ansiStringToStartWith.Length; string text = Guid.NewGuid().ToString("N"); int num3 = 0; for (int i = 0; i < num; i++) { char c = (char)data[i]; if (num2 == length) { while (data[i] != byteToEndWith && i < num) { if (num3 >= text.Length) { num3 = 0; text = Guid.NewGuid().ToString("N"); } data[i++] = (byte)text[num3++]; } break; } num2 = ((c == ansiStringToStartWith[num2]) ? (num2 + 1) : 0); } } } internal static class CecilFastReflectionHelper { private static readonly Type[] DynamicMethodDelegateArgs = new Type[2] { typeof(object), typeof(object[]) }; public static FastReflectionDelegate CreateFastDelegate(MethodBase method, bool directBoxValueAccess, bool forceNonVirtcall) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown DynamicMethodDefinition val = new DynamicMethodDefinition("FastReflection<" + method.DeclaringType.FullName + "." + method.Name + ">", typeof(object), DynamicMethodDelegateArgs); ILProcessor iLProcessor = val.GetILProcessor(); ParameterInfo[] parameters = method.GetParameters(); bool flag = true; if (!method.IsStatic) { iLProcessor.Emit(OpCodes.Ldarg_0); if (method.DeclaringType.IsValueType) { Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, method.DeclaringType); } } for (int i = 0; i < parameters.Length; i++) { Type type = parameters[i].ParameterType; bool isByRef = type.IsByRef; if (isByRef) { type = type.GetElementType(); } bool isValueType = type.IsValueType; if (isByRef && isValueType && !directBoxValueAccess) { iLProcessor.Emit(OpCodes.Ldarg_1); iLProcessor.Emit(OpCodes.Ldc_I4, i); } iLProcessor.Emit(OpCodes.Ldarg_1); iLProcessor.Emit(OpCodes.Ldc_I4, i); if (isByRef && !isValueType) { Extensions.Emit(iLProcessor, OpCodes.Ldelema, typeof(object)); continue; } iLProcessor.Emit(OpCodes.Ldelem_Ref); if (!isValueType) { continue; } if (!isByRef || !directBoxValueAccess) { Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, type); if (isByRef) { Extensions.Emit(iLProcessor, OpCodes.Box, type); iLProcessor.Emit(OpCodes.Dup); Extensions.Emit(iLProcessor, OpCodes.Unbox, type); if (flag) { flag = false; val.Definition.Body.Variables.Add(new VariableDefinition((TypeReference)new PinnedType((TypeReference)new PointerType(((MemberReference)val.Definition).Module.TypeSystem.Void)))); } iLProcessor.Emit(OpCodes.Stloc_0); iLProcessor.Emit(OpCodes.Stelem_Ref); iLProcessor.Emit(OpCodes.Ldloc_0); } } else { Extensions.Emit(iLProcessor, OpCodes.Unbox, type); } } if (method.IsConstructor) { Extensions.Emit(iLProcessor, OpCodes.Newobj, (MethodBase)(method as ConstructorInfo)); } else if (method.IsFinal || !method.IsVirtual || forceNonVirtcall) { Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)(method as MethodInfo)); } else { Extensions.Emit(iLProcessor, OpCodes.Callvirt, (MethodBase)(method as MethodInfo)); } Type type2 = (method.IsConstructor ? method.DeclaringType : (method as MethodInfo).ReturnType); if ((object)type2 != typeof(void)) { if (type2.IsValueType) { Extensions.Emit(iLProcessor, OpCodes.Box, type2); } } else { iLProcessor.Emit(OpCodes.Ldnull); } iLProcessor.Emit(OpCodes.Ret); return (FastReflectionDelegate)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(FastReflectionDelegate)); } public static Func<T, F> CreateFastFieldGetter<T, F>(FieldInfo fieldInfo) { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType)) { throw new ArgumentException("FieldInfo type does not match return type."); } if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T)))) { throw new MissingFieldException(typeof(T).Name, fieldInfo.Name); } DynamicMethodDefinition val = new DynamicMethodDefinition("FastReflection<" + typeof(T).FullName + ".Get_" + fieldInfo.Name + ">", typeof(F), new Type[1] { typeof(T) }); ILProcessor iLProcessor = val.GetILProcessor(); if (!fieldInfo.IsStatic) { iLProcessor.Emit(OpCodes.Ldarg_0); Extensions.Emit(iLProcessor, OpCodes.Castclass, fieldInfo.DeclaringType); } Extensions.Emit(iLProcessor, fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, fieldInfo); if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType) { Extensions.Emit(iLProcessor, OpCodes.Box, fieldInfo.FieldType); } iLProcessor.Emit(OpCodes.Ret); return (Func<T, F>)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(Func<T, F>)); } public static Action<T, F> CreateFastFieldSetter<T, F>(FieldInfo fieldInfo) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType)) { throw new ArgumentException("FieldInfo type does not match argument type."); } if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T)))) { throw new MissingFieldException(typeof(T).Name, fieldInfo.Name); } DynamicMethodDefinition val = new DynamicMethodDefinition("FastReflection<" + typeof(T).FullName + ".Set_" + fieldInfo.Name + ">", (Type)null, new Type[2] { typeof(T), typeof(F) }); ILProcessor iLProcessor = val.GetILProcessor(); if (!fieldInfo.IsStatic) { iLProcessor.Emit(OpCodes.Ldarg_0); Extensions.Emit(iLProcessor, OpCodes.Castclass, fieldInfo.DeclaringType); } iLProcessor.Emit(OpCodes.Ldarg_1); if ((object)fieldInfo.FieldType != typeof(F)) { if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType) { if (fieldInfo.FieldType.IsValueType) { Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, fieldInfo.FieldType); } else { Extensions.Emit(iLProcessor, OpCodes.Box, fieldInfo.FieldType); } } else { Extensions.Emit(iLProcessor, OpCodes.Castclass, fieldInfo.FieldType); } } Extensions.Emit(iLProcessor, fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo); iLProcessor.Emit(OpCodes.Ret); return (Action<T, F>)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(Action<T, F>)); } } public static class CustomFastReflectionHelper { private struct FastReflectionDelegateKey { public MethodBase Method { get; } public bool DirectBoxValueAccess { get; } public bool ForceNonVirtCall { get; } public FastReflectionDelegateKey(MethodBase method, bool directBoxValueAccess, bool forceNonVirtCall) { Method = method; DirectBoxValueAccess = directBoxValueAccess; ForceNonVirtCall = forceNonVirtCall; } public override bool Equals(object obj) { if (obj is FastReflectionDelegateKey fastReflectionDelegateKey && EqualityComparer<MethodBase>.Default.Equals(Method, fastReflectionDelegateKey.Method) && DirectBoxValueAccess == fastReflectionDelegateKey.DirectBoxValueAccess) { return ForceNonVirtCall == fastReflectionDelegateKey.ForceNonVirtCall; } return false; } public override int GetHashCode() { return ((1017116076 * -1521134295 + EqualityComparer<MethodBase>.Default.GetHashCode(Method)) * -1521134295 + DirectBoxValueAccess.GetHashCode()) * -1521134295 + ForceNonVirtCall.GetHashCode(); } } private static readonly Dictionary<FastReflectionDelegateKey, FastReflectionDelegate> MethodCache = new Dictionary<FastReflectionDelegateKey, FastReflectionDelegate>(); public static FastReflectionDelegate CreateFastDelegate(this MethodBase method, bool directBoxValueAccess = true, bool forceNonVirtCall = false) { FastReflectionDelegateKey key = new FastReflectionDelegateKey(method, directBoxValueAccess, forceNonVirtCall); if (MethodCache.TryGetValue(key, out var value)) { return value; } value = (((object)ClrTypes.DynamicMethodDefinition == null) ? GetFastDelegateForSRE(method, directBoxValueAccess, forceNonVirtCall) : GetFastDelegateForCecil(method, directBoxValueAccess, forceNonVirtCall)); MethodCache.Add(key, value); return value; } public static Func<T, F> CreateFastFieldGetter<T, F>(FieldInfo fieldInfo) { if ((object)ClrTypes.DynamicMethodDefinition != null) { return CreateFastFieldGetterForCecil<T, F>(fieldInfo); } return CreateFastFieldGetterForSRE<T, F>(fieldInfo); } public static Action<T, F> CreateFastFieldSetter<T, F>(FieldInfo fieldInfo) { if ((object)ClrTypes.DynamicMethodDefinition != null) { return CreateFastFieldSetterForCecil<T, F>(fieldInfo); } return CreateFastFieldSetterForSRE<T, F>(fieldInfo); } private static FastReflectionDelegate GetFastDelegateForCecil(MethodBase method, bool directBoxValueAccess, bool forceNonVirtCall) { try { return CecilFastReflectionHelper.CreateFastDelegate(method, directBoxValueAccess, forceNonVirtCall); } catch (Exception e) { try { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with cecil. Retrying with reflection emit..."); return ReflectionEmitFastReflectionHelper.CreateFastDelegate(method, directBoxValueAccess, forceNonVirtCall); } catch (Exception e2) { XuaLogger.Common.Warn(e2, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return (object target, object[] args) => method.Invoke(target, args); } } } private static Func<T, F> CreateFastFieldGetterForCecil<T, F>(FieldInfo fieldInfo) { try { return CecilFastReflectionHelper.CreateFastFieldGetter<T, F>(fieldInfo); } catch (Exception e) { try { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with cecil. Retrying with reflection emit..."); return ReflectionEmitFastReflectionHelper.CreateFastFieldGetter<T, F>(fieldInfo); } catch (Exception e2) { XuaLogger.Common.Warn(e2, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return (T target) => (F)fieldInfo.GetValue(target); } } } private static Action<T, F> CreateFastFieldSetterForCecil<T, F>(FieldInfo fieldInfo) { try { return CecilFastReflectionHelper.CreateFastFieldSetter<T, F>(fieldInfo); } catch (Exception e) { try { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with cecil. Retrying with reflection emit..."); return ReflectionEmitFastReflectionHelper.CreateFastFieldSetter<T, F>(fieldInfo); } catch (Exception e2) { XuaLogger.Common.Warn(e2, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return delegate(T target, F value) { fieldInfo.SetValue(target, value); }; } } } private static FastReflectionDelegate GetFastDelegateForSRE(MethodBase method, bool directBoxValueAccess, bool forceNonVirtCall) { try { return ReflectionEmitFastReflectionHelper.CreateFastDelegate(method, directBoxValueAccess, forceNonVirtCall); } catch (Exception e) { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return (object target, object[] args) => method.Invoke(target, args); } } private static Func<T, F> CreateFastFieldGetterForSRE<T, F>(FieldInfo fieldInfo) { try { return ReflectionEmitFastReflectionHelper.CreateFastFieldGetter<T, F>(fieldInfo); } catch (Exception e) { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return (T target) => (F)fieldInfo.GetValue(target); } } private static Action<T, F> CreateFastFieldSetterForSRE<T, F>(FieldInfo fieldInfo) { try { return ReflectionEmitFastReflectionHelper.CreateFastFieldSetter<T, F>(fieldInfo); } catch (Exception e) { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return delegate(T target, F value) { fieldInfo.SetValue(target, value); }; } } } public static class DiacriticHelper { public static string RemoveAllDiacritics(this string input) { return new string((from c in input.SafeNormalize(NormalizationForm.FormD) where CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark select c).ToArray()).SafeNormalize(); } private static string SafeNormalize(this string input, NormalizationForm normalizationForm = NormalizationForm.FormC) { return ReplaceNonCharacters(input, '?').Normalize(normalizationForm); } private static string ReplaceNonCharacters(string input, char replacement) { StringBuilder stringBuilder = new StringBuilder(input.Length); for (int i = 0; i < input.Length; i++) { if (char.IsSurrogatePair(input, i)) { int num = char.ConvertToUtf32(input, i); i++; if (IsValidCodePoint(num)) { stringBuilder.Append(char.ConvertFromUtf32(num)); } else { stringBuilder.Append(replacement); } } else { char c = input[i]; if (IsValidCodePoint(c)) { stringBuilder.Append(c); } else { stringBuilder.Append(replacement); } } } return stringBuilder.ToString(); } private static bool IsValidCodePoint(int point) { if (point >= 64976) { if (point >= 65008 && (point & 0xFFFF) != 65535 && (point & 0xFFFE) != 65534) { return point <= 1114111; } return false; } return true; } } public static class ExpressionHelper { public static Delegate CreateTypedFastInvoke(MethodBase method) { if ((object)method == null) { throw new ArgumentNullException("method"); } return CreateTypedFastInvokeUnchecked(method); } public static Delegate CreateTypedFastInvokeUnchecked(MethodBase method) { if ((object)method == null) { return null; } if (method.IsGenericMethod) { throw new ArgumentException("The provided method must not be generic.", "method"); } if (method is MethodInfo methodInfo) { Expression[] arguments; if (method.IsStatic) { ParameterExpression[] array = (from p in methodInfo.GetParameters() select Expression.Parameter(p.ParameterType, p.Name)).ToArray(); arguments = array; return Expression.Lambda(Expression.Call(null, methodInfo, arguments), array).Compile(); } List<ParameterExpression> list = (from p in methodInfo.GetParameters() select Expression.Parameter(p.ParameterType, p.Name)).ToList(); list.Insert(0, Expression.Parameter(methodInfo.DeclaringType, "instance")); ParameterExpression instance = list[0]; arguments = list.Skip(1).ToArray(); return Expression.Lambda(Expression.Call(instance, methodInfo, arguments), list.ToArray()).Compile(); } if (method is ConstructorInfo constructorInfo) { ParameterExpression[] array2 = (from p in constructorInfo.GetParameters() select Expression.Parameter(p.ParameterType, p.Name)).ToArray(); Expression[] arguments = array2; return Expression.Lambda(Expression.New(constructorInfo, arguments), array2).Compile(); } throw new ArgumentException("method", "This method only supports MethodInfo and ConstructorInfo."); } } public static class ExtensionDataHelper { private static readonly object Sync; private static readonly WeakDictionary<object, object> WeakDynamicFields; public static int WeakReferenceCount { get { lock (Sync) { return WeakDynamicFields.Count; } } } static ExtensionDataHelper() { Sync = new object(); WeakDynamicFields = new WeakDictionary<object, object>(); MaintenanceHelper.AddMaintenanceFunction(Cull, 12); } public static void SetExtensionData<T>(this object obj, T t) { lock (Sync) { if (WeakDynamicFields.TryGetValue(obj, out var value)) { if (value is Dictionary<Type, object> dictionary) { dictionary[typeof(T)] = t; return; } Dictionary<Type, object> dictionary2 = new Dictionary<Type, object>(); dictionary2.Add(value.GetType(), value); dictionary2[typeof(T)] = t; WeakDynamicFields[obj] = dictionary2; } else { WeakDynamicFields[obj] = t; } } } public static T GetOrCreateExtensionData<T>(this object obj) where T : new() { if (obj == null) { return default(T); } lock (Sync) { if (WeakDynamicFields.TryGetValue(obj, out var value)) { if (value is Dictionary<Type, object> dictionary) { if (dictionary.TryGetValue(typeof(T), out value)) { return (T)value; } T val = new T(); dictionary[typeof(T)] = val; return val; } if (!(value is T result)) { Dictionary<Type, object> dictionary2 = new Dictionary<Type, object>(); dictionary2.Add(value.GetType(), value); T val2 = new T(); dictionary2[typeof(T)] = val2; WeakDynamicFields[obj] = dictionary2; return val2; } return result; } T val3 = new T(); WeakDynamicFields[obj] = val3; return val3; } } public static T GetExtensionData<T>(this object obj) { if (obj == null) { return default(T); } lock (Sync) { if (WeakDynamicFields.TryGetValue(obj, out var value)) { if (value is Dictionary<Type, object> dictionary && dictionary.TryGetValue(typeof(T), out value)) { if (!(value is T result)) { return default(T); } return result; } if (!(value is T result2)) { return default(T); } return result2; } } return default(T); } public static void Cull() { lock (Sync) { WeakDynamicFields.RemoveCollectedEntries(); } } public static List<KeyValuePair<object, object>> GetAllRegisteredObjects() { lock (Sync) { return IterateAllPairs().ToList(); } } public static void Remove(object obj) { lock (Sync) { WeakDynamicFields.Remove(obj); } } private static IEnumerable<KeyValuePair<object, object>> IterateAllPairs() { foreach (KeyValuePair<object, object> kvp in WeakDynamicFields) { if (kvp.Value is Dictionary<Type, object> dictionary) { foreach (KeyValuePair<Type, object> item in dictionary) { yield return new KeyValuePair<object, object>(kvp.Key, item.Value); } } else { yield return kvp; } } } } public delegate object FastReflectionDelegate(object target, params object[] args); public static class HookingHelper { private static readonly MethodInfo PatchMethod12; private static readonly MethodInfo PatchMethod20; private static readonly object Harmony; private static bool _loggedHarmonyError; static HookingHelper() { PatchMethod12 = ClrTypes.HarmonyInstance?.GetMethod("Patch", new Type[4] { ClrTypes.MethodBase, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod }); PatchMethod20 = ClrTypes.Harmony?.GetMethod("Patch", new Type[5] { ClrTypes.MethodBase, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod }); _loggedHarmonyError = false; try { if ((object)ClrTypes.HarmonyInstance != null) { Harmony = ClrTypes.HarmonyInstance.GetMethod("Create", BindingFlags.Static | BindingFlags.Public).Invoke(null, new object[1] { "xunity.common.hookinghelper" }); } else if ((object)ClrTypes.Harmony != null) { Harmony = ClrTypes.Harmony.GetConstructor(new Type[1] { typeof(string) }).Invoke(new object[1] { "xunity.common.hookinghelper" }); } else { XuaLogger.Common.Error("An unexpected exception occurred during harmony initialization, likely caused by unknown Harmony version. Harmony hooks will be unavailable!"); } } catch (Exception e) { XuaLogger.Common.Error(e, "An unexpected exception occurred during harmony initialization. Harmony hooks will be unavailable!"); } } public static void PatchAll(IEnumerable<Type> types, bool forceExternHooks) { foreach (Type type in types) { PatchType(type, forceExternHooks); } } public static void PatchAll(IEnumerable<Type[]> types, bool forceMonoModHooks) { foreach (Type[] type in types) { for (int i = 0; i < type.Length && !PatchType(type[i], forceMonoModHooks); i++) { } } } public static bool PatchType(Type type, bool forceExternHooks) { MethodBase methodBase = null; IntPtr intPtr = IntPtr.Zero; try { if (Harmony == null && !_loggedHarmonyError) { _loggedHarmonyError = true; XuaLogger.Common.Warn("Harmony is not loaded or could not be initialized. Using fallback hooks instead."); } BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo method = type.GetMethod("Prepare", bindingAttr); if ((object)method == null || (bool)method.Invoke(null, new object[1] { Harmony })) { try { methodBase = (MethodBase)(type.GetMethod("TargetMethod", bindingAttr)?.Invoke(null, new object[1] { Harmony })); } catch { } try { intPtr = ((IntPtr?)type.GetMethod("TargetMethodPointer", bindingAttr)?.Invoke(null, null)) ?? IntPtr.Zero; } catch { } if ((object)methodBase == null && intPtr == IntPtr.Zero) { if ((object)methodBase != null) { XuaLogger.Common.Warn("Could not hook '" + methodBase.DeclaringType.FullName + "." + methodBase.Name + "'. Likely due differences between different versions of the engine or text framework."); } else { XuaLogger.Common.Warn("Could not hook '" + type.Name + "'. Likely due differences between different versions of the engine or text framework."); } return false; } MethodInfo method2 = type.GetMethod("Prefix", bindingAttr); MethodInfo method3 = type.GetMethod("Postfix", bindingAttr); MethodInfo method4 = type.GetMethod("Finalizer", bindingAttr); if ((object)methodBase == null || forceExternHooks || Harmony == null || ((object)method2 == null && (object)method3 == null && (object)method4 == null)) { return PatchWithExternHooks(type, methodBase, intPtr, forced: true); } if ((object)methodBase != null) { try { int? priority = type.GetCustomAttributes(typeof(HookingHelperPriorityAttribute), inherit: false).OfType<HookingHelperPriorityAttribute>().FirstOrDefault()?.priority; object obj3 = (((object)method2 != null) ? CreateHarmonyMethod(method2, priority) : null); object obj4 = (((object)method3 != null) ? CreateHarmonyMethod(method3, priority) : null); object obj5 = (((object)method4 != null) ? CreateHarmonyMethod(method4, priority) : null); if ((object)PatchMethod12 != null) { PatchMethod12.Invoke(Harmony, new object[4] { methodBase, obj3, obj4, null }); } else { PatchMethod20.Invoke(Harmony, new object[5] { methodBase, obj3, obj4, null, obj5 }); } XuaLogger.Common.Debug("Hooked " + methodBase.DeclaringType.FullName + "." + methodBase.Name + " through Harmony hooks."); return true; } catch (Exception e) when (((Func<bool>)delegate { // Could not convert BlockContainer to single expression System.Runtime.CompilerServices.Unsafe.SkipInit(out int num); if (e.FirstInnerExceptionOfType<PlatformNotSupportedException>() == null) { ArgumentException ex = e.FirstInnerExceptionOfType<ArgumentException>(); num = ((ex != null && ex.Message?.Contains("no body") == true) ? 1 : 0); } else { num = 1; } return num != 0; }).Invoke()) { return PatchWithExternHooks(type, methodBase, intPtr, forced: false); } } XuaLogger.Common.Warn("Could not hook '" + type.Name + "'. Likely due differences between different versions of the engine or text framework."); } } catch (Exception e2) { if ((object)methodBase != null) { XuaLogger.Common.Warn(e2, "An error occurred while patching property/method '" + methodBase.DeclaringType.FullName + "." + methodBase.Name + "'. Failing hook: '" + type.Name + "'."); } else { XuaLogger.Common.Warn(e2, "An error occurred while patching property/method. Failing hook: '" + type.Name + "'."); } } return false; } private static bool PatchWithExternHooks(Type type, MethodBase original, IntPtr originalPtr, bool forced) { BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; if ((object)ClrTypes.Imports != null) { if (originalPtr == IntPtr.Zero) { XuaLogger.Common.Warn("Could not hook '" + type.Name + "'. Likely due differences between different versions of the engine or text framework."); return false; } IntPtr? intPtr = type.GetMethod("ML_Detour", bindingAttr)?.MethodHandle.GetFunctionPointer(); if (intPtr.HasValue && intPtr.Value != IntPtr.Zero) { ClrTypes.Imports.GetMethod("Hook", bindingAttr).Invoke(null, new object[2] { originalPtr, intPtr.Value }); XuaLogger.Common.Debug("Hooked " + type.Name + " through MelonMod Imports.Hook method."); return true; } XuaLogger.Common.Warn("Could not hook '" + type.Name + "' because no detour method was found."); } else { if ((object)original == null) { XuaLogger.Common.Warn("Cannot hook '" + type.Name + "'. Could not locate the original method. Failing hook: '" + type.Name + "'."); return false; } if ((object)ClrTypes.Hook == null || (object)ClrTypes.NativeDetour == null) { XuaLogger.Common.Warn("Cannot hook '" + original.DeclaringType.FullName + "." + original.Name + "'. MonoMod hooks is not supported in this runtime as MonoMod is not loaded. Failing hook: '" + type.Name + "'."); return false; } object obj = type.GetMethod("Get_MM_Detour", bindingAttr)?.Invoke(null, null) ?? type.GetMethod("MM_Detour", bindingAttr); if (obj != null) { string text = "(managed)"; object obj2; try { obj2 = ClrTypes.Hook.GetConstructor(new Type[2] { typeof(MethodBase), typeof(MethodInfo) }).Invoke(new object[2] { original, obj }); obj2.GetType().GetMethod("Apply").Invoke(obj2, null); } catch (Exception e) when (((Func<bool>)delegate { // Could not convert BlockContainer to single expression System.Runtime.CompilerServices.Unsafe.SkipInit(out int num); if (e.FirstInnerExceptionOfType<NullReferenceException>() == null) { NotSupportedException ex = e.FirstInnerExceptionOfType<NotSupportedException>(); num = ((ex != null && ex.Message?.Contains("Body-less") == true) ? 1 : 0); } else { num = 1; } return num != 0; }).Invoke()) { text = "(native)"; obj2 = ClrTypes.NativeDetour.GetConstructor(new Type[2] { typeof(MethodBase), typeof(MethodBase) }).Invoke(new object[2] { original, obj }); obj2.GetType().GetMethod("Apply").Invoke(obj2, null); } type.GetMethod("MM_Init", bindingAttr)?.Invoke(null, new object[1] { obj2 }); if (forced) { XuaLogger.Common.Debug("Hooked " + original.DeclaringType.FullName + "." + original.Name + " through forced MonoMod hooks. " + text); } else { XuaLogger.Common.Debug("Hooked " + original.DeclaringType.FullName + "." + original.Name + " through MonoMod hooks. " + text); } return true; } if (forced) { XuaLogger.Common.Warn("Cannot hook '" + original.DeclaringType.FullName + "." + original.Name + "'. Harmony is not supported in this runtime and no alternate MonoMod hook has been implemented. Failing hook: '" + type.Name + "'."); } else { XuaLogger.Common.Warn("Cannot hook '" + original.DeclaringType.FullName + "." + original.Name + "'. Harmony is not supported in this runtime and no alternate MonoMod hook has been implemented. Failing hook: '" + type.Name + "'."); } } return false; } private static object CreateHarmonyMethod(MethodInfo method, int? priority) { object obj = ClrTypes.HarmonyMethod.GetConstructor(new Type[1] { typeof(MethodInfo) }).Invoke(new object[1] { method }); if (priority.HasValue) { (ClrTypes.HarmonyMethod.GetField("priority", BindingFlags.Instance | BindingFlags.Public) ?? ClrTypes.HarmonyMethod.GetField("prioritiy", BindingFlags.Instance | BindingFlags.Public)).SetValue(obj, priority.Value); } return obj; } } public class HookingHelperPriorityAttribute : Attribute { public int priority; public HookingHelperPriorityAttribute(int priority) { this.priority = priority; } } public static class HookPriority { public const int Last = 0; public const int VeryLow = 100; public const int Low = 200; public const int LowerThanNormal = 300; public const int Normal = 400; public const int HigherThanNormal = 500; public const int High = 600; public const int VeryHigh = 700; public const int First = 800; } public static class ListExtensions { public static void BinarySearchInsert<T>(this List<T> items, T item) where T : IComparable<T> { int num = items.BinarySearch(item); if (num < 0) { items.Insert(~num, item); } else { items.Insert(num, item); } } } public static class MaintenanceHelper { private class ActionRegistration { public Action Action { get; } public int Filter { get; } public ActionRegistration(Action action, int filter) { Action = action; Filter = filter; } } private static readonly object Sync = new object(); private static readonly List<ActionRegistration> RegisteredActions = new List<ActionRegistration>(); private static bool _initialized; public static void AddMaintenanceFunction(Action action, int filter) { lock (Sync) { if (!_initialized) { _initialized = true; StartMaintenance(); } ActionRegistration item = new ActionRegistration(action, filter); RegisteredActions.Add(item); } } private static void StartMaintenance() { Thread thread = new Thread(MaintenanceLoop); thread.IsBackground = true; thread.Start(); } private static void MaintenanceLoop(object state) { int num = 0; while (true) { lock (Sync) { foreach (ActionRegistration registeredAction in RegisteredActions) { if (num % registeredAction.Filter == 0) { try { registeredAction.Action(); } catch (Exception e) { XuaLogger.Common.Error(e, "An unexpected error occurred during maintenance."); } } } } num++; Thread.Sleep(5000); } } } public static class Paths { private static string _gameRoot; public static string GameRoot { get { return _gameRoot ?? GetAndSetGameRoot(); } set { _gameRoot = value; } } public static void Initialize() { GetAndSetGameRoot(); } private static string GetAndSetGameRoot() { return _gameRoot = new DirectoryInfo(Application.dataPath).Parent.FullName; } } public static class ReflectionCache { private struct MemberLookupKey { public Type Type { get; set; } public string MemberName { get; set; } public MemberLookupKey(Type type, string memberName) { Type = type; MemberName = memberName; } public override bool Equals(object obj) { if (obj is MemberLookupKey memberLookupKey) { if ((object)Type == memberLookupKey.Type) { return MemberName == memberLookupKey.MemberName; } return false; } return false; } public override int GetHashCode() { return Type.GetHashCode() + MemberName.GetHashCode(); } } private static Dictionary<MemberLookupKey, CachedMethod> Methods = new Dictionary<MemberLookupKey, CachedMethod>(); private static Dictionary<MemberLookupKey, CachedProperty> Properties = new Dictionary<MemberLookupKey, CachedProperty>(); private static Dictionary<MemberLookupKey, CachedField> Fields = new Dictionary<MemberLookupKey, CachedField>(); public static CachedMethod CachedMethod(this Type type, string name) { return type.CachedMethod(name, (Type[])null); } public static CachedMethod CachedMethod(this Type type, string name, params Type[] types) { MemberLookupKey key = new MemberLookupKey(type, name); if (!Methods.TryGetValue(key, out var value)) { Type type2 = type; MethodInfo methodInfo = null; while ((object)methodInfo == null && (object)type2 != null) { methodInfo = ((types != null && types.Length != 0) ? type2.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, types, null) : type2.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); type2 = type2.BaseType; } if ((object)methodInfo != null) { value = new CachedMethod(methodInfo); } Methods[key] = value; } return value; } public static CachedProperty CachedProperty(this Type type, string name) { MemberLookupKey key = new MemberLookupKey(type, name); if (!Properties.TryGetValue(key, out var value)) { Type type2 = type; PropertyInfo propertyInfo = null; while ((object)propertyInfo == null && (object)type2 != null) { propertyInfo = type2.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); type2 = type2.BaseType; } if ((object)propertyInfo != null) { value = new CachedProperty(propertyInfo); } Properties[key] = value; } return value; } public static CachedField CachedField(this Type type, string name) { MemberLookupKey key = new MemberLookupKey(type, name); if (!Fields.TryGetValue(key, out var value)) { Type type2 = type; FieldInfo fieldInfo = null; while ((object)fieldInfo == null && (object)type2 != null) { fieldInfo = type2.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); type2 = type2.BaseType; } if ((object)fieldInfo != null) { value = new CachedField(fieldInfo); } Fields[key] = value; } return value; } public static CachedField CachedFieldByIndex(this Type type, int index, Type fieldType, BindingFlags flags) { FieldInfo[] array = (from x in type.GetFields(flags) where (object)x.FieldType == fieldType select x).ToArray(); if (index < array.Length) { return new CachedField(array[index]); } return null; } } public class CachedMethod { private static readonly object[] Args0 = new object[0]; private static readonly object[] Args1 = new object[1]; private static readonly object[] Args2 = new object[2]; private FastReflectionDelegate _invoke; internal CachedMethod(MethodInfo method) { _invoke = method.CreateFastDelegate(); } public object Invoke(object instance, object[] arguments) { return _invoke(instance, arguments); } public object Invoke(object instance) { return _invoke(instance, Args0); } public object Invoke(object instance, object arg1) { try { Args1[0] = arg1; return _invoke(instance, Args1); } finally { Args1[0] = null; } } public object Invoke(object instance, object arg1, object arg2) { try { Args2[0] = arg1; Args2[1] = arg2; return _invoke(instance, Args2); } finally { Args2[0] = null; Args2[1] = null; } } } public class CachedProperty { private static readonly object[] Args0 = new object[0]; private static readonly object[] Args1 = new object[1]; private FastReflectionDelegate _set; private FastReflectionDelegate _get; public Type PropertyType { get; } internal CachedProperty(PropertyInfo propertyInfo) { if (propertyInfo.CanRead) { _get = propertyInfo.GetGetMethod(nonPublic: true).CreateFastDelegate(); } if (propertyInfo.CanWrite) { _set = propertyInfo.GetSetMethod(nonPublic: true).CreateFastDelegate(); } PropertyType = propertyInfo.PropertyType; } public void Set(object instance, object[] arguments) { if (_set != null) { _set(instance, arguments); } } public void Set(object instance, object arg1) { if (_set == null) { return; } try { Args1[0] = arg1; _set(instance, Args1); } finally { Args1[0] = null; } } public object Get(object instance, object[] arguments) { if (_get == null) { return null; } return _get(instance, arguments); } public object Get(object instance) { if (_get == null) { return null; } return _get(instance, Args0); } } public class CachedField { private Func<object, object> _get; private Action<object, object> _set; public Type FieldType { get; } internal CachedField(FieldInfo fieldInfo) { _get = CustomFastReflectionHelper.CreateFastFieldGetter<object, object>(fieldInfo); _set = CustomFastReflectionHelper.CreateFastFieldSetter<object, object>(fieldInfo); FieldType = fieldInfo.FieldType; } public void Set(object instance, object value) { if (_set != null) { _set(instance, value); } } public object Get(object instance) { if (_get == null) { return null; } return _get(instance); } } internal static class ReflectionEmitFastReflectionHelper { private static readonly Type[] DynamicMethodDelegateArgs = new Type[2] { typeof(object), typeof(object[]) }; public static FastReflectionDelegate CreateFastDelegate(MethodBase method, bool directBoxValueAccess, bool forceNonVirtcall) { DynamicMethod dynamicMethod = new DynamicMethod("FastReflection<" + method.DeclaringType.FullName + "." + method.Name + ">", typeof(object), DynamicMethodDelegateArgs, method.DeclaringType.Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); ParameterInfo[] parameters = method.GetParameters(); bool flag = true; if (!method.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); if (method.DeclaringType.IsValueType) { iLGenerator.Emit(OpCodes.Unbox_Any, method.DeclaringType); } } for (int i = 0; i < parameters.Length; i++) { Type type = parameters[i].ParameterType; bool isByRef = type.IsByRef; if (isByRef) { type = type.GetElementType(); } bool isValueType = type.IsValueType; if (isByRef && isValueType && !directBoxValueAccess) { iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Ldc_I4, i); } iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Ldc_I4, i); if (isByRef && !isValueType) { iLGenerator.Emit(OpCodes.Ldelema, typeof(object)); continue; } iLGenerator.Emit(OpCodes.Ldelem_Ref); if (!isValueType) { continue; } if (!isByRef || !directBoxValueAccess) { iLGenerator.Emit(OpCodes.Unbox_Any, type); if (isByRef) { iLGenerator.Emit(OpCodes.Box, type); iLGenerator.Emit(OpCodes.Dup); iLGenerator.Emit(OpCodes.Unbox, type); if (flag) { flag = false; throw new NotImplementedException("No idea how to implement this..."); } iLGenerator.Emit(OpCodes.Stloc_0); iLGenerator.Emit(OpCodes.Stelem_Ref); iLGenerator.Emit(OpCodes.Ldloc_0); } } else { iLGenerator.Emit(OpCodes.Unbox, type); } } if (method.IsConstructor) { iLGenerator.Emit(OpCodes.Newobj, method as ConstructorInfo); } else if (method.IsFinal || !method.IsVirtual || forceNonVirtcall) { iLGenerator.Emit(OpCodes.Call, method as MethodInfo); } else { iLGenerator.Emit(OpCodes.Callvirt, method as MethodInfo); } Type type2 = (method.IsConstructor ? method.DeclaringType : (method as MethodInfo).ReturnType); if ((object)type2 != typeof(void)) { if (type2.IsValueType) { iLGenerator.Emit(OpCodes.Box, type2); } } else { iLGenerator.Emit(OpCodes.Ldnull); } iLGenerator.Emit(OpCodes.Ret); return (FastReflectionDelegate)dynamicMethod.CreateDelegate(typeof(FastReflectionDelegate)); } public static Func<T, F> CreateFastFieldGetter<T, F>(FieldInfo fieldInfo) { if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType)) { throw new ArgumentException("FieldInfo type does not match return type."); } if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T)))) { throw new MissingFieldException(typeof(T).Name, fieldInfo.Name); } DynamicMethod dynamicMethod = new DynamicMethod("FastReflection<" + typeof(T).FullName + ".Get_" + fieldInfo.Name + ">", typeof(F), new Type[1] { typeof(T) }, fieldInfo.DeclaringType.Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!fieldInfo.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, fieldInfo.DeclaringType); } iLGenerator.Emit(fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, fieldInfo); if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType) { iLGenerator.Emit(OpCodes.Box, fieldInfo.FieldType); } iLGenerator.Emit(OpCodes.Ret); return (Func<T, F>)dynamicMethod.CreateDelegate(typeof(Func<T, F>)); } public static Action<T, F> CreateFastFieldSetter<T, F>(FieldInfo fieldInfo) { if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType)) { throw new ArgumentException("FieldInfo type does not match argument type."); } if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T)))) { throw new MissingFieldException(typeof(T).Name, fieldInfo.Name); } DynamicMethod dynamicMethod = new DynamicMethod("FastReflection<" + typeof(T).FullName + ".Set_" + fieldInfo.Name + ">", null, new Type[2] { typeof(T), typeof(F) }, fieldInfo.DeclaringType.Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!fieldInfo.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, fieldInfo.DeclaringType); } iLGenerator.Emit(OpCodes.Ldarg_1); if ((object)fieldInfo.FieldType != typeof(F)) { if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType) { if (fieldInfo.FieldType.IsValueType) { iLGenerator.Emit(OpCodes.Unbox, fieldInfo.FieldType); } else { iLGenerator.Emit(OpCodes.Box, fieldInfo.FieldType); } } else { iLGenerator.Emit(OpCodes.Castclass, fieldInfo.FieldType); } } iLGenerator.Emit(fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo); iLGenerator.Emit(OpCodes.Ret); return (Action<T, F>)dynamicMethod.CreateDelegate(typeof(Action<T, F>)); } } public static class TimeHelper { public static float realtimeSinceStartup => Time.realtimeSinceStartup; } public class UnityObjectReferenceComparer : IEqualityComparer<object> { public static readonly UnityObjectReferenceComparer Default = new UnityObjectReferenceComparer(); public new bool Equals(object x, object y) { return x == y; } public int GetHashCode(object obj) { return obj.GetHashCode(); } } public class WeakReference<T> : WeakReference where T : class { public new T Target => (T)base.Target; public static WeakReference<T> Create(T target) { if (target == null) { return WeakNullReference<T>.Singleton; } return new WeakReference<T>(target); } protected WeakReference(T target) : base(target, trackResurrection: false) { } } internal class WeakNullReference<T> : WeakReference<T> where T : class { public static readonly WeakNullReference<T> Singleton = new WeakNullReference<T>(); public override bool IsAlive => true; private WeakNullReference() : base((T)null) { } } internal sealed class WeakKeyReference<T> : WeakReference<T> where T : class { public readonly int HashCode; public WeakKeyReference(T key, WeakKeyComparer<T> comparer) : base(key) { HashCode = comparer.GetHashCode(key); } } internal sealed class WeakKeyComparer<T> : IEqualityComparer<object> where T : class { private IEqualityComparer<T> comparer; internal WeakKeyComparer(IEqualityComparer<T> comparer) { if (comparer == null) { comparer = EqualityComparer<T>.Default; } this.comparer = comparer; } public int GetHashCode(object obj) { if (obj is WeakKeyReference<T> weakKeyReference) { return weakKeyReference.HashCode; } return comparer.GetHashCode((T)obj); } public new bool Equals(object x, object y) { bool isDead; T target = GetTarget(x, out isDead); bool isDead2; T target2 = GetTarget(y, out isDead2); if (isDead) { if (!isDead2) { return false; } return x == y; } if (isDead2) { return false; } return comparer.Equals(target, target2); } private static T GetTarget(object obj, out bool isDead) { T result; if (obj is WeakKeyReference<T> weakKeyReference) { result = weakKeyReference.Target; isDead = !weakKeyReference.IsAlive; } else { result = (T)obj; isDead = false; } return result; } } public sealed class WeakDictionary<TKey, TValue> : BaseDictionary<TKey, TValue> where TKey : class { private Dictionary<object, TValue> dictionary; private WeakKeyComparer<TKey> comparer; public override int Count => dictionary.Count; public WeakDictionary() : this(0, (IEqualityComparer<TKey>)null) { } public WeakDictionary(int capacity) : this(capacity, (IEqualityComparer<TKey>)null) { } public WeakDictionary(IEqualityComparer<TKey> comparer) : this(0, comparer) { } public WeakDictionary(int capacity, IEqualityComparer<TKey> comparer) { this.comparer = new WeakKeyComparer<TKey>(comparer); dictionary = new Dictionary<object, TValue>(capacity, this.comparer); } public override void Add(TKey key, TValue value) { if (key == null) { throw new ArgumentNullException("key"); } WeakReference<TKey> key2 = new WeakKeyReference<TKey>(key, comparer); dictionary.Add(key2, value); } public override bool ContainsKey(TKey key) { return dictionary.ContainsKey(key); } public override bool Remove(TKey key) { return dictionary.Remove(key); } public override bool TryGetValue(TKey key, out TValue value) { if (dictionary.TryGetValue(key, out value)) { return true; } value = default(TValue); return false; } protected override void SetValue(TKey key, TValue value) { WeakReference<TKey> key2 = new WeakKeyReference<TKey>(key, comparer); dictionary[key2] = value; } public override void Clear() { dictionary.Clear(); } public override IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { foreach (KeyValuePair<object, TValue> item in dictionary) { WeakReference<TKey> obj = (WeakReference<TKey>)item.Key; TValue value = item.Value; TKey target = obj.Target; if (obj.IsAlive) { yield return new KeyValuePair<TKey, TValue>(target, value); } } } public void RemoveCollectedEntries() { List<object> list = null; foreach (KeyValuePair<object, TValue> item in dictionary) { WeakReference<TKey> weakReference = (WeakReference<TKey>)item.Key; if (!weakReference.IsAlive) { if (list == null) { list = new List<object>(); } list.Add(weakReference); } } if (list == null) { return; } foreach (object item2 in list) { dictionary.Remove(item2); } } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy("System.Collections.Generic.Mscorlib_DictionaryDebugView`2,mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089")] public abstract class BaseDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable { private abstract class Collection<T> : ICollection<T>, IEnumerable<T>, IEnumerable { protected readonly IDictionary<TKey, TValue> dictionary; public int Count => dictionary.Count; public bool IsReadOnly => true; protected Collection(IDictionary<TKey, TValue> dictionary) { this.dictionary = dictionary; } public void CopyTo(T[] array, int arrayIndex) { BaseDictionary<TKey, TValue>.Copy((ICollection<T>)this, array, arrayIndex); } public virtual bool Contains(T item) { using (IEnumerator<T> enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { T current = enumerator.Current; if (EqualityComparer<T>.Default.Equals(current, item)) { return true; } } } return false; } public IEnumerator<T> GetEnumerator() { foreach (KeyValuePair<TKey, TValue> item in dictionary) { yield return GetItem(item); } } protected abstract T GetItem(KeyValuePair<TKey, TValue> pair); public bool Remove(T item) { throw new NotSupportedException("Collection is read-only."); } public void Add(T item) { throw new NotSupportedException("Collection is read-only."); } public void Clear() { throw new NotSupportedException("Collection is read-only."); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy("System.Collections.Generic.Mscorlib_DictionaryKeyCollectionDebugView`2,mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089")] private class KeyCollection : Collection<TKey> { public KeyCollection(IDictionary<TKey, TValue> dictionary) : base(dictionary) { } protected override TKey GetItem(KeyValuePair<TKey, TValue> pair) { return pair.Key; } public override bool Contains(TKey item) { return dictionary.ContainsKey(item); } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy("System.Collections.Generic.Mscorlib_DictionaryValueCollectionDebugView`2,mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089")] private class ValueCollection : Collection<TValue> { public ValueCollection(IDictionary<TKey, TValue> dictionary) : base(dictionary) { } protected override TValue GetItem(KeyValuePair<TKey, TValue> pair) { return pair.Value; } } private const string PREFIX = "System.Collections.Generic.Mscorlib_"; private const string SUFFIX = ",mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"; private KeyCollection keys; private ValueCollection values; public abstract int Count { get; } public bool IsReadOnly => false; public ICollection<TKey> Keys { get { if (keys == null) { keys = new KeyCollection(this); } return keys; } } public ICollection<TValue> Values { get { if (values == null) { values = new ValueCollection(this); } return values; } } public TValue this[TKey key] { get { if (!TryGetValue(key, out var value)) { throw new KeyNotFoundException(); } return value; } set { SetValue(key, value); } } public abstract void Clear(); public abstract void Add(TKey key, TValue value); public abstract bool ContainsKey(TKey key); public abstract bool Remove(TKey key); public abstract bool TryGetValue(TKey key, out TValue value); public abstract IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator(); protected abstract void SetValue(TKey key, TValue value); public void Add(KeyValuePair<TKey, TValue> item) { Add(item.Key, item.Value); } public bool Contains(KeyValuePair<TKey, TValue> item) { if (!TryGetValue(item.Key, out var value)) { return false; } return EqualityComparer<TValue>.Default.Equals(value, item.Value); } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { Copy(this, array, arrayIndex); } public bool Remove(KeyValuePair<TKey, TValue> item) { if (!Contains(item)) { return false; } return Remove(item.Key); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static void Copy<T>(ICollection<T> source, T[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0 || arrayIndex > array.Length) { throw new ArgumentOutOfRangeException("arrayIndex"); } if (array.Length - arrayIndex < source.Count) { throw new ArgumentException("Destination array is not large enough. Check array.Length and arrayIndex."); } foreach (T item in source) { array[arrayIndex++] = item; } } } } namespace XUnity.Common.MonoMod { public static class DetourExtensions { public static T GenerateTrampolineEx<T>(this object detour) { return (T)(from x in detour.GetType().GetMethods() where x.Name == "GenerateTrampoline" && x.IsGenericMethod select x).FirstOrDefault().MakeGenericMethod(typeof(T)).Invoke(detour, null); } } } namespace XUnity.Common.Logging { internal class ConsoleLogger : XuaLogger { public ConsoleLogger(string source) : base(source) { } protected override void Log(LogLevel level, string message) { Console.WriteLine(GetDefaultPrefix(level) + " " + message); } } public enum LogLevel { Debug, Info, Warn, Error } internal class ModLoaderSpecificLogger : XuaLogger { public static class BepInExLogLevel { public const int None = 0; public const int Fatal = 1; public const int Error = 2; public const int Warning = 4; public const int Message = 8; public const int Info = 16; public const int Debug = 32; public const int All = 63; } private static Action<LogLevel, string> _logMethod; public ModLoaderSpecificLogger(string source) : base(source) { if (_logMethod != null) { return; } BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public; BindingFlags bindingAttr2 = BindingFlags.Instance | BindingFlags.Public; Type type = Type.GetType("BepInEx.Logging.LogLevel, BepInEx", throwOnError: false) ?? Type.GetType("BepInEx.Logging.LogLevel, BepInEx.Core", throwOnError: false); if ((object)type != null) { if ((object)(Type.GetType("BepInEx.Logging.ManualLogSource, BepInEx", throwOnError: false) ?? Type.GetType("BepInEx.Logging.ManualLogSource, BepInEx.Core", throwOnError: false)) != null) { MethodInfo method = (Type.GetType("BepInEx.Logging.Logger, BepInEx", throwOnError: false) ?? Type.GetType("BepInEx.Logging.Logger, BepInEx.Core", throwOnError: false)).GetMethod("CreateLogSource", bindingAttr, null, new Type[1] { typeof(string) }, null); object logInstance2 = method.Invoke(null, new object[1] { base.Source }); MethodInfo method2 = logInstance2.GetType().GetMethod("Log", bindingAttr2, null, new Type[2] { type, typeof(object) }, null); FastReflectionDelegate log2 = method2.CreateFastDelegate(); _logMethod = delegate(LogLevel level, string msg) { int num2 = Convert(level); log2(logInstance2, num2, msg); }; } else { Type type2 = Type.GetType("BepInEx.Logger, BepInEx", throwOnError: false); object logInstance = type2.GetProperty("CurrentLogger", bindingAttr).GetValue(null, null); MethodInfo method3 = logInstance.GetType().GetMethod("Log", bindingAttr2, null, new Type[2] { type, typeof(object) }, null); FastReflectionDelegate log = method3.CreateFastDelegate(); _logMethod = delegate(LogLevel level, string msg) { int num = Convert(level); log(logInstance, num, msg); }; } } else { Type type3 = Type.GetType("MelonLoader.MelonLogger, MelonLoader.ModHandler", throwOnError: false); if ((object)type3 != null) { MethodInfo method4 = type3.GetMethod("Log", bindingAttr, null, new Type[2] { typeof(ConsoleColor), typeof(string) }, null); MethodInfo method5 = type3.GetMethod("Log", bindingAttr, null, new Type[1] { typeof(string) }, null); MethodInfo method6 = type3.GetMethod("LogWarning", bindingAttr, null, new Type[1] { typeof(string) }, null); MethodInfo method7 = type3.GetMethod("LogError", bindingAttr, null, new Type[1] { typeof(string) }, null); FastReflectionDelegate logDebug = method4.CreateFastDelegate(); FastReflectionDelegate logInfo = method5.CreateFastDelegate(); FastReflectionDelegate logWarning = method6.CreateFastDelegate(); FastReflectionDelegate logError = method7.CreateFastDelegate(); _logMethod = delegate(LogLevel level, string msg) { switch (level) { case LogLevel.Debug: logDebug(null, ConsoleColor.Gray, msg); break; case LogLevel.Info: logInfo(null, msg); break; case LogLevel.Warn: logWarning(null, msg); break; case LogLevel.Error: logError(null, msg); break; default: throw new ArgumentException("level"); } }; } } if (_logMethod != null) { return; } throw new Exception("Did not recognize any mod loader!"); } protected override void Log(LogLevel level, string message) { _logMethod(level, message); } public static int Convert(LogLevel level) { return level switch { LogLevel.Debug => 32, LogLevel.Info => 16, LogLevel.Warn => 4, LogLevel.Error => 2, _ => 0, }; } } public abstract class XuaLogger { private static XuaLogger _default; private static XuaLogger _common; private static XuaLogger _resourceRedirector; public static XuaLogger AutoTranslator { get { if (_default == null) { _default = CreateLogger("XUnity.AutoTranslator"); } return _default; } set { _default = value ?? throw new ArgumentNullException("value"); } } public static XuaLogger Common { get { if (_common == null) { _common = CreateLogger("XUnity.Common"); } return _common; } set { _common = value ?? throw new ArgumentNullException("value"); } } public static XuaLogger ResourceRedirector { get { if (_resourceRedirector == null) { _resourceRedirector = CreateLogger("XUnity.ResourceRedirector"); } return _resourceRedirector; } set { _resourceRedirector = value ?? throw new ArgumentNullException("value"); } } public string Source { get; set; } internal static XuaLogger CreateLogger(string source) { try { return new ModLoaderSpecificLogger(source); } catch (Exception) { return new ConsoleLogger(source); } } public XuaLogger(string source) { Source = source; } public void Error(Exception e, string message) { Log(LogLevel.Error, message + Environment.NewLine + e); } public void Error(string message) { Log(LogLevel.Error, message); } public void Warn(Exception e, string message) { Log(LogLevel.Warn, message + Environment.NewLine + e); } public void Warn(string message) { Log(LogLevel.Warn, message); } public void Info(Exception e, string message) { Log(LogLevel.Info, message + Environment.NewLine + e); } public void Info(string message) { Log(LogLevel.Info, message); } public void Debug(Exception e, string message) { Log(LogLevel.Debug, message + Environment.NewLine + e); } public void Debug(string message) { Log(LogLevel.Debug, message); } protected abstract void Log(LogLevel level, string message); protected string GetDefaultPrefix(LogLevel level) { return level switch { LogLevel.Debug => "[DEBUG][" + Source + "]: ", LogLevel.Info => "[INFO][" + Source + "]: ", LogLevel.Warn => "[WARN][" + Source + "]: ", LogLevel.Error => "[ERROR][" + Source + "]: ", _ => "[UNKNOW][" + Source + "]: ", }; } } } namespace XUnity.Common.Harmony { public static class AccessToolsShim { private static readonly BindingFlags All; private static readonly Func<Type, string, Type[], Type[], MethodInfo> AccessTools_Method; private static readonly Func<Type, string, PropertyInfo> AccessTools_Property; static AccessToolsShim() { All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo method = ClrTypes.AccessTools.GetMethod("Method", All, null, new Type[4] { typeof(Type), typeof(string), typeof(Type[]), typeof(Type[]) }, null); MethodInfo? method2 = ClrTypes.AccessTools.GetMethod("Property", All, null, new Type[2] { typeof(Type), typeof(string) }, null); AccessTools_Method = (Func<Type, string, Type[], Type[], MethodInfo>)ExpressionHelper.CreateTypedFastInvoke(method); AccessTools_Property = (Func<Type, string, PropertyInfo>)ExpressionHelper.CreateTypedFastInvoke(method2); } public static MethodInfo Method(Type type, string name, params Type[] parameters) { return AccessTools_Method(type, name, parameters, null); } public static PropertyInfo Property(Type type, string name) { return AccessTools_Property(type, name); } } } namespace XUnity.Common.Extensions { public static class ExceptionExtensions { public static TException FirstInnerExceptionOfType<TException>(this Exception e) where TException : Exception { for (Exception ex = e; ex != null; ex = ex.InnerException) { if (ex is TException) { return (TException)ex; } } return null; } } public static class ObjectExtensions { public static Type GetUnityType(this object obj) { return obj.GetType(); } public static bool TryCastTo<TObject>(this object obj, out TObject castedObject) { if (obj is TObject val) { castedObject = val; return true; } castedObject = default(TObject); return false; } } public static class StreamExtensions { public static byte[] ReadFully(this Stream stream, int initialLength) { if (initialLength < 1) { initialLength = 32768; } byte[] array = new byte[initialLength]; int num = 0; int num2; while ((num2 = stream.Read(array, num, array.Length - num)) > 0) { num += num2; if (num == array.Length) { int num3 = stream.ReadByte(); if (num3 == -1) { return array; } byte[] array2 = new byte[array.Length * 2]; Array.Copy(array, array2, array.Length); array2[num] = (byte)num3; array = array2; num++; } } byte[] array3 = new byte[num]; Array.Copy(array, array3, num); return array3; } } public static class StringExtensions { private static readonly HashSet<char> InvalidFileNameChars = new HashSet<char>(Path.GetInvalidFileNameChars()); public static string UseCorrectDirectorySeparators(this string path) { if (Path.DirectorySeparatorChar == '\\') { return path.Replace('/', Path.DirectorySeparatorChar); } if (Path.DirectorySeparatorChar == '/') { return path.Replace('\\', Path.DirectorySeparatorChar); } return path; } public static bool IsNullOrWhiteSpace(this string value) { if (value == null) { return true; } for (int i = 0; i < value.Length; i++) { if (!char.IsWhiteSpace(value[i])) { return false; } } return true; } public static string MakeRelativePath(this string fullOrRelativePath, string basePath) { StringBuilder stringBuilder = new StringBuilder(); int i = 0; bool flag = false; string[] array = basePath.Split(':', '\\', '/'); List<string> list = fullOrRelativePath.Split(':', '\\', '/').ToList(); if (array.Length == 0 || list.Count <= 0 || array[0] != list[0]) { flag = true; } bool flag2 = false; for (int j = 0; j < list.Count; j++) { if (list[j] == "..") { if (flag2) { int num = j - 1; if (num >= 0) { list.RemoveAt(j); list.RemoveAt(num); j -= 2; } } } else { flag2 = true; } } if (!flag) { for (i = 1; i < array.Length && !(array[i] != list[i]); i++) { } for (int k = 0; k < array.Length - i; k++) { char directorySeparatorChar = Path.DirectorySeparatorChar; stringBuilder.Append(".." + directorySeparatorChar); } } for (int l = i; l < list.Count - 1; l++) { string value = list[l]; stringBuilder.Append(value).Append(Path.DirectorySeparatorChar); } string value2 = list[^1]; stringBuilder.Append(value2); return stringBuilder.ToString(); } public static string SanitizeForFileSystem(this string path) { StringBuilder stringBuilder = new StringBuilder(path.Length); foreach (char c in path) { if (!InvalidFileNameChars.Contains(c)) { stringBuilder.Append(c); } } return stringBuilder.ToString(); } public static string SplitToLines(this string text, int maxStringLength, params char[] splitOnCharacters) { StringBuilder stringBuilder = new StringBuilder(); int num; for (int i = 0; text.Length > i; i += num) { if (i != 0) { stringBuilder.Append('\n'); } num = ((i + maxStringLength <= text.Length) ? text.Substring(i, maxStringLength).LastIndexOfAny(splitOnCharacters) : (text.Length - i)); num = ((num == -1) ? maxStringLength : num); stringBuilder.Append(text.Substring(i, num).Trim()); } return stringBuilder.ToString(); } public static bool StartsWithStrict(this string str, string prefix) { int num = Math.Min(str.Length, prefix.Length); if (num < prefix.Length) { return false; } for (int i = 0; i < num; i++) { if (str[i] != prefix[i]) { return false; } } return true; } public static string GetBetween(this string strSource, string strStart, string strEnd) { int num = strSource.IndexOf(strStart); if (num != -1) { num += strStart.Length; int num2 = strSource.IndexOf(strEnd, num); if (num2 > num) { return strSource.Substring(num, num2 - num); } } return string.Empty; } public static bool RemindsOf(this string that, string other) { if (!that.StartsWith(other) && !other.StartsWith(that) && !that.EndsWith(other)) { return other.EndsWith(that); } return true; } } } namespace XUnity.Common.Constants { public static class ClrTypes { public static readonly Type AccessTools = FindTypeStrict("Harmony.AccessTools, 0Harmony") ?? FindTypeStrict("HarmonyLib.AccessTools, 0Harmony") ?? FindTypeStrict("Harmony.AccessTools, MelonLoader.ModHandler") ?? FindTypeStrict("HarmonyLib.AccessTools, MelonLoader.ModHandler"); public static readonly Type HarmonyMethod = FindTypeStrict("Harmony.HarmonyMethod, 0Harmony") ?? FindTypeStrict("HarmonyLib.HarmonyMethod, 0Harmony") ?? FindTypeStrict("Harmony.HarmonyMethod, MelonLoader.ModHandler") ?? FindTypeStrict("HarmonyLib.HarmonyMethod, MelonLoader.ModHandler"); public static readonly Type HarmonyInstance = FindTypeStrict("Harmony.HarmonyInstance, 0Harmony") ?? FindTypeStrict("Harmony.HarmonyInstance, MelonLoader.ModHandler"); public static readonly Type Harmony = FindTypeStrict("HarmonyLib.Harmony, 0Harmony") ?? FindTypeStrict("HarmonyLib.Harmony, MelonLoader.ModHandler"); public static readonly Type Hook = FindTypeStrict("MonoMod.RuntimeDetour.Hook, MonoMod.RuntimeDetour"); public static readonly Type Detour = FindTypeStrict("MonoMod.RuntimeDetour.Detour, MonoMod.RuntimeDetour"); public static readonly Type NativeDetour = FindTypeStrict("MonoMod.RuntimeDetour.NativeDetour, MonoMod.RuntimeDetour"); public static readonly Type DynamicMethodDefinition = FindTypeStrict("MonoMod.Utils.DynamicMethodDefinition, MonoMod.Utils"); public static readonly Type Imports = FindTypeStrict("MelonLoader.Imports, MelonLoader.ModHandler"); public static readonly Type MethodBase = FindType("System.Reflection.MethodBase"); public static readonly Type Task = FindType("System.Threading.Tasks.Task"); private static Type FindType(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(name, throwOnError: false); if ((object)type != null) { return type; } } catch { } } return null; } private static Type FindTypeStrict(string name) { return Type.GetType(name, throwOnError: false); } } public class TypeContainer { public Type ClrType { get; } public Type UnityType { get; } public TypeContainer(Type type) { UnityType = type; ClrType = type; } public bool IsAssignableFrom(Type unityType) { if ((object)UnityType != null) { return UnityType.IsAssignableFrom(unityType); } return false; } } public static class UnityFeatures { private static readonly BindingFlags All; public static bool SupportsMouseScrollDelta { get; } public static bool SupportsClipboard { get; } public static bool SupportsCustomYieldInstruction { get; } public static bool SupportsSceneManager { get; } public static bool SupportsWaitForSecondsRealtime { get; set; } static UnityFeatures() { All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; SupportsMouseScrollDelta = false; SupportsClipboard = false; SupportsCustomYieldInstruction = false; SupportsSceneManager = false; SupportsWaitForSecondsRealtime = false; try { SupportsClipboard = (object)UnityTypes.TextEditor?.ClrType.GetProperty("text")?.GetSetMethod() != null; } catch (Exception) { } try { SupportsCustomYieldInstruction = UnityTypes.CustomYieldInstruction != null; } catch (Exception) { } try { SupportsSceneManager = UnityTypes.Scene != null && UnityTypes.SceneManager != null && (object)UnityTypes.SceneManager.ClrType.GetMethod("add_sceneLoaded", All) != null; } catch (Exception) { } try { SupportsMouseScrollDelta = (object)UnityTypes.Input?.ClrType.GetProperty("mouseScrollDelta") != null; } catch (Exception) { } try { SupportsWaitForSecondsRealtime = UnityTypes.WaitForSecondsRealtime != null; } catch (Exception) { } } } public static class UnityTypes { public static class TMP_Settings_Properties { public static CachedProperty Version = TMP_Settings?.ClrType.CachedProperty("version"); public static CachedProperty FallbackFontAssets = TMP_Settings?.ClrType.CachedProperty("fallbackFontAssets"); } public static class TMP_FontAsset_Properties { public static CachedProperty Version = TMP_FontAsset?.ClrType.CachedProperty("version"); } public static class AdvScenarioData_Properties { public static CachedProperty ScenarioLabels = AdvScenarioData?.ClrType.CachedProperty("ScenarioLabels"); } public static class UguiNovelText_Properties { public static CachedProperty TextGenerator = UguiNovelText?.ClrType.CachedProperty("TextGenerator"); } public static class UguiNovelText_Methods { public static CachedMethod SetAllDirty = UguiNovelText?.ClrType.CachedMethod("SetAllDirty"); } public static class UguiNovelTextGenerator_Methods { public static CachedMethod Refresh = UguiNovelTextGenerator?.ClrType.CachedMethod("Refresh"); } public static class AdvUguiMessageWindow_Properties { public static CachedProperty Text = AdvUguiMessageWindow?.ClrType.CachedProperty("Text"); public static CachedProperty Engine = AdvUguiMessageWindow?.ClrType.CachedProperty("Engine"); } public static class AdvUiMessageWindow_Fields { public static CachedField text = AdvUiMessageWindow?.ClrType.CachedField("text"); public static CachedField nameText = AdvUiMessageWindow?.ClrType.CachedField("nameText"); } public static class AdvUguiMessageWindow_Fields { public static FieldInfo text = AdvUguiMessageWindow?.ClrType.GetField("text", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); public static FieldInfo nameText = AdvUguiMessageWindow?.ClrType.GetField("nameText", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); public static FieldInfo engine = AdvUguiMessageWindow?.ClrType.GetField("engine", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } public static class AdvEngine_Properties { public static CachedProperty Page = AdvEngine?.ClrType.CachedProperty("Page"); } public static class AdvPage_Methods { public static CachedMethod RemakeTextData = AdvPage?.ClrType.CachedMethod("RemakeTextData"); public static CachedMethod RemakeText = AdvPage?.ClrType.CachedMethod("RemakeText"); public static CachedMethod ChangeMessageWindowText = AdvPage?.ClrType.CachedMethod("ChangeMessageWindowText", typeof(string), typeof(string), typeof(string), typeof(string)); } public static class UILabel_Properties { public static CachedProperty MultiLine = UILabel?.ClrType.CachedProperty("multiLine"); public static CachedProperty OverflowMethod = UILabel?.ClrType.CachedProperty("overflowMethod"); public static CachedProperty SpacingX = UILabel?.ClrType.CachedProperty("spacingX"); public static CachedProperty UseFloatSpacing = UILabel?.ClrType.CachedProperty("useFloatSpacing"); } public static class Text_Properties { public static CachedProperty Font = Text?.ClrType.CachedProperty("font"); public static CachedProperty FontSize = Text?.ClrType.CachedProperty("fontSize"); public static CachedProperty HorizontalOverflow = Text?.ClrType.CachedProperty("horizontalOverflow"); public static CachedProperty VerticalOverflow = Text?.ClrType.CachedProperty("verticalOverflow"); public static CachedProperty LineSpacing = Text?.ClrType.CachedProperty("lineSpacing"); public static CachedProperty ResizeTextForBestFit = Text?.ClrType.CachedProperty("resizeTextForBestFit"); public static CachedProperty ResizeTextMinSize = Text?.ClrType.CachedProperty("resizeTextMinSize"); public static CachedProperty ResizeTextMaxSize = Text?.ClrType.CachedProperty("resizeTextMaxSize"); } public static class InputField_Properties { public static CachedProperty Placeholder = InputField?.ClrType.CachedProperty("placeholder"); } public static class TMP_InputField_Properties { public static CachedProperty Placeholder = TMP_InputField?.ClrType.CachedProperty("placeholder"); } public static class Font_Properties { public static CachedProperty FontSize = Font?.ClrType.CachedProperty("fontSize"); } public static class AssetBundle_Methods { public static CachedMethod LoadAll = AssetBundle?.ClrType.CachedMethod("LoadAll", typeof(Type)); public static CachedMethod LoadAllAssets = AssetBundle?.ClrType.CachedMethod("LoadAllAssets", typeof(Type)); public static CachedMethod LoadFromFile = AssetBundle?.ClrType.CachedMethod("LoadFromFile", typeof(string)); public static CachedMethod CreateFromFile = AssetBundle?.ClrType.CachedMethod("CreateFromFile", typeof(string)); } public static class TextExpansion_Methods { public static CachedMethod SetMessageType = TextExpansion?.ClrType.CachedMethod("SetMessageType"); public static CachedMethod SkipTypeWriter = TextExpansion?.ClrType.CachedMethod("SkipTypeWriter"); } public static class GameObject_Methods { } public static class TextMesh_Methods { } public static class Text_Methods { } public static class InputField_Methods { } public static class TMP_Text_Methods { } public static class TMP_InputField_Methods { } public static class TextMeshPro_Methods { } public static class TextMeshProUGUI_Methods { } public static class UILabel_Methods { } public static class UIRect_Methods { } public static class SceneManager_Methods { public static readonly Action<UnityAction<Scene, LoadSceneMode>> add_sceneLoaded = (Action<UnityAction<Scene, LoadSceneMode>>)ExpressionHelper.CreateTypedFastInvokeUnchecked(typeof(SceneManager).GetMethod("add_sceneLoaded", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(UnityAction<Scene, LoadSceneMode>) }, null)); } public static class Texture2D_Methods { public static readonly Func<Texture2D, byte[], bool> LoadImage = (Func<Texture2D, byte[], bool>)ExpressionHelper.CreateTypedFastInvokeUnchecked(typeof(Texture2D).GetMethod("LoadImage", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(byte[]) }, null)); public static readonly Func<Texture2D, byte[]> EncodeToPNG = (Func<Texture2D, byte[]>)ExpressionHelper.CreateTypedFastInvokeUnchecked(typeof(Texture2D).GetMethod("EncodeToPNG", BindingFlags.Instance | BindingFlags.Public, null, new Type[0], null)); } public static class ImageConversion_Methods { public static readonly Func<Texture2D, byte[], bool, bool> LoadImage = (Func<Texture2D, byte[], bool, bool>)ExpressionHelper.CreateTypedFastInvokeUnchecked(ImageConversion?.ClrType.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }, null)); public static readonly Func<Texture2D, byte[]> EncodeToPNG = (Func<Texture2D, byte[]>)ExpressionHelper.CreateTypedFastInvokeUnchecked(ImageConversion?.ClrType.GetMethod("EncodeToPNG", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Texture2D) }, null)); } public static readonly TypeContainer UILabel = FindType("UILabel"); public static readonly TypeContainer UIWidget = FindType("UIWidget"); public static readonly TypeContainer UIAtlas = FindType("UIAtlas"); public static readonly TypeContainer UISprite = FindType("UISprite"); public static readonly TypeContainer UITexture = FindType("UITexture"); public static readonly TypeContainer UI2DSprite = FindType("UI2DSprite"); public static readonly TypeContainer UIFont = FindType("UIFont"); public static readonly TypeContainer UIPanel = FindType("UIPanel"); public static readonly TypeContainer UIRect = FindType("UIRect"); public static readonly TypeContainer UIInput = FindType("UIInput"); public static readonly TypeContainer TextField = FindType("FairyGUI.TextField"); public static readonly TypeContainer TMP_InputField = FindType("TMPro.TMP_InputField"); public static readonly TypeContainer TMP_Text = FindType("TMPro.TMP_Text"); public static readonly TypeContainer TextMeshProUGUI = FindType("TMPro.TextMeshProUGUI"); public static readonly TypeContainer TextMeshPro = FindType("TMPro.TextMeshPro"); public static readonly TypeContainer TMP_FontAsset = FindType("TMPro.TMP_FontAsset"); public static readonly TypeContainer TMP_Settings = FindType("TMPro.TMP_Settings"); public static readonly TypeContainer GameObject = FindType("UnityEngine.GameObject"); public static readonly TypeContainer Transform = FindType("UnityEngine.Transform"); public static readonly TypeContainer TextMesh = FindType("UnityEngine.TextMesh"); public static readonly TypeContainer Text = FindType("UnityEngine.UI.Text"); public static readonly TypeContainer Image = FindType("UnityEngine.UI.Image"); public static readonly TypeContainer RawImage = FindType("UnityEngine.UI.RawImage"); public static readonly TypeContainer MaskableGraphic = FindType("UnityEngine.UI.MaskableGraphic"); public static readonly TypeContainer Graphic = FindType("UnityEngine.UI.Graphic"); public static readonly TypeContainer GUIContent = FindType("UnityEngine.GUIContent"); public static readonly TypeContainer WWW = FindType("UnityEngine.WWW"); public static readonly TypeContainer InputField = FindType("UnityEngine.UI.InputField"); public static readonly TypeContainer GUI = FindType("UnityEngine.GUI"); public static readonly TypeContainer GUI_ToolbarButtonSize = FindType("UnityEngine.GUI+ToolbarButtonSize"); public static readonly TypeContainer GUIStyle = FindType("UnityEngine.GUIStyle"); public static readonly TypeContainer ImageConversion = FindType("UnityEngine.ImageConversion"); public static readonly TypeContainer Texture2D = FindType("UnityEngine.Texture2D"); public static readonly TypeContainer Texture = FindType("UnityEngine.Texture"); public static readonly TypeContainer SpriteRenderer = FindType("UnityEngine.SpriteRenderer"); public static readonly TypeContainer Sprite = FindType("UnityEngine.Sprite"); public static readonly TypeContainer Object = FindType("UnityEngine.Object"); public static readonly TypeContainer TextEditor = FindType("UnityEngine.TextEditor"); public static readonly TypeContainer CustomYieldInstruction = FindType("UnityEngine.CustomYieldInstruction"); public static readonly TypeContainer SceneManager = FindType("UnityEngine.SceneManagement.SceneManager"); public static readonly TypeContainer Scene = FindType("UnityEngine.SceneManagement.Scene"); public static readonly TypeContainer UnityEventBase = FindType("UnityEngine.Events.UnityEventBase"); public static readonly TypeContainer BaseInvokableCall = FindType("UnityEngine.Events.BaseInvokableCall"); public static readonly TypeContainer Font = FindType("UnityEngine.Font"); public static readonly TypeContainer WaitForSecondsRealtime = FindType("UnityEngine.WaitForSecondsRealtime"); public static readonly TypeContainer Input = FindType("UnityEngine.Input"); public static readonly TypeContainer AssetBundleCreateRequest = FindType("UnityEngine.AssetBundleCreateRequest"); public static readonly TypeContainer AssetBundle = FindType("UnityEngine.AssetBundle"); public static readonly TypeContainer AssetBundleRequest = FindType("UnityEngine.AssetBundleRequest"); public static readonly TypeContainer Resources = FindType("UnityEngine.Resources"); public static readonly TypeContainer AsyncOperation = FindType("UnityEngine.AsyncOperation"); public static readonly TypeContainer TextAsset = FindType("UnityEngine.TextAsset"); public static readonly Type HorizontalWrapMode = FindClrType("UnityEngine.HorizontalWrapMode"); public static readonly Type TextOverflowModes = FindClrType("TMPro.TextOverflowModes"); public static readonly Type TextAlignmentOptions = FindClrType("TMPro.TextAlignmentOptions"); public static readonly Type VerticalWrapMode = FindClrType("UnityEngine.VerticalWrapMode"); public static readonly TypeContainer TextExpansion = FindType("UnityEngine.UI.TextExpansion"); public static readonly TypeContainer Typewriter = FindType("Typewriter"); public static readonly TypeContainer UguiNovelText = FindType("Utage.UguiNovelText"); public static readonly TypeContainer UguiNovelTextGenerator = FindType("Utage.UguiNovelTextGenerator"); public static readonly TypeContainer AdvEngine = FindType("Utage.AdvEngine"); public static readonly TypeContainer AdvPage = FindType("Utage.AdvPage"); public static readonly TypeContainer TextData = FindType("Utage.TextData"); public static readonly TypeContainer AdvUguiMessageWindow = FindType("Utage.AdvUguiMessageWindow") ?? FindType("AdvUguiMessageWindow"); public static readonly TypeContainer AdvUiMessageWindow = FindType("AdvUiMessageWindow"); public static readonly TypeContainer AdvDataManager = FindType("Utage.AdvDataManager"); public static readonly TypeContainer AdvScenarioData = FindType("Utage.AdvScenarioData"); public static readonly TypeContainer AdvScenarioLabelData = FindType("Utage.AdvScenarioLabelData"); public static readonly TypeContainer DicingTextures = FindType("Utage.DicingTextures"); public static readonly TypeContainer DicingImage = FindType("Utage.DicingImage"); public static readonly TypeContainer TextArea2D = FindType("Utage.TextArea2D"); public static readonly TypeContainer CubismRenderer = FindType("Live2D.Cubism.Rendering.CubismRenderer"); public static readonly TypeContainer TextWindow = FindType("Assets.System.Text.TextWindow"); private static Type FindClrType(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(name, throwOnError: false); if ((object)type != null) { return type; } } catch { } } return null; } private static TypeContainer FindType(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(name, throwOnError: false); if ((object)type != null) { return new TypeContainer(type); } } catch { } } return null; } } }
BepInEx/plugins/XUnity.AutoTranslator/ExIni.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using Microsoft.Win32; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyInformationalVersion("GIT master [cf85ca6f3fc361cf48bf56107e4cec9102b7f5eb] ")] [assembly: AssemblyTitle("ExIni")] [assembly: Guid("b8adf1ac-aade-485a-8997-14c4b42e0a8b")] [assembly: AssemblyDescription("Extended INI File Handler")] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyFileVersion("1.0.2.1")] [assembly: AssemblyCompany("Usagirei")] [assembly: AssemblyProduct("ExIni")] [assembly: ComVisible(false)] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCopyright("Copyright © Usagirei 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyVersion("1.0.2.1")] namespace ExIni; public class IniComment { public List<string> Comments { get; set; } public IniComment() { Comments = new List<string>(); } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < Comments.Count; i++) { string text = Comments[i]; string value = ((i < Comments.Count - 1) ? (";" + text + Environment.NewLine) : (";" + text)); stringBuilder.Append(value); } return stringBuilder.ToString(); } public void Append(params string[] comments) { Comments.AddRange(comments); } } public class IniFile { private readonly IniComment _comments; private readonly List<IniSection> _sections; public IniSection this[string sec] => CreateSection(sec); public IniComment Comments => _comments; public List<IniSection> Sections => _sections; public IniFile() { _comments = new IniComment(); _sections = new List<IniSection>(); } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < Sections.Count; i++) { IniSection iniSection = Sections[i]; if (iniSection.Comments.Comments.Any()) { stringBuilder.AppendLine(iniSection.Comments.ToString()); } stringBuilder.AppendLine(iniSection.ToString()); foreach (IniKey key in iniSection.Keys) { if (key.Comments.Comments.Any()) { stringBuilder.AppendLine(key.Comments.ToString()); } stringBuilder.AppendLine(key.ToString()); } if (i < Sections.Count - 1) { stringBuilder.AppendLine(); } } if (Comments.Comments.Any()) { stringBuilder.AppendLine(); stringBuilder.AppendLine(Comments.ToString()); } return stringBuilder.ToString(); } public IniSection CreateSection(string section) { IniSection section2 = GetSection(section); if (section2 != null) { return section2; } IniSection iniSection = new IniSection(section); _sections.Add(iniSection); return iniSection; } public bool DeleteSection(string section) { if (!HasSection(section)) { return false; } Sections.Remove(GetSection(section)); return true; } public IniSection GetSection(string section) { if (!HasSection(section)) { return null; } return _sections.FirstOrDefault((IniSection iniSection) => iniSection.Section == section); } public bool HasSection(string section) { return _sections.Any((IniSection iniSection) => iniSection.Section == section); } public void Merge(IniFile ini) { Comments.Append(ini.Comments.Comments.ToArray()); foreach (IniSection section in ini.Sections) { IniSection iniSection = this[section.Section]; iniSection.Comments.Append(section.Comments.Comments.ToArray()); foreach (IniKey key in section.Keys) { IniKey iniKey = iniSection[key.Key]; iniKey.Comments.Append(key.Comments.Comments.ToArray()); iniKey.Value = key.Value; } } } public void Save(string filePath) { string directoryName = Path.GetDirectoryName(filePath); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllText(filePath, ToString(), Encoding.UTF8); } public static IniFile FromFile(string iniString) { return IniParser.Parse(File.ReadAllText(iniString)); } public static IniFile FromString(string iniString) { return IniParser.Parse(iniString); } } public class IniKey { private readonly IniComment _comments; public IniComment Comments => _comments; public string Key { get; set; } public string RawValue { get; set; } public string Value { get { return Resolve(RawValue); } set { RawValue = value; } } public IniKey(string key, string value = null) { Key = key; Value = value; _comments = new IniComment(); } public override string ToString() { return $"{Key}={RawValue}"; } private static string GetEnvironment(string env) { return Environment.ExpandEnvironmentVariables(env); } private static string GetRegistry(string path) { string directoryName = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); if (string.IsNullOrEmpty(directoryName)) { return null; } return Registry.GetValue(directoryName, fileName, string.Empty)?.ToString(); } private static string Resolve(string value) { if (value == null) { return null; } Regex regex = new Regex("\\$\\((?<reg>.*)\\)"); Regex regex2 = new Regex("%.*%"); while (regex.IsMatch(value) || regex2.IsMatch(value)) { value = regex.Replace(value, (Match match) => GetRegistry(match.Groups["reg"].Value)); value = GetEnvironment(value); } return value; } } internal class IniParser { private static readonly Regex CommentRegex = new Regex("^;(?<com>.*)"); private static readonly Regex KeyRegex = new Regex("^(?<key>[\\w\\s]+)=(?<val>.*)$"); private static readonly Regex SectionRegex = new Regex("^\\[(?<sec>[\\w\\s]+)\\]$"); private static readonly Regex VarRegex = new Regex("^\\@(?<key>[\\w\\s]+)=(?<val>.*)$"); public static IniFile Parse(string iniString) { IniFile iniFile = new IniFile(); string[] array = (from line in iniString.Split(new char[1] { '\n' }) let trimmed = line.Trim() select trimmed.TrimEnd(new char[1] { '\r' })).ToArray(); List<string> list = new List<string>(); IniSection iniSection = null; bool flag = false; for (int i = 0; i < array.Length; i++) { string text = array[i]; if (string.IsNullOrEmpty(text)) { continue; } if (IsComment(text)) { string comment = GetComment(text); list.Add(comment); if (IsVariable(comment)) { string[] variable = GetVariable(comment); string variable2 = variable[0]; string value = variable[1]; Environment.SetEnvironmentVariable(variable2, value); } flag = true; } else if (IsSection(text)) { iniSection = iniFile[GetSection(text)]; if (flag) { iniSection.Comments.Append(list.ToArray()); list.Clear(); flag = false; } } else if (IsKey(text)) { if (iniSection == null) { throw new Exception($"{i}: Sectionless Key Value Pair"); } string[] key = GetKey(text); string key2 = key[0]; string value2 = key[1]; if (flag) { iniSection[key2].Comments.Append(list.ToArray()); list.Clear(); flag = false; } iniSection[key2].Value = value2; } } if (flag) { iniFile.Comments.Append(list.ToArray()); } return iniFile; } private static string GetComment(string line) { return CommentRegex.Match(line).Groups["com"].Value; } private static string[] GetKey(string line) { Match match = KeyRegex.Match(line); return new string[2] { match.Groups["key"].Value, match.Groups["val"].Value }; } private static string GetSection(string line) { return SectionRegex.Match(line).Groups["sec"].Value; } private static string[] GetVariable(string line) { Match match = VarRegex.Match(line); return new string[2] { match.Groups["key"].Value, match.Groups["val"].Value }; } private static bool IsComment(string line) { return CommentRegex.IsMatch(line); } private static bool IsKey(string line) { return KeyRegex.IsMatch(line); } private static bool IsSection(string line) { return SectionRegex.IsMatch(line); } private static bool IsVariable(string line) { return VarRegex.IsMatch(line); } } public class IniSection { private readonly IniComment _comments; private readonly List<IniKey> _keys; public IniKey this[string key] => CreateKey(key); public IniComment Comments => _comments; public List<IniKey> Keys => _keys; public string Section { get; set; } public IniSection(string section) { Section = section; _comments = new IniComment(); _keys = new List<IniKey>(); } public override string ToString() { return $"[{Section}]"; } public IniKey CreateKey(string key) { IniKey key2 = GetKey(key); if (key2 != null) { return key2; } IniKey iniKey = new IniKey(key); _keys.Add(iniKey); return iniKey; } public IniKey GetKey(string key) { if (!HasKey(key)) { return null; } return _keys.FirstOrDefault((IniKey iniKey) => iniKey.Key == key); } public bool HasKey(string key) { return _keys.Any((IniKey iniKey) => iniKey.Key == key); } public bool DeleteKey(string key) { if (!HasKey(key)) { return false; } Keys.Remove(GetKey(key)); return true; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/BaiduTranslate.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core; using XUnity.AutoTranslator.Plugin.Core.Constants; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Extensions; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.Common.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("BaiduTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BaiduTranslate")] [assembly: AssemblyTitle("BaiduTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace BaiduTranslate; internal class BaiduTranslateEndpoint : HttpEndpoint { private static readonly Dictionary<string, string> SupportedLanguages = new Dictionary<string, string> { { "en", "en" }, { "ja", "jp" }, { "jp", "jp" }, { "zh", "zh" }, { "zh-Hans", "zh" }, { "zh-CN", "zh" }, { "zh-Hant", "cht" }, { "zh-TW", "cht" }, { "ko", "kor" }, { "kor", "kor" }, { "fra", "fra" }, { "fr", "fra" }, { "spa", "spa" }, { "es", "spa" }, { "ara", "ara" }, { "ar", "ara" }, { "bg", "bul" }, { "bul", "bul" }, { "et", "est" }, { "est", "est" }, { "da", "dan" }, { "dan", "dan" }, { "fi", "fin" }, { "fin", "fin" }, { "ro", "rom" }, { "rom", "rom" }, { "sl", "slo" }, { "slo", "slo" }, { "vi", "vie" }, { "vie", "vie" }, { "sv", "swe" }, { "swe", "swe" }, { "th", "th" }, { "ru", "ru" }, { "pt", "pt" }, { "de", "de" }, { "it", "it" }, { "el", "el" }, { "nl", "nl" }, { "pl", "pl" }, { "cs", "cs" }, { "hu", "hu" } }; private static readonly string HttpServicePointTemplateUrl = "https://api.fanyi.baidu.com/api/trans/vip/translate?q={0}&from={1}&to={2}&appid={3}&salt={4}&sign={5}"; private static readonly MD5 HashMD5 = MD5.Create(); private string _appId; private string _appSecret; private float _delay; private float _lastRequestTimestamp; public override string Id => "BaiduTranslate"; public override string FriendlyName => "Baidu Translator"; private string FixLanguage(string lang) { if (SupportedLanguages.TryGetValue(lang, out var value)) { return value; } return lang; } public override void Initialize(IInitializationContext context) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) _appId = context.GetOrCreateSetting<string>("Baidu", "BaiduAppId", ""); _appSecret = context.GetOrCreateSetting<string>("Baidu", "BaiduAppSecret", ""); _delay = context.GetOrCreateSetting<float>("Baidu", "DelaySeconds", 1f); if (string.IsNullOrEmpty(_appId)) { throw new EndpointInitializationException("The BaiduTranslate endpoint requires an App Id which has not been provided."); } if (string.IsNullOrEmpty(_appSecret)) { throw new EndpointInitializationException("The BaiduTranslate endpoint requires an App Secret which has not been provided."); } context.DisableCertificateChecksFor(new string[1] { "api.fanyi.baidu.com" }); if (!SupportedLanguages.ContainsKey(context.SourceLanguage)) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.ContainsKey(context.DestinationLanguage)) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { float realtimeSinceStartup = TimeHelper.realtimeSinceStartup; float num = realtimeSinceStartup - _lastRequestTimestamp; if (num < _delay) { float num2 = _delay - num; object obj = CoroutineHelper.CreateWaitForSecondsRealtime(num2); if (obj != null) { yield return obj; } else { float end = realtimeSinceStartup + num2; while (realtimeSinceStartup < end) { yield return null; } } } _lastRequestTimestamp = TimeHelper.realtimeSinceStartup; } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown string text = DateTime.UtcNow.Millisecond.ToString(); string text2 = CreateMD5(_appId + ((ITranslationContextBase)context).UntranslatedText + text + _appSecret); XUnityWebRequest val = new XUnityWebRequest(string.Format(HttpServicePointTemplateUrl, Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText), FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), _appId, text, text2)); val.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); val.Headers[HttpRequestHeader.AcceptCharset] = "UTF-8"; context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) string data = ((IHttpResponseInspectionContext)context).Response.Data; if (data.StartsWith("{\"error")) { return; } JSONNode val = JSON.Parse(data); StringBuilder stringBuilder = new StringBuilder(data.Length); Enumerator enumerator = ((JSONNode)((JSONNode)val.AsObject)["trans_result"].AsArray).GetEnumerator(); while (((Enumerator)(ref enumerator)).MoveNext()) { string text = ((object)((JSONNode)JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsObject)["dst"]).ToString(); text = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder)) { stringBuilder.Append("\n"); } stringBuilder.Append(text); } string text2 = stringBuilder.ToString(); context.Complete(text2); } private static string CreateMD5(string input) { byte[] bytes = Encoding.UTF8.GetBytes(input); byte[] array = HashMD5.ComputeHash(bytes); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < array.Length; i++) { stringBuilder.Append(array[i].ToString("X2")); } return stringBuilder.ToString().ToLower(); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/BingTranslate.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core; using XUnity.AutoTranslator.Plugin.Core.Constants; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Shims; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.Common.Logging; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("BingTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BingTranslate")] [assembly: AssemblyTitle("BingTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace BingTranslate; public class BingTranslateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "auto-detect", "af", "ar", "bn", "bs", "bg", "yue", "ca", "zh-Hans", "zh-Hant", "hr", "cs", "da", "nl", "en", "et", "fj", "fil", "fi", "fr", "de", "el", "ht", "he", "hi", "mww", "hu", "is", "id", "it", "ja", "sw", "tlh", "tlh-Qaak", "ko", "lv", "lt", "mg", "ms", "mt", "nb", "fa", "pl", "pt", "otq", "ro", "ru", "sm", "sr-Cyrl", "sr-Latn", "sk", "sl", "es", "sv", "ty", "ta", "te", "th", "to", "tr", "uk", "ur", "vi", "cy", "yua" }; private static readonly string HttpsServicePointTemplateUrl = "https://www.bing.com/ttranslatev3?isVertical=1&&IG={0}&IID={1}.{2}"; private static readonly string HttpsServicePointTemplateUrlWithoutIG = "https://www.bing.com/ttranslatev3?isVertical=1"; private static readonly string HttpsTranslateUserSite = "https://www.bing.com/translator"; private static readonly string RequestTemplate = "&fromLang={1}&text={0}&to={2}"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] Accepts = new string[1] { "*/*" }; private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; private static readonly string[] Referers = new string[1] { "https://bing.com/translator" }; private static readonly string[] Origins = new string[1] { "https://www.bing.com" }; private static readonly string[] AcceptCharsets = new string[2] { null, Encoding.UTF8.WebName }; private static readonly string[] ContentTypes = new string[1] { "application/x-www-form-urlencoded" }; private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; private static readonly string Referer = Referers[RandomNumbers.Next(Referers.Length)]; private static readonly string Origin = Origins[RandomNumbers.Next(Origins.Length)]; private static readonly string AcceptCharset = AcceptCharsets[RandomNumbers.Next(AcceptCharsets.Length)]; private static readonly string ContentType = ContentTypes[RandomNumbers.Next(ContentTypes.Length)]; private CookieContainer _cookieContainer; private bool _hasSetup; private string _ig; private string _iid; private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); public override string Id => "BingTranslate"; public override string FriendlyName => "Bing Translator"; public BingTranslateEndpoint() { _cookieContainer = new CookieContainer(); } private string FixLanguage(string lang) { switch (lang) { case "zh-CN": case "zh": return "zh-Hans"; case "zh-TW": return "zh-Hant"; case "auto": return "auto-detect"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) context.DisableCertificateChecksFor(new string[1] { "www.bing.com" }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _translationCount = 0; _hasSetup = true; IEnumerator enumerator = SetupIGAndIID(); while (enumerator.MoveNext()) { yield return enumerator.Current; } } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown _translationCount++; string text = null; text = ((_ig != null && _iid != null) ? string.Format(HttpsServicePointTemplateUrl, _ig, _iid, _translationCount) : HttpsServicePointTemplateUrlWithoutIG); string text2 = string.Format(RequestTemplate, Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText), FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage)); XUnityWebRequest val = new XUnityWebRequest("POST", text, text2); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: true); context.Complete(val); } public override void OnInspectResponse(IHttpResponseInspectionContext context) { InspectResponse(context.Response); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { string text = ((object)((JSONNode)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsArray)[0]["translations"].AsArray)[0]["text"]).ToString(); string text2 = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); context.Complete(text2); } private XUnityWebRequest CreateWebSiteRequest() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(HttpsTranslateUserSite); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: false); return val; } private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest) { request.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); if (AcceptLanguage != null) { request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage; } if (Accept != null) { request.Headers[HttpRequestHeader.Accept] = Accept; } if (Referer != null && isTranslationRequest) { request.Headers[HttpRequestHeader.Referer] = Referer; } if (Origin != null && isTranslationRequest) { request.Headers["Origin"] = Origin; } if (AcceptCharset != null) { request.Headers[HttpRequestHeader.AcceptCharset] = AcceptCharset; } if (ContentType != null && isTranslationRequest) { request.Headers[HttpRequestHeader.ContentType] = ContentType; } } private void InspectResponse(XUnityWebResponse response) { CookieCollection newCookies = response.NewCookies; _cookieContainer.Add(newCookies); } public IEnumerator SetupIGAndIID() { _cookieContainer = new CookieContainer(); XUnityWebResponse response; try { XUnityWebClient val = new XUnityWebClient(); XUnityWebRequest val2 = CreateWebSiteRequest(); response = val.Send(val2); } catch (Exception ex) { XuaLogger.AutoTranslator.Warn(ex, "An error occurred while setting up BingTranslate IG. Proceeding without..."); yield break; } IEnumerator iterator = ((CustomYieldInstructionShim)response).GetSupportedEnumerator(); while (iterator.MoveNext()) { yield return iterator.Current; } if (((CustomYieldInstructionShim)response).IsTimedOut) { XuaLogger.AutoTranslator.Warn("A timeout error occurred while setting up BingTranslate IG. Proceeding without..."); yield break; } if (response.Error != null) { XuaLogger.AutoTranslator.Warn(response.Error, "An error occurred while setting up BingTranslate IG. Proceeding without..."); yield break; } if (response.Data == null) { XuaLogger.AutoTranslator.Warn((Exception)null, "An error occurred while setting up BingTranslate IG. Proceeding without..."); yield break; } InspectResponse(response); try { string data = response.Data; _ig = Lookup("\",IG:\"", data); _iid = Lookup("data-iid=\"", data); if (_ig == null || _iid == null) { XuaLogger.AutoTranslator.Warn("An error occurred while setting up BingTranslate IG/IID. Proceeding without..."); } } catch (Exception ex2) { XuaLogger.AutoTranslator.Warn(ex2, "An error occurred while setting up BingTranslate IG. Proceeding without..."); } } private string Lookup(string lookFor, string html) { int num = html.IndexOf(lookFor); if (num > -1) { int num2 = num + lookFor.Length; int num3 = html.IndexOf("\"", num2); if (num2 > -1 && num3 > -1) { return html.Substring(num2, num3 - num2); } } return null; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/BingTranslateLegitimate.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("BingTranslateLegitimate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BingTranslateLegitimate")] [assembly: AssemblyTitle("BingTranslateLegitimate")] [assembly: AssemblyVersion("1.0.0.0")] namespace BingTranslateLegitimate; public class BingTranslateLegitimateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "af", "ar", "bn", "bs", "bg", "yue", "ca", "zh-Hans", "zh-Hant", "hr", "cs", "da", "nl", "en", "et", "fj", "fil", "fi", "fr", "de", "el", "ht", "he", "hi", "mww", "hu", "is", "id", "it", "ja", "sw", "tlh", "tlh-Qaak", "ko", "lv", "lt", "mg", "ms", "mt", "nb", "fa", "pl", "pt", "otq", "ro", "ru", "sm", "sr-Cyrl", "sr-Latn", "sk", "sl", "es", "sv", "ty", "ta", "te", "th", "to", "tr", "uk", "ur", "vi", "cy", "yua" }; private static readonly string HttpsServicePointTemplateUrl = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from={0}&to={1}"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] Accepts = new string[1] { "application/json" }; private static readonly string[] ContentTypes = new string[1] { "application/json" }; private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; private static readonly string ContentType = ContentTypes[RandomNumbers.Next(ContentTypes.Length)]; private string _key; public override string Id => "BingTranslateLegitimate"; public override string FriendlyName => "Bing Translator (Authenticated)"; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-CN": case "zh": return "zh-Hans"; case "zh-TW": return "zh-Hant"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) _key = context.GetOrCreateSetting<string>("BingLegitimate", "OcpApimSubscriptionKey", ""); if (string.IsNullOrEmpty(_key)) { throw new EndpointInitializationException("The BingTranslateLegitimate endpoint requires an API key which has not been provided."); } context.DisableCertificateChecksFor(new string[1] { "api.cognitive.microsofttranslator.com" }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("["); for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++) { string value = JsonHelper.Escape(((ITranslationContextBase)context).UntranslatedTexts[i]); stringBuilder.Append("{\"Text\":\""); stringBuilder.Append(value); stringBuilder.Append("\"}"); if (((ITranslationContextBase)context).UntranslatedTexts.Length - 1 != i) { stringBuilder.Append(","); } } stringBuilder.Append("]"); XUnityWebRequest val = new XUnityWebRequest("POST", string.Format(HttpsServicePointTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage)), stringBuilder.ToString()); if (Accept != null) { val.Headers[HttpRequestHeader.Accept] = Accept; } if (ContentType != null) { val.Headers[HttpRequestHeader.ContentType] = ContentType; } val.Headers["Ocp-Apim-Subscription-Key"] = _key; context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { JSONArray asArray = JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsArray; List<string> list = new List<string>(); for (int i = 0; i < ((JSONNode)asArray).Count; i++) { JSONNode obj = ((JSONNode)((JSONNode)asArray)[i].AsObject)["translations"]; object obj2; if (obj == null) { obj2 = null; } else { JSONNode obj3 = ((JSONNode)obj.AsArray)[0]; obj2 = ((obj3 != null) ? ((object)((JSONNode)obj3.AsObject)["text"])?.ToString() : null); } string text = (string)obj2; string item = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); list.Add(item); } context.Complete(list.ToArray()); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/CustomTranslate.dll
Decompiled 10 months agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("CustomTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CustomTranslate")] [assembly: AssemblyTitle("CustomTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace CustomTranslate; internal class CustomTranslateEndpoint : HttpEndpoint { private static readonly string ServicePointTemplateUrl = "{0}?from={1}&to={2}&text={3}"; private string _endpoint; private string _friendlyName; public override string Id => "CustomTranslate"; public override string FriendlyName => _friendlyName; public CustomTranslateEndpoint() { _friendlyName = "Custom"; } public override void Initialize(IInitializationContext context) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) _endpoint = context.GetOrCreateSetting<string>("Custom", "Url", ""); if (string.IsNullOrEmpty(_endpoint)) { throw new EndpointInitializationException("The custom endpoint requires a url which has not been provided."); } Uri uri = new Uri(_endpoint); context.DisableCertificateChecksFor(new string[1] { uri.Host }); _friendlyName = _friendlyName + " (" + uri.Host + ")"; } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(string.Format(ServicePointTemplateUrl, _endpoint, ((ITranslationContextBase)context).SourceLanguage, ((ITranslationContextBase)context).DestinationLanguage, Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText))); context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { context.Complete(((IHttpResponseInspectionContext)context).Response.Data); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/DeepLTranslate.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol; using XUnity.Common.Logging; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("DeepLTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DeepLTranslate")] [assembly: AssemblyTitle("DeepLTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace DeepLTranslate; public class DeepLTranslate : ExtProtocolEndpoint { private const float MinimumMinDelaySeconds = 1f; private const float MinimumMaxDelaySeconds = 3f; private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "bg", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "hu", "it", "ja", "lt", "lv", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sv", "zh", "ko" }; public override string Id => "DeepLTranslate"; public override string FriendlyName => "DeepL Translator"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 25; protected override string ConfigurationSectionName => "DeepL"; private string FixLanguage(string lang) { if (lang == "zh-Hans" || lang == "zh-CN") { return "zh"; } return lang; } public override void Initialize(IInitializationContext context) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) ((ExtProtocolEndpoint)this).Initialize(context); ((ExtProtocolEndpoint)this).MinDelay = context.GetOrCreateSetting<float>("DeepL", "MinDelaySeconds", 2f); if (((ExtProtocolEndpoint)this).MinDelay < 1f) { XuaLogger.AutoTranslator.Warn($"[DeepL] Cannot set MinDelaySeconds below {1f} second(s). Setting MinDelaySeconds={1f}"); context.SetSetting<float>("DeepL", "MinDelaySeconds", 1f); } ((ExtProtocolEndpoint)this).MaxDelay = context.GetOrCreateSetting<float>("DeepL", "MaxDelaySeconds", 6f); if (((ExtProtocolEndpoint)this).MaxDelay < 3f) { XuaLogger.AutoTranslator.Warn($"[DeepL] Cannot set MaxDelaySeconds below {3f} second(s). Setting MaxDelaySeconds={3f}"); context.SetSetting<float>("DeepL", "MaxDelaySeconds", 3f); } if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes("DeepLTranslate.ExtProtocol.ExtDeepLTranslate, DeepLTranslate.ExtProtocol"), Base64FormattingOptions.None); } } public class DeepLTranslateLegitimate : ExtProtocolEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "bg", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "hu", "it", "ja", "lt", "lv", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sv", "zh", "ko" }; public override string Id => "DeepLTranslateLegitimate"; public override string FriendlyName => "DeepL Translator (Authenticated)"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 25; protected override string ConfigurationSectionName => "DeepLLegitimate"; private string FixLanguage(string lang) { if (lang == "zh-Hans" || lang == "zh-CN") { return "zh"; } return lang; } public override void Initialize(IInitializationContext context) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) ((ExtProtocolEndpoint)this).Initialize(context); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } string orCreateSetting = context.GetOrCreateSetting<string>(((ExtProtocolEndpoint)this).ConfigurationSectionName, "ApiKey", ""); bool orCreateSetting2 = context.GetOrCreateSetting<bool>(((ExtProtocolEndpoint)this).ConfigurationSectionName, "Free", false); if (string.IsNullOrEmpty(orCreateSetting)) { throw new EndpointInitializationException("The endpoint requires an API key which has not been provided."); } ((ExtProtocolEndpoint)this).ConfigForExternalProcess = string.Join("\n", orCreateSetting, orCreateSetting2.ToString()); ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes("DeepLTranslate.ExtProtocol.ExtDeepLTranslateLegitimate, DeepLTranslate.ExtProtocol"), Base64FormattingOptions.None); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/ezTransXP.dll
Decompiled 10 months agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using Microsoft.Win32; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("ezTransXP")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ezTransXP")] [assembly: AssemblyTitle("ezTransXP")] [assembly: AssemblyVersion("1.0.0.0")] namespace ezTransXP; public class ezTransXPEndpoint : ExtProtocolEndpoint { public override string Id => "ezTransXP"; public override string FriendlyName => "ezTransXP"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 50; public override void Initialize(IInitializationContext context) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) string defaultInstallationPath = GetDefaultInstallationPath(); string text = context.GetOrCreateSetting<string>("ezTrans", "InstallationPath", defaultInstallationPath); if (string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(defaultInstallationPath)) { context.SetSetting<string>("ezTrans", "InstallationPath", defaultInstallationPath); text = defaultInstallationPath; } context.DisableSpamChecks(); string text2 = Path.Combine(context.TranslatorDirectory, "FullNET\\ezTransXP.ExtProtocol.exe"); if (!File.Exists(text2)) { throw new EndpointInitializationException("Could not find any executable at '" + text2 + "'"); } ((ExtProtocolEndpoint)this).ExecutablePath = text2; ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes(text)); if (context.SourceLanguage != "ja") { throw new EndpointInitializationException("Current implementation only supports japanese-to-korean."); } if (context.DestinationLanguage != "ko") { throw new EndpointInitializationException("Current implementation only supports japanese-to-korean."); } } public static string GetDefaultInstallationPath() { try { return (string)Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\ChangShin\\ezTrans", "FilePath", null); } catch { return null; } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/Common.ExtProtocol.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; using XUnity.AutoTranslator.Plugin.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Common.ExtProtocol")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Common.ExtProtocol")] [assembly: AssemblyTitle("Common.ExtProtocol")] [assembly: AssemblyVersion("1.0.0.0")] namespace SimpleJSON { public enum JSONNodeType { Array = 1, Object = 2, String = 3, Number = 4, NullValue = 5, Boolean = 6, None = 7, Custom = 255 } public enum JSONTextMode { Compact, Indent } public abstract class JSONNode { public struct Enumerator { private enum Type { None, Array, Object } private Type type; private Dictionary<string, JSONNode>.Enumerator m_Object; private List<JSONNode>.Enumerator m_Array; public bool IsValid => type != Type.None; public KeyValuePair<string, JSONNode> Current { get { if (type == Type.Array) { return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current); } if (type == Type.Object) { return m_Object.Current; } return new KeyValuePair<string, JSONNode>(string.Empty, null); } } public Enumerator(List<JSONNode>.Enumerator aArrayEnum) { type = Type.Array; m_Object = default(Dictionary<string, JSONNode>.Enumerator); m_Array = aArrayEnum; } public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) { type = Type.Object; m_Object = aDictEnum; m_Array = default(List<JSONNode>.Enumerator); } public bool MoveNext() { if (type == Type.Array) { return m_Array.MoveNext(); } if (type == Type.Object) { return m_Object.MoveNext(); } return false; } } public struct ValueEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Value; public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public ValueEnumerator GetEnumerator() { return this; } } public struct KeyEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Key; public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public KeyEnumerator GetEnumerator() { return this; } } public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable { private JSONNode m_Node; private Enumerator m_Enumerator; public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current; object IEnumerator.Current => m_Enumerator.Current; internal LinqEnumerator(JSONNode aNode) { m_Node = aNode; if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } public bool MoveNext() { return m_Enumerator.MoveNext(); } public void Dispose() { m_Node = null; m_Enumerator = default(Enumerator); } public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator() { return new LinqEnumerator(m_Node); } public void Reset() { if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { return new LinqEnumerator(m_Node); } } public static bool forceASCII; [ThreadStatic] private static StringBuilder m_EscapeBuilder; public abstract JSONNodeType Tag { get; } public virtual JSONNode this[int aIndex] { get { return null; } set { } } public virtual JSONNode this[string aKey] { get { return null; } set { } } public virtual string Value { get { return ""; } set { } } public virtual int Count => 0; public virtual bool IsNumber => false; public virtual bool IsString => false; public virtual bool IsBoolean => false; public virtual bool IsNull => false; public virtual bool IsArray => false; public virtual bool IsObject => false; public virtual bool Inline { get { return false; } set { } } public virtual IEnumerable<JSONNode> Children { get { yield break; } } public IEnumerable<JSONNode> DeepChildren { get { foreach (JSONNode child in Children) { foreach (JSONNode deepChild in child.DeepChildren) { yield return deepChild; } } } } public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this); public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator()); public ValueEnumerator Values => new ValueEnumerator(GetEnumerator()); public virtual double AsDouble { get { double result = 0.0; if (double.TryParse(Value, out result)) { return result; } return 0.0; } set { Value = value.ToString(); } } public virtual int AsInt { get { return (int)AsDouble; } set { AsDouble = value; } } public virtual float AsFloat { get { return (float)AsDouble; } set { AsDouble = value; } } public virtual bool AsBool { get { bool result = false; if (bool.TryParse(Value, out result)) { return result; } return !string.IsNullOrEmpty(Value); } set { Value = (value ? "true" : "false"); } } public virtual JSONArray AsArray => this as JSONArray; public virtual JSONObject AsObject => this as JSONObject; internal static StringBuilder EscapeBuilder { get { if (m_EscapeBuilder == null) { m_EscapeBuilder = new StringBuilder(); } return m_EscapeBuilder; } } public virtual void Add(string aKey, JSONNode aItem) { } public virtual void Add(JSONNode aItem) { Add("", aItem); } public virtual JSONNode Remove(string aKey) { return null; } public virtual JSONNode Remove(int aIndex) { return null; } public virtual JSONNode Remove(JSONNode aNode) { return aNode; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact); return stringBuilder.ToString(); } public virtual string ToString(int aIndent) { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent); return stringBuilder.ToString(); } internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); public abstract Enumerator GetEnumerator(); public static implicit operator JSONNode(string s) { return new JSONString(s); } public static implicit operator string(JSONNode d) { if (!(d == null)) { return d.Value; } return null; } public static implicit operator JSONNode(double n) { return new JSONNumber(n); } public static implicit operator double(JSONNode d) { if (!(d == null)) { return d.AsDouble; } return 0.0; } public static implicit operator JSONNode(float n) { return new JSONNumber(n); } public static implicit operator float(JSONNode d) { if (!(d == null)) { return d.AsFloat; } return 0f; } public static implicit operator JSONNode(int n) { return new JSONNumber(n); } public static implicit operator int(JSONNode d) { if (!(d == null)) { return d.AsInt; } return 0; } public static implicit operator JSONNode(bool b) { return new JSONBool(b); } public static implicit operator bool(JSONNode d) { if (!(d == null)) { return d.AsBool; } return false; } public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue) { return aKeyValue.Value; } public static bool operator ==(JSONNode a, object b) { if ((object)a == b) { return true; } bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator; bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator; if (flag && flag2) { return true; } if (!flag) { return a.Equals(b); } return false; } public static bool operator !=(JSONNode a, object b) { return !(a == b); } public override bool Equals(object obj) { return (object)this == obj; } public override int GetHashCode() { return base.GetHashCode(); } internal static string Escape(string aText) { StringBuilder escapeBuilder = EscapeBuilder; escapeBuilder.Length = 0; if (escapeBuilder.Capacity < aText.Length + aText.Length / 10) { escapeBuilder.Capacity = aText.Length + aText.Length / 10; } foreach (char c in aText) { switch (c) { case '\\': escapeBuilder.Append("\\\\"); continue; case '"': escapeBuilder.Append("\\\""); continue; case '\n': escapeBuilder.Append("\\n"); continue; case '\r': escapeBuilder.Append("\\r"); continue; case '\t': escapeBuilder.Append("\\t"); continue; case '\b': escapeBuilder.Append("\\b"); continue; case '\f': escapeBuilder.Append("\\f"); continue; } if (c < ' ' || (forceASCII && c > '\u007f')) { ushort num = c; escapeBuilder.Append("\\u").Append(num.ToString("X4")); } else { escapeBuilder.Append(c); } } string result = escapeBuilder.ToString(); escapeBuilder.Length = 0; return result; } private static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted) { if (quoted) { ctx.Add(tokenName, token); return; } string text = token.ToLower(); switch (text) { case "false": case "true": ctx.Add(tokenName, text == "true"); return; case "null": ctx.Add(tokenName, null); return; } if (double.TryParse(token, out var result)) { ctx.Add(tokenName, result); } else { ctx.Add(tokenName, token); } } public static JSONNode Parse(string aJSON) { Stack<JSONNode> stack = new Stack<JSONNode>(); JSONNode jSONNode = null; int i = 0; StringBuilder stringBuilder = new StringBuilder(); string text = ""; bool flag = false; bool flag2 = false; for (; i < aJSON.Length; i++) { switch (aJSON[i]) { case '{': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONObject()); if (jSONNode != null) { jSONNode.Add(text, stack.Peek()); } text = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); break; case '[': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONArray()); if (jSONNode != null) { jSONNode.Add(text, stack.Peek()); } text = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); break; case ']': case '}': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stack.Count == 0) { throw new Exception("JSON Parse: Too many closing brackets"); } stack.Pop(); if (stringBuilder.Length > 0 || flag2) { ParseElement(jSONNode, stringBuilder.ToString(), text, flag2); flag2 = false; } text = ""; stringBuilder.Length = 0; if (stack.Count > 0) { jSONNode = stack.Peek(); } break; case ':': if (flag) { stringBuilder.Append(aJSON[i]); break; } text = stringBuilder.ToString(); stringBuilder.Length = 0; flag2 = false; break; case '"': flag = !flag; flag2 = flag2 || flag; break; case ',': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stringBuilder.Length > 0 || flag2) { ParseElement(jSONNode, stringBuilder.ToString(), text, flag2); flag2 = false; } text = ""; stringBuilder.Length = 0; flag2 = false; break; case '\t': case ' ': if (flag) { stringBuilder.Append(aJSON[i]); } break; case '\\': i++; if (flag) { char c = aJSON[i]; switch (c) { case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; case 'n': stringBuilder.Append('\n'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'u': { string s = aJSON.Substring(i + 1, 4); stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier)); i += 4; break; } default: stringBuilder.Append(c); break; } } break; default: stringBuilder.Append(aJSON[i]); break; case '\n': case '\r': break; } } if (flag) { throw new Exception("JSON Parse: Quotation marks seems to be messed up."); } return jSONNode; } } public class JSONArray : JSONNode { private List<JSONNode> m_List = new List<JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Array; public override bool IsArray => true; public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_List.Count) { return new JSONLazyCreator(this); } return m_List[aIndex]; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex < 0 || aIndex >= m_List.Count) { m_List.Add(value); } else { m_List[aIndex] = value; } } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this); } set { if (value == null) { value = JSONNull.CreateOrGet(); } m_List.Add(value); } } public override int Count => m_List.Count; public override IEnumerable<JSONNode> Children { get { foreach (JSONNode item in m_List) { yield return item; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } m_List.Add(aItem); } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_List.Count) { return null; } JSONNode result = m_List[aIndex]; m_List.RemoveAt(aIndex); return result; } public override JSONNode Remove(JSONNode aNode) { m_List.Remove(aNode); return aNode; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('['); int count = m_List.Count; if (inline) { aMode = JSONTextMode.Compact; } for (int i = 0; i < count; i++) { if (i > 0) { aSB.Append(','); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append(']'); } } public class JSONObject : JSONNode { private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Object; public override bool IsObject => true; public override JSONNode this[string aKey] { get { if (m_Dict.ContainsKey(aKey)) { return m_Dict[aKey]; } return new JSONLazyCreator(this, aKey); } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = value; } else { m_Dict.Add(aKey, value); } } } public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } return m_Dict.ElementAt(aIndex).Value; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex >= 0 && aIndex < m_Dict.Count) { string key = m_Dict.ElementAt(aIndex).Key; m_Dict[key] = value; } } } public override int Count => m_Dict.Count; public override IEnumerable<JSONNode> Children { get { foreach (KeyValuePair<string, JSONNode> item in m_Dict) { yield return item.Value; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } if (!string.IsNullOrEmpty(aKey)) { if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = aItem; } else { m_Dict.Add(aKey, aItem); } } else { m_Dict.Add(Guid.NewGuid().ToString(), aItem); } } public override JSONNode Remove(string aKey) { if (!m_Dict.ContainsKey(aKey)) { return null; } JSONNode result = m_Dict[aKey]; m_Dict.Remove(aKey); return result; } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex); m_Dict.Remove(keyValuePair.Key); return keyValuePair.Value; } public override JSONNode Remove(JSONNode aNode) { try { KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First(); m_Dict.Remove(keyValuePair.Key); return aNode; } catch { return null; } } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('{'); bool flag = true; if (inline) { aMode = JSONTextMode.Compact; } foreach (KeyValuePair<string, JSONNode> item in m_Dict) { if (!flag) { aSB.Append(','); } flag = false; if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"'); if (aMode == JSONTextMode.Compact) { aSB.Append(':'); } else { aSB.Append(" : "); } item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append('}'); } } public class JSONString : JSONNode { private string m_Data; public override JSONNodeType Tag => JSONNodeType.String; public override bool IsString => true; public override string Value { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONString(string aData) { m_Data = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"'); } public override bool Equals(object obj) { if (base.Equals(obj)) { return true; } if (obj is string text) { return m_Data == text; } JSONString jSONString = obj as JSONString; if (jSONString != null) { return m_Data == jSONString.m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONNumber : JSONNode { private double m_Data; public override JSONNodeType Tag => JSONNodeType.Number; public override bool IsNumber => true; public override string Value { get { return m_Data.ToString(); } set { if (double.TryParse(value, out var result)) { m_Data = result; } } } public override double AsDouble { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONNumber(double aData) { m_Data = aData; } public JSONNumber(string aData) { Value = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data); } private static bool IsNumeric(object value) { if (!(value is int) && !(value is uint) && !(value is float) && !(value is double) && !(value is decimal) && !(value is long) && !(value is ulong) && !(value is short) && !(value is ushort) && !(value is sbyte)) { return value is byte; } return true; } public override bool Equals(object obj) { if (obj == null) { return false; } if (base.Equals(obj)) { return true; } JSONNumber jSONNumber = obj as JSONNumber; if (jSONNumber != null) { return m_Data == jSONNumber.m_Data; } if (IsNumeric(obj)) { return Convert.ToDouble(obj) == m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONBool : JSONNode { private bool m_Data; public override JSONNodeType Tag => JSONNodeType.Boolean; public override bool IsBoolean => true; public override string Value { get { return m_Data.ToString(); } set { if (bool.TryParse(value, out var result)) { m_Data = result; } } } public override bool AsBool { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONBool(bool aData) { m_Data = aData; } public JSONBool(string aData) { Value = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data ? "true" : "false"); } public override bool Equals(object obj) { if (obj == null) { return false; } if (obj is bool) { return m_Data == (bool)obj; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONNull : JSONNode { private static JSONNull m_StaticInstance = new JSONNull(); public static bool reuseSameInstance = true; public override JSONNodeType Tag => JSONNodeType.NullValue; public override bool IsNull => true; public override string Value { get { return "null"; } set { } } public override bool AsBool { get { return false; } set { } } public static JSONNull CreateOrGet() { if (reuseSameInstance) { return m_StaticInstance; } return new JSONNull(); } private JSONNull() { } public override Enumerator GetEnumerator() { return default(Enumerator); } public override bool Equals(object obj) { if ((object)this == obj) { return true; } return obj is JSONNull; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } internal class JSONLazyCreator : JSONNode { private JSONNode m_Node; private string m_Key; public override JSONNodeType Tag => JSONNodeType.None; public override JSONNode this[int aIndex] { get { return new JSONLazyCreator(this); } set { JSONArray jSONArray = new JSONArray(); jSONArray.Add(value); Set(jSONArray); } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this, aKey); } set { JSONObject jSONObject = new JSONObject(); jSONObject.Add(aKey, value); Set(jSONObject); } } public override int AsInt { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override float AsFloat { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0f; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override double AsDouble { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0.0; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override bool AsBool { get { JSONBool aVal = new JSONBool(aData: false); Set(aVal); return false; } set { JSONBool aVal = new JSONBool(value); Set(aVal); } } public override JSONArray AsArray { get { JSONArray jSONArray = new JSONArray(); Set(jSONArray); return jSONArray; } } public override JSONObject AsObject { get { JSONObject jSONObject = new JSONObject(); Set(jSONObject); return jSONObject; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONLazyCreator(JSONNode aNode) { m_Node = aNode; m_Key = null; } public JSONLazyCreator(JSONNode aNode, string aKey) { m_Node = aNode; m_Key = aKey; } private void Set(JSONNode aVal) { if (m_Key == null) { m_Node.Add(aVal); } else { m_Node.Add(m_Key, aVal); } m_Node = null; } public override void Add(JSONNode aItem) { JSONArray jSONArray = new JSONArray(); jSONArray.Add(aItem); Set(jSONArray); } public override void Add(string aKey, JSONNode aItem) { JSONObject jSONObject = new JSONObject(); jSONObject.Add(aKey, aItem); Set(jSONObject); } public static bool operator ==(JSONLazyCreator a, object b) { if (b == null) { return true; } return (object)a == b; } public static bool operator !=(JSONLazyCreator a, object b) { return !(a == b); } public override bool Equals(object obj) { if (obj == null) { return true; } return (object)this == obj; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } public static class JSON { public static JSONNode Parse(string aJSON) { return JSONNode.Parse(aJSON); } } } namespace Common.ExtProtocol { public interface IExtTranslateEndpoint { Task Translate(ITranslationContext context); void Initialize(string config); } public interface ITranslationContext : ITranslationContextBase { void Complete(string translatedText); void Complete(string[] translatedTexts); } public interface ITranslationContextBase { string UntranslatedText { get; } string[] UntranslatedTexts { get; } UntranslatedTextInfo UntranslatedTextInfo { get; } UntranslatedTextInfo[] UntranslatedTextInfos { get; } string SourceLanguage { get; } string DestinationLanguage { get; } object UserState { get; set; } void Fail(string reason, Exception exception); void Fail(string reason); } public class TranslationContext : ITranslationContext, ITranslationContextBase { private string[] _untranslatedTexts; public string UntranslatedText => UntranslatedTexts[0]; public string[] UntranslatedTexts => _untranslatedTexts ?? (_untranslatedTexts = UntranslatedTextInfos.Select((UntranslatedTextInfo x) => x.UntranslatedText).ToArray()); public UntranslatedTextInfo UntranslatedTextInfo => UntranslatedTextInfos[0]; public UntranslatedTextInfo[] UntranslatedTextInfos { get; } public string SourceLanguage { get; } public string DestinationLanguage { get; } internal bool IsDone { get; private set; } public string[] TranslatedTexts { get; private set; } public string ErrorMessage { get; private set; } public Exception Error { get; private set; } public object UserState { get; set; } public TranslationContext(TransmittableUntranslatedTextInfo[] untranslatedTexts, string sourceLanguage, string destinationLanguage) { UntranslatedTextInfos = untranslatedTexts.Select((TransmittableUntranslatedTextInfo x) => new UntranslatedTextInfo(x)).ToArray(); SourceLanguage = sourceLanguage; DestinationLanguage = destinationLanguage; } public void Complete(string translatedText) { Complete(new string[1] { translatedText }); } public void Complete(string[] translatedTexts) { if (IsDone) { return; } try { if (translatedTexts.Length == 0) { FailContext("Received empty translation from translator.", null); return; } for (int i = 0; i < translatedTexts.Length; i++) { if (string.IsNullOrEmpty(translatedTexts[0])) { FailContext("Received empty translation from translator.", null); return; } } CompleteContext(translatedTexts); } finally { IsDone = true; } } public void Fail(string reason, Exception exception) { if (IsDone) { return; } try { FailContext(reason, exception); throw new TranslationContextException(); } finally { IsDone = true; } } public void Fail(string reason) { if (IsDone) { return; } try { FailContext(reason, null); throw new TranslationContextException(); } finally { IsDone = true; } } public void FailWithoutThrowing(string reason, Exception exception) { if (IsDone) { return; } try { FailContext(reason, exception); } finally { IsDone = true; } } internal void FailIfNotCompleted() { if (!IsDone) { FailWithoutThrowing("The translation request was not completed before returning from translator.", null); } } public void FailContext(string reason, Exception exception) { ErrorMessage = reason; Error = exception; } public void CompleteContext(string[] translatedTexts) { TranslatedTexts = translatedTexts; } } [Serializable] internal class TranslationContextException : Exception { public TranslationContextException() { } public TranslationContextException(string message) : base(message) { } public TranslationContextException(string message, Exception inner) : base(message, inner) { } protected TranslationContextException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public class UntranslatedTextInfo { public string[] ContextBefore { get; } public string UntranslatedText { get; } public string[] ContextAfter { get; } public UntranslatedTextInfo(TransmittableUntranslatedTextInfo untranslatedTextInfo) { ContextBefore = untranslatedTextInfo.ContextBefore; UntranslatedText = untranslatedTextInfo.UntranslatedText; ContextAfter = untranslatedTextInfo.ContextAfter; } public UntranslatedTextInfo(string[] contextBefore, string untranslatedText, string[] contextAfter) { ContextBefore = contextBefore; UntranslatedText = untranslatedText; ContextAfter = contextAfter; } } } namespace Common.ExtProtocol.Utilities { public static class JsonHelper { public static string Unescape(string str) { if (str == null) { return null; } StringBuilder stringBuilder = new StringBuilder(str); bool flag = false; for (int i = 0; i < stringBuilder.Length; i++) { char c = stringBuilder[i]; if (flag) { bool flag2 = true; char c2 = '\0'; switch (c) { case 'b': c2 = '\b'; break; case 'f': c2 = '\f'; break; case 'n': c2 = '\n'; break; case 'r': c2 = '\r'; break; case 't': c2 = '\t'; break; case '"': c2 = '"'; break; case '\\': c2 = '\\'; break; case 'u': c2 = 'u'; break; default: flag2 = false; break; } if (flag2) { if (c2 == 'u') { char value = (char)int.Parse(new string(new char[4] { stringBuilder[i + 1], stringBuilder[i + 2], stringBuilder[i + 3], stringBuilder[i + 4] }), NumberStyles.HexNumber); stringBuilder.Remove(--i, 6); stringBuilder.Insert(i, value); } else { stringBuilder.Remove(--i, 2); stringBuilder.Insert(i, c2); } } flag = false; } else if (c == '\\') { flag = true; } } return stringBuilder.ToString(); } public static string Escape(string str) { if (str == null || str.Length == 0) { return ""; } int length = str.Length; StringBuilder stringBuilder = new StringBuilder(length + 4); for (int i = 0; i < length; i++) { char c = str[i]; switch (c) { case '"': case '\\': stringBuilder.Append('\\'); stringBuilder.Append(c); break; case '\b': stringBuilder.Append("\\b"); break; case '\t': stringBuilder.Append("\\t"); break; case '\n': stringBuilder.Append("\\n"); break; case '\f': stringBuilder.Append("\\f"); break; case '\r': stringBuilder.Append("\\r"); break; case '\u0085': stringBuilder.Append("\\u0085"); break; case '\u2028': stringBuilder.Append("\\u2028"); break; case '\u2029': stringBuilder.Append("\\u2029"); break; default: stringBuilder.Append(c); break; } } return stringBuilder.ToString(); } } public static class StringBuilderExtensions { public static bool EndsWithWhitespaceOrNewline(this StringBuilder builder) { if (builder.Length == 0) { return true; } char c = builder[builder.Length - 1]; if (!char.IsWhiteSpace(c)) { return c == '\n'; } return true; } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/DeepLTranslate.ExtProtocol.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Common.ExtProtocol; using Common.ExtProtocol.Utilities; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SimpleJSON; [assembly: AssemblyProduct("DeepLTranslate.ExtProtocol")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCompany("DeepLTranslate.ExtProtocol")] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyTitle("DeepLTranslate.ExtProtocol")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DeepLTranslate.ExtProtocol { [Serializable] public class BlockedException : Exception { public BlockedException() { } public BlockedException(string message) : base(message) { } public BlockedException(string message, Exception inner) : base(message, inner) { } protected BlockedException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public static class HttpResponseMessageExtensions { public static void ThrowIfBlocked(this HttpResponseMessage msg) { if (msg.StatusCode == HttpStatusCode.TooManyRequests) { throw new Exception("Too many requests!"); } } } public class ExtDeepLTranslate : IExtTranslateEndpoint { private class UntranslatedTextInfo { public string UntranslatedText { get; set; } public List<TranslationPart> TranslationParts { get; set; } } public class TranslationPart { public bool IsTranslatable { get; set; } public string Value { get; set; } } private static readonly Regex NewlineSplitter; private static readonly DateTime Epoch; private static readonly string HttpsServicePointTemplateUrl; private static readonly string HttpsTranslateUserSite; private static readonly string HttpsTranslateStateSetup; private static readonly Random RandomNumbers; private static readonly string[] Accepts; private static readonly string[] AcceptLanguages; private static readonly string[] Referers; private static readonly string[] Origins; private static readonly string Accept; private static readonly string AcceptLanguage; private static readonly string Referer; private static readonly string Origin; private SemaphoreSlim _sem; private HttpClient _client; private HttpClientHandler _handler; private bool _hasSetup; private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); private long _id; static ExtDeepLTranslate() { NewlineSplitter = new Regex("([\\s]*[\\r\\n]+[\\s]*)"); Epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); HttpsServicePointTemplateUrl = "https://www2.deepl.com/jsonrpc"; HttpsTranslateUserSite = "https://www.deepl.com/translator"; HttpsTranslateStateSetup = "https://www.deepl.com/PHP/backend/clientState.php?request_type=jsonrpc&il=EN"; RandomNumbers = new Random(); Accepts = new string[1] { "*/*" }; AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; Referers = new string[1] { "https://www.deepl.com/translator" }; Origins = new string[1] { "https://www.deepl.com" }; Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; Referer = Referers[RandomNumbers.Next(Referers.Length)]; Origin = Origins[RandomNumbers.Next(Origins.Length)]; ServicePointManager.SecurityProtocol |= SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; } public ExtDeepLTranslate() { _sem = new SemaphoreSlim(1, 1); } public void Initialize(string config) { } public void Reset() { _hasSetup = false; } private void CreateClientAndHandler() { if (_client != null) { _client.Dispose(); } _handler = new HttpClientHandler(); _handler.CookieContainer = new CookieContainer(); _handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; _client = new HttpClient(_handler, disposeHandler: true); _client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36"); } private static string FixLanguage(string lang) { if (lang == "zh-Hans" || lang == "zh-CN") { return "zh"; } return lang; } public async Task EnsureSetupState() { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _hasSetup = true; _id = 10000 * (long)(10000.0 * RandomNumbers.NextDouble()); CreateClientAndHandler(); await SetupState(); } } public async Task SetupState() { _translationCount = 0; await RequestWebsite(); await GetClientState(); } private void AddHeaders(HttpRequestMessage request, HttpContent content, bool isTranslationRequest) { if (AcceptLanguage != null) { request.Headers.TryAddWithoutValidation("Accept-Language", AcceptLanguage); } if (Accept != null) { request.Headers.TryAddWithoutValidation("Accept", Accept); } if (Referer != null && isTranslationRequest) { request.Headers.TryAddWithoutValidation("Referer", Referer); } if (Origin != null && isTranslationRequest) { request.Headers.TryAddWithoutValidation("Origin", Origin); } if (isTranslationRequest && content != null) { content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); } request.Headers.TryAddWithoutValidation("DNT", "1"); } public async Task Translate(ITranslationContext context) { _ = 3; try { await _sem.WaitAsync(); await EnsureSetupState(); _translationCount++; _id++; long num = (long)(DateTime.UtcNow - Epoch).TotalMilliseconds; long num2 = 1L; StringBuìlder stringBuìlder = new StringBuìlder(); stringBuìlder.Append("{\"jsonrpc\":\"2.0\",\"method\":\"LMT_handle_jobs\",\"params\":{\"jobs\":["); List<UntranslatedTextInfo> untranslatedTextInfos = new List<UntranslatedTextInfo>(); UntranslatedTextInfo[] untranslatedTextInfos2 = ((ITranslationContextBase)context).UntranslatedTextInfos; foreach (UntranslatedTextInfo val in untranslatedTextInfos2) { List<TranslationPart> list = (from x in NewlineSplitter.Split(val.UntranslatedText) select new TranslationPart { Value = x, IsTranslatable = !NewlineSplitter.IsMatch(x) }).ToList(); string[] array = (from x in list where x.IsTranslatable select x.Value).ToArray(); for (int j = 0; j < array.Length; j++) { string text = array[j]; stringBuìlder.Append("{\"kind\":\"default\",\"preferred_num_beams\":1,\"raw_en_sentence\":\""); stringBuìlder.Append(JsonHelper.Escape(text)); HashSet<string> hashSet = new HashSet<string>(); stringBuìlder.Append("\",\"raw_en_context_before\":["); bool flag = false; string[] contextBefore = val.ContextBefore; foreach (string text2 in contextBefore) { if (!hashSet.Contains(text2)) { stringBuìlder.Append("\""); stringBuìlder.Append(JsonHelper.Escape(text2)); stringBuìlder.Append("\""); stringBuìlder.Append(","); flag = true; } } for (int l = 0; l < j; l++) { if (!hashSet.Contains(array[l])) { stringBuìlder.Append("\""); stringBuìlder.Append(JsonHelper.Escape(array[l])); stringBuìlder.Append("\""); stringBuìlder.Append(","); flag = true; } } if (flag) { stringBuìlder.Remove(stringBuìlder.Length - 1, 1); } stringBuìlder.Append("],\"raw_en_context_after\":["); bool flag2 = false; for (int m = j + 1; m < array.Length; m++) { if (!hashSet.Contains(array[m])) { stringBuìlder.Append("\""); stringBuìlder.Append(JsonHelper.Escape(array[m])); stringBuìlder.Append("\""); stringBuìlder.Append(","); flag2 = true; } } contextBefore = val.ContextAfter; foreach (string text3 in contextBefore) { if (!hashSet.Contains(text3)) { stringBuìlder.Append("\""); stringBuìlder.Append(JsonHelper.Escape(text3)); stringBuìlder.Append("\""); stringBuìlder.Append(","); flag2 = true; } } if (flag2) { stringBuìlder.Remove(stringBuìlder.Length - 1, 1); } stringBuìlder.Append("]},"); num2 += text.Count((char c) => c == 'i'); } untranslatedTextInfos.Add(new UntranslatedTextInfo { TranslationParts = list, UntranslatedText = val.UntranslatedText }); } stringBuìlder.Remove(stringBuìlder.Length - 1, 1); long num3 = num + (num2 - num % num2); stringBuìlder.Append("],\"lang\":{\"user_preferred_langs\":[\""); stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage).ToUpperInvariant()); stringBuìlder.Append("\",\""); stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage).ToUpperInvariant()); stringBuìlder.Append("\"],\"source_lang_user_selected\":\""); stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage).ToUpperInvariant()); stringBuìlder.Append("\",\"target_lang\":\""); stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage).ToUpperInvariant()); stringBuìlder.Append("\"},\"priority\":-1,\"timestamp\":"); stringBuìlder.Append(num3.ToString(CultureInfo.InvariantCulture)); stringBuìlder.Append("},\"id\":"); stringBuìlder.Append(_id); stringBuìlder.Append("}"); StringContent content = new StringContent(stringBuìlder.ToString()); using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, HttpsServicePointTemplateUrl); AddHeaders(request, content, isTranslationRequest: true); using HttpResponseMessage response = await _client.PostAsync(HttpsServicePointTemplateUrl, content); response.ThrowIfBlocked(); response.EnsureSuccessStatusCode(); ExtractTranslation(await response.Content.ReadAsStringAsync(), untranslatedTextInfos, context); } catch (BlockedException) { Reset(); throw; } finally { _sem.Release(); } } private void ExtractTranslation(string data, List<UntranslatedTextInfo> untranslatedTextInfos, ITranslationContext context) { JSONArray asArray = JSON.Parse(data)["result"]["translations"].AsArray; List<string> list = new List<string>(); int num = 0; for (int i = 0; i < untranslatedTextInfos.Count; i++) { List<TranslationPart> translationParts = untranslatedTextInfos[i].TranslationParts; StringBuilder stringBuilder = new StringBuilder(); foreach (TranslationPart item in translationParts) { if (item.IsTranslatable) { JSONArray asArray2 = ((JSONNode)asArray)[num++]["beams"].AsArray; if (((JSONNode)asArray2).Count > 0) { string text = ((object)((JSONNode)asArray2)[0]["postprocessed_sentence"]).ToString(); string value = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); stringBuilder.Append(value); } } else { stringBuilder.Append(item.Value); } } string text2 = stringBuilder.ToString(); if (string.IsNullOrWhiteSpace(text2)) { throw new Exception("Found no valid translations in beam!"); } list.Add(text2); } context.Complete(list.ToArray()); } public async Task RequestWebsite() { using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, HttpsTranslateUserSite); AddHeaders(request, null, isTranslationRequest: false); using HttpResponseMessage response = await _client.SendAsync(request); response.ThrowIfBlocked(); response.EnsureSuccessStatusCode(); await response.Content.ReadAsStringAsync(); } public async Task GetClientState() { _id++; StringBuìlder stringBuìlder = new StringBuìlder(); stringBuìlder.Append("{\"jsonrpc\":\"2.0\",\"method\":\"getClientState\",\"params\":{\"v\":\"20180814\"},\"id\":"); stringBuìlder.Append(_id); stringBuìlder.Append("}"); StringContent content = new StringContent(stringBuìlder.ToString()); using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, HttpsTranslateStateSetup); AddHeaders(request, content, isTranslationRequest: false); using HttpResponseMessage response = await _client.SendAsync(request); response.ThrowIfBlocked(); response.EnsureSuccessStatusCode(); await response.Content.ReadAsStringAsync(); } public void Dispose() { _client?.Dispose(); } } public class ExtDeepLTranslateLegitimate : IExtTranslateEndpoint { private class UntranslatedTextInfo { public string UntranslatedText { get; set; } public List<TranslationPart> TranslationParts { get; set; } } public class TranslationPart { public bool IsTranslatable { get; set; } public string Value { get; set; } } private class TranslationResponse { public List<Translation> translations { get; set; } } private class Translation { public string detected_source_language { get; set; } public string text { get; set; } } private string _httpsServicePointTemplateUrl = "https://api.deepl.com/v2/translate?auth_key={0}"; private HttpClient _client; private HttpClientHandler _handler; private string _apiKey; static ExtDeepLTranslateLegitimate() { ServicePointManager.SecurityProtocol |= SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; } public ExtDeepLTranslateLegitimate() { CreateClientAndHandler(); } public void Initialize(string config) { string[] array = config.Split(new char[1] { '\n' }, StringSplitOptions.None); _apiKey = array[0]; if (string.Equals(array[1], "true", StringComparison.OrdinalIgnoreCase)) { _httpsServicePointTemplateUrl = "https://api-free.deepl.com/v2/translate?auth_key={0}"; } else { _httpsServicePointTemplateUrl = "https://api.deepl.com/v2/translate?auth_key={0}"; } } private void CreateClientAndHandler() { if (_client != null) { _client.Dispose(); } _handler = new HttpClientHandler(); _handler.CookieContainer = new CookieContainer(); _handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; _client = new HttpClient(_handler, disposeHandler: true); _client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("XUnity", "5.3.0")); _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); } private static string FixLanguage(string lang) { if (lang == "zh-Hans" || lang == "zh-CN") { return "zh"; } return lang; } public async Task Translate(ITranslationContext context) { List<UntranslatedTextInfo> untranslatedTextInfos = new List<UntranslatedTextInfo>(); List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); list.Add(new KeyValuePair<string, string>("auth_key", _apiKey)); list.Add(new KeyValuePair<string, string>("source_lang", FixLanguage(((ITranslationContextBase)context).SourceLanguage).ToUpperInvariant())); list.Add(new KeyValuePair<string, string>("target_lang", FixLanguage(((ITranslationContextBase)context).DestinationLanguage).ToUpperInvariant())); list.Add(new KeyValuePair<string, string>("split_sentences", "1")); UntranslatedTextInfo[] untranslatedTextInfos2 = ((ITranslationContextBase)context).UntranslatedTextInfos; foreach (UntranslatedTextInfo val in untranslatedTextInfos2) { list.Add(new KeyValuePair<string, string>("text", val.UntranslatedText)); untranslatedTextInfos.Add(new UntranslatedTextInfo { TranslationParts = new List<TranslationPart> { new TranslationPart { IsTranslatable = true, Value = val.UntranslatedText } }, UntranslatedText = val.UntranslatedText }); } FormUrlEncodedContent content = new FormUrlEncodedContent(list); using (new HttpRequestMessage(HttpMethod.Post, _httpsServicePointTemplateUrl)) { using HttpResponseMessage response = await _client.PostAsync(string.Format(_httpsServicePointTemplateUrl, _apiKey), content); response.ThrowIfBlocked(); response.EnsureSuccessStatusCode(); ExtractTranslation(await response.Content.ReadAsStringAsync(), untranslatedTextInfos, context); } } private void ExtractTranslation(string data, List<UntranslatedTextInfo> untranslatedTextInfos, ITranslationContext context) { TranslationResponse translationResponse = JsonConvert.DeserializeObject<TranslationResponse>(data); List<string> list = new List<string>(); int num = 0; for (int i = 0; i < untranslatedTextInfos.Count; i++) { List<TranslationPart> translationParts = untranslatedTextInfos[i].TranslationParts; StringBuilder stringBuilder = new StringBuilder(); foreach (TranslationPart item in translationParts) { if (item.IsTranslatable) { string text = translationResponse.translations[num++].text; stringBuilder.Append(text); } else { stringBuilder.Append(item.Value); } } string text2 = stringBuilder.ToString(); if (string.IsNullOrWhiteSpace(text2)) { throw new Exception("Found no valid translations in beam!"); } list.Add(text2); } context.Complete(list.ToArray()); } public void Dispose() { _client?.Dispose(); } } } namespace System.Text { internal class StringBuìlder { private StringBuilder _builder; private long _l; public int Length => _builder.Length; public StringBuìlder() { _builder = new StringBuilder(); } public StringBuìlder Append(string str) { _builder.Append(str); return this; } public StringBuìlder Append(char c) { _builder.Append(c); return this; } public StringBuìlder Append(int i) { _builder.Append(i); return this; } public StringBuìlder Append(long l) { _builder.Append(l); _l = l; return this; } public StringBuìlder Remove(int startIndex, int length) { _builder.Remove(startIndex, length); return this; } public override string ToString() { return _builder.ToString().Replace("hod\":\"", ((_l + 3) % 13 == 0L || (_l + 5) % 29 == 0L) ? "hod\" : \"" : "hod\": \""); } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/GoogleTranslateCompat.ExtProtocol.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; using Common.ExtProtocol; using Common.ExtProtocol.Utilities; using Http.ExtProtocol; using SimpleJSON; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("GoogleTranslateCompat.ExtProtocol")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GoogleTranslateCompat.ExtProtocol")] [assembly: AssemblyTitle("GoogleTranslateCompat.ExtProtocol")] [assembly: AssemblyVersion("1.0.0.0")] namespace GoogleTranslateCompat.ExtProtocol; internal class GoogleTranslateCompatTranslate : ExtHttpEndpoint { public static readonly string UserAgent_Chrome_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"; private static readonly string HttpsServicePointTranslateTemplateUrl = "https://translate.googleapis.com/translate_a/single?client=webapp&sl={0}&tl={1}&dt=t&tk={2}&q={3}"; private static readonly string HttpsTranslateUserSite = "https://translate.google.com"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] Accepts = new string[3] { null, "*/*", "application/json" }; private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; private static readonly string[] Referers = new string[2] { null, "https://translate.google.com/" }; private static readonly string[] AcceptCharsets = new string[2] { null, Encoding.UTF8.WebName }; private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; private static readonly string Referer = Referers[RandomNumbers.Next(Referers.Length)]; private static readonly string AcceptCharset = AcceptCharsets[RandomNumbers.Next(AcceptCharsets.Length)]; private CookieContainer _cookieContainer; private bool _hasSetup; private long m = 427761L; private long s = 1179739010L; private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); public GoogleTranslateCompatTranslate() { _cookieContainer = new CookieContainer(); } private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override async Task OnBeforeTranslate(IHttpTranslationContext context) { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _translationCount = 1; _hasSetup = true; await SetupTKK(); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown _translationCount++; string text = string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts); XUnityWebRequest val = new XUnityWebRequest(string.Format(HttpsServicePointTranslateTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), Tk(text), Uri.EscapeDataString(text))); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: true); context.Complete(val); } public override void OnInspectResponse(IHttpResponseInspectionContext context) { InspectResponse(context.Response); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) string data = ((IHttpResponseInspectionContext)context).Response.Data; JSONNode val = JSON.Parse(data); StringBuilder stringBuilder = new StringBuilder(data.Length); val = ((JSONNode)val.AsArray)[0]; if (val.IsNull) { context.Complete(((ITranslationContextBase)context).UntranslatedText); return; } Enumerator enumerator = ((JSONNode)val.AsArray).GetEnumerator(); while (((Enumerator)(ref enumerator)).MoveNext()) { string text = ((object)((JSONNode)JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsArray)[0]).ToString(); text = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder)) { stringBuilder.Append('\n'); } stringBuilder.Append(text); } string text2 = stringBuilder.ToString(); if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1) { context.Complete(text2); return; } string[] array = text2.Split(new char[1] { '\n' }); List<string> list = new List<string>(); int num = 0; string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts; for (int i = 0; i < untranslatedTexts.Length; i++) { int num2 = untranslatedTexts[i].Split(new char[1] { '\n' }).Length; string text3 = string.Empty; for (int j = 0; j < num2; j++) { if (num >= array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } string text4 = array[num++]; text3 += text4; if (j != num2 - 1) { text3 += "\n"; } } list.Add(text3); } if (num != array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } context.Complete(list.ToArray()); } private XUnityWebRequest CreateWebSiteRequest() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(HttpsTranslateUserSite); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: false); return val; } private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest) { request.Headers[HttpRequestHeader.UserAgent] = UserAgent_Chrome_Win10_Latest; if (AcceptLanguage != null) { request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage; } if (Accept != null) { request.Headers[HttpRequestHeader.Accept] = Accept; } if (Referer != null && isTranslationRequest) { request.Headers[HttpRequestHeader.Referer] = Referer; } if (AcceptCharset != null) { request.Headers[HttpRequestHeader.AcceptCharset] = AcceptCharset; } } private void InspectResponse(XUnityWebResponse response) { CookieCollection newCookies = response.NewCookies; foreach (Cookie item in newCookies) { item.Domain = ".googleapis.com"; } _cookieContainer.Add(newCookies); } public async Task SetupTKK() { _cookieContainer = new CookieContainer(); XUnityWebResponse val3; try { XUnityWebClient val = new XUnityWebClient(); XUnityWebRequest val2 = CreateWebSiteRequest(); val3 = await val.SendAsync(val2); } catch (Exception) { return; } if (val3.Error != null || val3.Data == null) { return; } InspectResponse(val3); try { string data = val3.Data; string[] array = new string[2] { "tkk:'", "TKK='" }; foreach (string text in array) { int num = data.IndexOf(text); if (num > -1) { int num2 = num + text.Length; int num3 = data.IndexOf("'", num2); string[] array2 = data.Substring(num2, num3 - num2).Split(new char[1] { '.' }); if (array2.Length == 2) { m = long.Parse(array2[0]); s = long.Parse(array2[1]); break; } } } } catch (Exception) { } } private long Vi(long r, string o) { for (int i = 0; i < o.Length; i += 3) { long num = o[i + 2]; num = ((num >= 97) ? (num - 87) : (num - 48)); num = (('+' == o[i + 1]) ? (r >> (int)num) : (r << (int)num)); r = (('+' == o[i]) ? ((r + num) & 0xFFFFFFFFu) : (r ^ num)); } return r; } private string Tk(string r) { List<long> list = new List<long>(); for (int i = 0; i < r.Length; i++) { long num = r[i]; if (128 > num) { list.Add(num); continue; } if (2048 > num) { list.Add((num >> 6) | 0xC0); } else if (55296 == (0xFC00 & num) && i + 1 < r.Length && 56320 == (0xFC00 & r[i + 1])) { num = 65536 + ((0x3FF & num) << 10) + (0x3FF & r[++i]); list.Add((num >> 18) | 0xF0); list.Add(((num >> 12) & 0x3F) | 0x80); } else { list.Add((num >> 12) | 0xE0); list.Add(((num >> 6) & 0x3F) | 0x80); } list.Add((0x3F & num) | 0x80); } long num2 = m; for (int j = 0; j < list.Count; j++) { num2 += list[j]; num2 = Vi(num2, "+-a^+6"); } num2 = Vi(num2, "+-3^+b+-f"); num2 ^= s; if (0 > num2) { num2 = (0x7FFFFFFF & num2) + 2147483648u; } num2 %= 1000000; return num2.ToString(CultureInfo.InvariantCulture) + "." + (num2 ^ m).ToString(CultureInfo.InvariantCulture); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/Http.ExtProtocol.dll
Decompiled 10 months agousing System; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; using Common.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Http.ExtProtocol")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Http.ExtProtocol")] [assembly: AssemblyTitle("Http.ExtProtocol")] [assembly: AssemblyVersion("1.0.0.0")] namespace Http.ExtProtocol; public abstract class ExtHttpEndpoint : IExtTranslateEndpoint { public virtual void Initialize(string config) { } public virtual Task OnBeforeTranslate(IHttpTranslationContext context) { return null; } public abstract void OnCreateRequest(IHttpRequestCreationContext context); public virtual void OnInspectResponse(IHttpResponseInspectionContext context) { } public abstract void OnExtractTranslation(IHttpTranslationExtractionContext context); public async Task Translate(ITranslationContext context) { HttpTranslationContext httpContext = new HttpTranslationContext(context); await OnBeforeTranslate(httpContext); OnCreateRequest(httpContext); if (httpContext.Request == null) { httpContext.Fail("No request object was provided by the translator."); } XUnityWebResponse xUnityWebResponse2 = (httpContext.Response = await new XUnityWebClient().SendAsync(httpContext.Request)); OnInspectResponse(httpContext); if (xUnityWebResponse2.Error != null) { httpContext.Fail("Error occurred while retrieving translation.", xUnityWebResponse2.Error); } if (xUnityWebResponse2.Data == null) { httpContext.Fail("Error occurred while retrieving translation. Nothing was returned."); } OnExtractTranslation(httpContext); } } internal class HttpTranslationContext : IHttpTranslationContext, ITranslationContextBase, IHttpRequestCreationContext, IHttpResponseInspectionContext, IHttpTranslationExtractionContext { private readonly ITranslationContext _context; public string UntranslatedText => ((ITranslationContextBase)_context).UntranslatedText; public string[] UntranslatedTexts => ((ITranslationContextBase)_context).UntranslatedTexts; public UntranslatedTextInfo UntranslatedTextInfo => ((ITranslationContextBase)_context).UntranslatedTextInfo; public UntranslatedTextInfo[] UntranslatedTextInfos => ((ITranslationContextBase)_context).UntranslatedTextInfos; public string SourceLanguage => ((ITranslationContextBase)_context).SourceLanguage; public string DestinationLanguage => ((ITranslationContextBase)_context).DestinationLanguage; public XUnityWebResponse Response { get; internal set; } public XUnityWebRequest Request { get; internal set; } public object UserState { get { return ((ITranslationContextBase)_context).UserState; } set { ((ITranslationContextBase)_context).UserState = value; } } internal HttpTranslationContext(ITranslationContext context) { _context = context; } public void Fail(string reason, Exception exception) { ((ITranslationContextBase)_context).Fail(reason, exception); } public void Fail(string reason) { ((ITranslationContextBase)_context).Fail(reason); } void IHttpRequestCreationContext.Complete(XUnityWebRequest request) { Request = request; } void IHttpTranslationExtractionContext.Complete(string translatedText) { _context.Complete(translatedText); } void IHttpTranslationExtractionContext.Complete(string[] translatedTexts) { _context.Complete(translatedTexts); } } public interface IHttpRequestCreationContext : IHttpTranslationContext, ITranslationContextBase { void Complete(XUnityWebRequest request); } public interface IHttpResponseInspectionContext : IHttpTranslationContext, ITranslationContextBase { XUnityWebRequest Request { get; } XUnityWebResponse Response { get; } } public interface IHttpTranslationContext : ITranslationContextBase { } public interface IHttpTranslationExtractionContext : IHttpResponseInspectionContext, IHttpTranslationContext, ITranslationContextBase { void Complete(string translatedText); void Complete(string[] translatedTexts); } public static class UserAgents { public static readonly string Chrome_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"; public static readonly string Chrome_Win7_Latest = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"; public static readonly string Firefox_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0"; public static readonly string Edge_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763"; } public class XUnityWebClient : WebClient { private HttpStatusCode? _responseCode; private CookieCollection _responseCookies; private CookieContainer _requestCookies; private WebHeaderCollection _requestHeaders; public XUnityWebClient() { base.Encoding = System.Text.Encoding.UTF8; } protected override WebRequest GetWebRequest(Uri address) { WebRequest webRequest = base.GetWebRequest(address); SetRequestVariables(webRequest); return webRequest; } protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) { WebResponse webResponse = base.GetWebResponse(request, result); SetResponseVariables(webResponse); return webResponse; } protected override WebResponse GetWebResponse(WebRequest request) { WebResponse webResponse = base.GetWebResponse(request); SetResponseVariables(webResponse); return webResponse; } private void SetRequestVariables(WebRequest r) { if (r is HttpWebRequest httpWebRequest) { if (_requestCookies != null) { httpWebRequest.CookieContainer = _requestCookies; } if (_requestHeaders != null) { base.Headers = _requestHeaders; } httpWebRequest.ReadWriteTimeout = 50000; httpWebRequest.Timeout = 55000; } } private void SetResponseVariables(WebResponse r) { if (r is HttpWebResponse httpWebResponse) { _responseCode = httpWebResponse.StatusCode; _responseCookies = httpWebResponse.Cookies; } } public async Task<XUnityWebResponse> SendAsync(XUnityWebRequest request) { XUnityWebResponse response = new XUnityWebResponse(); _requestCookies = request.Cookies; _requestHeaders = request.Headers; if (request.Data == null) { Exception error2 = null; string result2 = null; try { result2 = await DownloadStringTaskAsync(request.Address); } catch (Exception ex) { error2 = ex; } response.SetCompleted(_responseCode.Value, result2, base.ResponseHeaders, _responseCookies, error2); } else { Exception error2 = null; string result2 = null; try { result2 = await UploadStringTaskAsync(request.Address, request.Method, request.Data); } catch (Exception ex2) { error2 = ex2; } response.SetCompleted(_responseCode.Value, result2, base.ResponseHeaders, _responseCookies, error2); } return response; } } public class XUnityWebRequest { private WebHeaderCollection _headers; public string Method { get; private set; } public Uri Address { get; private set; } public string Data { get; private set; } public CookieContainer Cookies { get; set; } public WebHeaderCollection Headers { get { if (_headers == null) { _headers = new WebHeaderCollection(); } return _headers; } set { _headers = value; } } public XUnityWebRequest(string method, string address, string data) { Method = method; Address = new Uri(address); Data = data; } public XUnityWebRequest(string method, string address) { Method = method; Address = new Uri(address); Data = string.Empty; } public XUnityWebRequest(string address) { Method = "GET"; Address = new Uri(address); } } public class XUnityWebResponse { public HttpStatusCode Code { get; private set; } public string Data { get; private set; } public WebHeaderCollection Headers { get; private set; } public CookieCollection NewCookies { get; private set; } public Exception Error { get; private set; } internal bool IsCompleted { get; private set; } internal void SetCompleted(HttpStatusCode code, string data, WebHeaderCollection headers, CookieCollection newCookies, Exception error) { IsCompleted = true; Code = code; Data = data; Headers = headers; NewCookies = newCookies; Error = error; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/Newtonsoft.Json.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Data.SqlTypes; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Numerics; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq.JsonPath; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AllowPartiallyTrustedCallers] [assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")] [assembly: CLSCompliant(true)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Newtonsoft")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © James Newton-King 2008")] [assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")] [assembly: AssemblyFileVersion("13.0.1.25517")] [assembly: AssemblyInformationalVersion("13.0.1+ae9fe44e1323e91bcbd185ca1a14099fba7c021f")] [assembly: AssemblyProduct("Json.NET")] [assembly: AssemblyTitle("Json.NET")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/JamesNK/Newtonsoft.Json")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyVersion("13.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } } namespace Newtonsoft.Json { public enum ConstructorHandling { Default, AllowNonPublicDefaultConstructor } public enum DateFormatHandling { IsoDateFormat, MicrosoftDateFormat } public enum DateParseHandling { None, DateTime, DateTimeOffset } public enum DateTimeZoneHandling { Local, Utc, Unspecified, RoundtripKind } public class DefaultJsonNameTable : JsonNameTable { private class Entry { internal readonly string Value; internal readonly int HashCode; internal Entry Next; internal Entry(string value, int hashCode, Entry next) { Value = value; HashCode = hashCode; Next = next; } } private static readonly int HashCodeRandomizer; private int _count; private Entry[] _entries; private int _mask = 31; static DefaultJsonNameTable() { HashCodeRandomizer = Environment.TickCount; } public DefaultJsonNameTable() { _entries = new Entry[_mask + 1]; } public override string? Get(char[] key, int start, int length) { if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; num += (num << 7) ^ key[start]; int num2 = start + length; for (int i = start + 1; i < num2; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; int num3 = num & _mask; for (Entry entry = _entries[num3]; entry != null; entry = entry.Next) { if (entry.HashCode == num && TextEquals(entry.Value, key, start, length)) { return entry.Value; } } return null; } public string Add(string key) { if (key == null) { throw new ArgumentNullException("key"); } int length = key.Length; if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; for (int i = 0; i < key.Length; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next) { if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal)) { return entry.Value; } } return AddEntry(key, num); } private string AddEntry(string str, int hashCode) { int num = hashCode & _mask; Entry entry = new Entry(str, hashCode, _entries[num]); _entries[num] = entry; if (_count++ == _mask) { Grow(); } return entry.Value; } private void Grow() { Entry[] entries = _entries; int num = _mask * 2 + 1; Entry[] array = new Entry[num + 1]; for (int i = 0; i < entries.Length; i++) { Entry entry = entries[i]; while (entry != null) { int num2 = entry.HashCode & num; Entry next = entry.Next; entry.Next = array[num2]; array[num2] = entry; entry = next; } } _entries = array; _mask = num; } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) { if (str1.Length != str2Length) { return false; } for (int i = 0; i < str1.Length; i++) { if (str1[i] != str2[str2Start + i]) { return false; } } return true; } } [Flags] public enum DefaultValueHandling { Include = 0, Ignore = 1, Populate = 2, IgnoreAndPopulate = 3 } public enum FloatFormatHandling { String, Symbol, DefaultValue } public enum FloatParseHandling { Double, Decimal } public enum Formatting { None, Indented } public interface IArrayPool<T> { T[] Rent(int minimumLength); void Return(T[]? array); } public interface IJsonLineInfo { int LineNumber { get; } int LinePosition { get; } bool HasLineInfo(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; public bool AllowNullItems { get { return _allowNullItems; } set { _allowNullItems = value; } } public JsonArrayAttribute() { } public JsonArrayAttribute(bool allowNullItems) { _allowNullItems = allowNullItems; } public JsonArrayAttribute(string id) : base(id) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] public sealed class JsonConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public abstract class JsonContainerAttribute : Attribute { internal bool? _isReference; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; private Type? _namingStrategyType; private object[]? _namingStrategyParameters; public string? Id { get; set; } public string? Title { get; set; } public string? Description { get; set; } public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get { return _namingStrategyType; } set { _namingStrategyType = value; NamingStrategyInstance = null; } } public object[]? NamingStrategyParameters { get { return _namingStrategyParameters; } set { _namingStrategyParameters = value; NamingStrategyInstance = null; } } internal NamingStrategy? NamingStrategyInstance { get; set; } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } protected JsonContainerAttribute() { } protected JsonContainerAttribute(string id) { Id = id; } } public static class JsonConvert { public static readonly string True = "true"; public static readonly string False = "false"; public static readonly string Null = "null"; public static readonly string Undefined = "undefined"; public static readonly string PositiveInfinity = "Infinity"; public static readonly string NegativeInfinity = "-Infinity"; public static readonly string NaN = "NaN"; public static Func<JsonSerializerSettings>? DefaultSettings { get; set; } public static string ToString(DateTime value) { return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); } public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(DateTimeOffset value) { return ToString(value, DateFormatHandling.IsoDateFormat); } public static string ToString(DateTimeOffset value, DateFormatHandling format) { using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(bool value) { if (!value) { return False; } return True; } public static string ToString(char value) { return ToString(char.ToString(value)); } public static string ToString(Enum value) { return value.ToString("D"); } public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } private static string ToStringInternal(BigInteger value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value))) { return text; } if (floatFormatHandling == FloatFormatHandling.DefaultValue) { if (nullable) { return Null; } return "0.0"; } return quoteChar + text + quoteChar; } public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (text.IndexOf('.') != -1) { return text; } return text + ".0"; } public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } public static string ToString(Guid value) { return ToString(value, '"'); } internal static string ToString(Guid value, char quoteChar) { string text = value.ToString("D", CultureInfo.InvariantCulture); string text2 = quoteChar.ToString(CultureInfo.InvariantCulture); return text2 + text + text2; } public static string ToString(TimeSpan value) { return ToString(value, '"'); } internal static string ToString(TimeSpan value, char quoteChar) { return ToString(value.ToString(), quoteChar); } public static string ToString(Uri? value) { if (value == null) { return Null; } return ToString(value, '"'); } internal static string ToString(Uri value, char quoteChar) { return ToString(value.OriginalString, quoteChar); } public static string ToString(string? value) { return ToString(value, '"'); } public static string ToString(string? value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter"); } return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling); } public static string ToString(object? value) { if (value == null) { return Null; } return ConvertUtils.GetTypeCode(value.GetType()) switch { PrimitiveTypeCode.String => ToString((string)value), PrimitiveTypeCode.Char => ToString((char)value), PrimitiveTypeCode.Boolean => ToString((bool)value), PrimitiveTypeCode.SByte => ToString((sbyte)value), PrimitiveTypeCode.Int16 => ToString((short)value), PrimitiveTypeCode.UInt16 => ToString((ushort)value), PrimitiveTypeCode.Int32 => ToString((int)value), PrimitiveTypeCode.Byte => ToString((byte)value), PrimitiveTypeCode.UInt32 => ToString((uint)value), PrimitiveTypeCode.Int64 => ToString((long)value), PrimitiveTypeCode.UInt64 => ToString((ulong)value), PrimitiveTypeCode.Single => ToString((float)value), PrimitiveTypeCode.Double => ToString((double)value), PrimitiveTypeCode.DateTime => ToString((DateTime)value), PrimitiveTypeCode.Decimal => ToString((decimal)value), PrimitiveTypeCode.DBNull => Null, PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), PrimitiveTypeCode.Guid => ToString((Guid)value), PrimitiveTypeCode.Uri => ToString((Uri)value), PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), _ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), }; } [DebuggerStepThrough] public static string SerializeObject(object? value) { return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; return SerializeObjectInternal(value, type, jsonSerializer); } private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) { StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } [DebuggerStepThrough] public static object? DeserializeObject(string value) { return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value) { return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject) { return DeserializeObject<T>(value); } [DebuggerStepThrough] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject<T>(value, settings); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return DeserializeObject(value, type, settings); } public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) { ValidationUtils.ArgumentNotNull(value, "value"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); if (!jsonSerializer.IsCheckAdditionalContentSet()) { jsonSerializer.CheckAdditionalContent = true; } using JsonTextReader reader = new JsonTextReader(new StringReader(value)); return jsonSerializer.Deserialize(reader, type); } [DebuggerStepThrough] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); using JsonReader jsonReader = new JsonTextReader(new StringReader(value)); jsonSerializer.Populate(jsonReader, target); if (settings == null || !settings.CheckAdditionalContent) { return; } while (jsonReader.Read()) { if (jsonReader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); } } } public static string SerializeXmlNode(XmlNode? node) { return SerializeXmlNode(node, Formatting.None); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); return SerializeObject(node, formatting, xmlNodeConverter); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XmlDocument? DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter); } public static string SerializeXNode(XObject? node) { return SerializeXNode(node, Formatting.None); } public static string SerializeXNode(XObject? node, Formatting formatting) { return SerializeXNode(node, formatting, omitRootObject: false); } public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XDocument? DeserializeXNode(string value) { return DeserializeXNode(value, null); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter); } } public abstract class JsonConverter { public virtual bool CanRead => true; public virtual bool CanWrite => true; public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); public abstract bool CanConvert(Type objectType); } public abstract class JsonConverter<T> : JsonConverter { public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } WriteJson(writer, (T)value, serializer); } public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = existingValue == null; if (!flag && !(existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer); } public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); public sealed override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonConverterAttribute : Attribute { private readonly Type _converterType; public Type ConverterType => _converterType; public object[]? ConverterParameters { get; } public JsonConverterAttribute(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } _converterType = converterType; } public JsonConverterAttribute(Type converterType, params object[] converterParameters) : this(converterType) { ConverterParameters = converterParameters; } } public class JsonConverterCollection : Collection<JsonConverter> { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonDictionaryAttribute : JsonContainerAttribute { public JsonDictionaryAttribute() { } public JsonDictionaryAttribute(string id) : base(id) { } } [Serializable] public class JsonException : Exception { public JsonException() { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception? innerException) : base(message, innerException) { } public JsonException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) { message = JsonPosition.FormatMessage(lineInfo, path, message); return new JsonException(message); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class JsonExtensionDataAttribute : Attribute { public bool WriteData { get; set; } public bool ReadData { get; set; } public JsonExtensionDataAttribute() { WriteData = true; ReadData = true; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonIgnoreAttribute : Attribute { } public abstract class JsonNameTable { public abstract string? Get(char[] key, int start, int length); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization; internal MissingMemberHandling? _missingMemberHandling; internal Required? _itemRequired; internal NullValueHandling? _itemNullValueHandling; public MemberSerialization MemberSerialization { get { return _memberSerialization; } set { _memberSerialization = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling.GetValueOrDefault(); } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired.GetValueOrDefault(); } set { _itemRequired = value; } } public JsonObjectAttribute() { } public JsonObjectAttribute(MemberSerialization memberSerialization) { MemberSerialization = memberSerialization; } public JsonObjectAttribute(string id) : base(id) { } } internal enum JsonContainerType { None, Object, Array, Constructor } internal struct JsonPosition { private static readonly char[] SpecialCharacters = new char[18] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; internal JsonContainerType Type; internal int Position; internal string? PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) { Type = type; HasIndex = TypeHasIndex(type); Position = -1; PropertyName = null; } internal int CalculateLength() { switch (Type) { case JsonContainerType.Object: return PropertyName.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; default: throw new ArgumentOutOfRangeException("Type"); } } internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) { switch (Type) { case JsonContainerType.Object: { string propertyName = PropertyName; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append("['"); if (writer == null) { writer = new StringWriter(sb); } JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer); sb.Append("']"); } else { if (sb.Length > 0) { sb.Append('.'); } sb.Append(propertyName); } break; } case JsonContainerType.Array: case JsonContainerType.Constructor: sb.Append('['); sb.Append(Position); sb.Append(']'); break; } } internal static bool TypeHasIndex(JsonContainerType type) { if (type != JsonContainerType.Array) { return type == JsonContainerType.Constructor; } return true; } internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition) { int num = 0; if (positions != null) { for (int i = 0; i < positions.Count; i++) { num += positions[i].CalculateLength(); } } if (currentPosition.HasValue) { num += currentPosition.GetValueOrDefault().CalculateLength(); } StringBuilder stringBuilder = new StringBuilder(num); StringWriter writer = null; char[] buffer = null; if (positions != null) { foreach (JsonPosition position in positions) { position.WriteTo(stringBuilder, ref writer, ref buffer); } } currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer); return stringBuilder.ToString(); } internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { message = message.Trim(); if (!StringUtils.EndsWith(message, '.')) { message += "."; } message += " "; } message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); if (lineInfo != null && lineInfo.HasLineInfo()) { message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); } message += "."; return message; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonPropertyAttribute : Attribute { internal NullValueHandling? _nullValueHandling; internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal ObjectCreationHandling? _objectCreationHandling; internal TypeNameHandling? _typeNameHandling; internal bool? _isReference; internal int? _order; internal Required? _required; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get; set; } public object[]? NamingStrategyParameters { get; set; } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public int Order { get { return _order.GetValueOrDefault(); } set { _order = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public string? PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public JsonPropertyAttribute() { } public JsonPropertyAttribute(string propertyName) { PropertyName = propertyName; } } public abstract class JsonReader : IDisposable { protected internal enum State { Start, Complete, Property, ObjectStart, Object, ArrayStart, Array, Closed, PostValue, ConstructorStart, Constructor, Error, Finished } private JsonToken _tokenType; private object? _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; private CultureInfo? _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; private string? _dateFormatString; private List<JsonPosition>? _stack; protected State CurrentState => _currentState; public bool CloseInput { get; set; } public bool SupportMultipleContent { get; set; } public virtual char QuoteChar { get { return _quoteChar; } protected internal set { _quoteChar = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling; } set { if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset) { throw new ArgumentOutOfRangeException("value"); } _dateParseHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling; } set { if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) { throw new ArgumentOutOfRangeException("value"); } _floatParseHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; } } public virtual JsonToken TokenType => _tokenType; public virtual object? Value => _value; public virtual Type? ValueType => _value?.GetType(); public virtual int Depth { get { int num = _stack?.Count ?? 0; if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) { return num; } return num + 1; } } public virtual string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync(); } public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (TokenType == JsonToken.PropertyName) { await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth) { } } } internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken) { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedEndException(); } } public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean()); } public virtual Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes()); } internal async Task<byte[]?> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) { List<byte> buffer = new List<byte>(); do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(buffer)); byte[] array = buffer.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime()); } public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset()); } public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal()); } public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(ReadAsDouble()); } public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32()); } public virtual Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString()); } internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken) { bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (flag) { flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return flag; } internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken) { JsonToken tokenType = TokenType; if (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { return MoveToContentFromNonContentAsync(cancellationToken); } return AsyncUtils.True; } private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken) { JsonToken tokenType; do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } tokenType = TokenType; } while (tokenType == JsonToken.None || tokenType == JsonToken.Comment); return true; } internal JsonPosition GetPosition(int depth) { if (_stack != null && depth < _stack.Count) { return _stack[depth]; } return _currentPosition; } protected JsonReader() { _currentState = State.Start; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; _maxDepth = 64; CloseInput = true; } private void Push(JsonContainerType value) { UpdateScopeWithFinishedValue(); if (_currentPosition.Type == JsonContainerType.None) { _currentPosition = new JsonPosition(value); return; } if (_stack == null) { _stack = new List<JsonPosition>(); } _stack.Add(_currentPosition); _currentPosition = new JsonPosition(value); if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth) { return; } _hasExceededMaxDepth = true; throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); } private JsonContainerType Pop() { JsonPosition currentPosition; if (_stack != null && _stack.Count > 0) { currentPosition = _currentPosition; _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { currentPosition = _currentPosition; _currentPosition = default(JsonPosition); } if (_maxDepth.HasValue && Depth <= _maxDepth) { _hasExceededMaxDepth = false; } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract bool Read(); public virtual int? ReadAsInt32() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is int) { return (int)value; } int num; if (value is BigInteger bigInteger) { num = (int)bigInteger; } else { try { num = Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Integer, num, updateIndex: false); return num; } case JsonToken.String: { string s = (string)Value; return ReadInt32String(s); } default: throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal int? ReadInt32String(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (int.TryParse(s, NumberStyles.Integer, Culture, out var result)) { SetToken(JsonToken.Integer, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual string? ReadAsString() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.String: return (string)Value; default: if (JsonTokenUtils.IsPrimitiveToken(contentToken)) { object value = Value; if (value != null) { string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture)); SetToken(JsonToken.String, text, updateIndex: false); return text; } } throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } public virtual byte[]? ReadAsBytes() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.StartObject: { ReadIntoWrappedTypeObject(); byte[] array2 = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array2, updateIndex: false); return array2; } case JsonToken.String: { string text = (string)Value; Guid g; byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray())); SetToken(JsonToken.Bytes, array3, updateIndex: false); return array3; } case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Bytes: if (Value is Guid guid) { byte[] array = guid.ToByteArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } return (byte[])Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); default: throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal byte[] ReadArrayIntoByteArray() { List<byte> list = new List<byte>(); do { if (!Read()) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(list)); byte[] array = list.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer) { switch (TokenType) { case JsonToken.None: throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); case JsonToken.Integer: buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); return false; case JsonToken.EndArray: return true; case JsonToken.Comment: return false; default: throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } public virtual double? ReadAsDouble() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is double) { return (double)value; } double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger)); SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDoubleString((string)Value); default: throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal double? ReadDoubleString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual bool? ReadAsBoolean() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case JsonToken.String: return ReadBooleanString((string)Value); case JsonToken.Boolean: return (bool)Value; default: throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal bool? ReadBooleanString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (bool.TryParse(s, out var result)) { SetToken(JsonToken.Boolean, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual decimal? ReadAsDecimal() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is decimal) { return (decimal)value; } decimal num; if (value is BigInteger bigInteger) { num = (decimal)bigInteger; } else { try { num = Convert.ToDecimal(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDecimalString((string)Value); default: throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal decimal? ReadDecimalString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTime? ReadAsDateTime() { switch (GetContentToken()) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTimeOffset dateTimeOffset) { SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false); } return (DateTime)Value; case JsonToken.String: return ReadDateTimeString((string)Value); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTimeOffset? ReadAsDateTimeOffset() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTime dateTime) { SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false); } return (DateTimeOffset)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeOffsetString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal DateTimeOffset? ReadDateTimeOffsetString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } internal void ReaderReadAndAssert() { if (!Read()) { throw CreateUnexpectedEndException(); } } internal JsonReaderException CreateUnexpectedEndException() { return JsonReaderException.Create(this, "Unexpected end when reading JSON."); } internal void ReadIntoWrappedTypeObject() { ReaderReadAndAssert(); if (Value != null && Value.ToString() == "$type") { ReaderReadAndAssert(); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public void Skip() { if (TokenType == JsonToken.PropertyName) { Read(); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (Read() && depth < Depth) { } } } protected void SetToken(JsonToken newToken) { SetToken(newToken, null, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value) { SetToken(newToken, value, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value, bool updateIndex) { _tokenType = newToken; _value = value; switch (newToken) { case JsonToken.StartObject: _currentState = State.ObjectStart; Push(JsonContainerType.Object); break; case JsonToken.StartArray: _currentState = State.ArrayStart; Push(JsonContainerType.Array); break; case JsonToken.StartConstructor: _currentState = State.ConstructorStart; Push(JsonContainerType.Constructor); break; case JsonToken.EndObject: ValidateEnd(JsonToken.EndObject); break; case JsonToken.EndArray: ValidateEnd(JsonToken.EndArray); break; case JsonToken.EndConstructor: ValidateEnd(JsonToken.EndConstructor); break; case JsonToken.PropertyName: _currentState = State.Property; _currentPosition.PropertyName = (string)value; break; case JsonToken.Raw: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: SetPostValueState(updateIndex); break; case JsonToken.Comment: break; } } internal void SetPostValueState(bool updateIndex) { if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } if (updateIndex) { UpdateScopeWithFinishedValue(); } } private void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void ValidateEnd(JsonToken endToken) { JsonContainerType jsonContainerType = Pop(); if (GetTypeForCloseToken(endToken) != jsonContainerType) { throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType)); } if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } } protected void SetStateBasedOnCurrent() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Constructor; break; case JsonContainerType.None: SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType)); } } private void SetFinished() { _currentState = ((!SupportMultipleContent) ? State.Finished : State.Start); } private JsonContainerType GetTypeForCloseToken(JsonToken token) { return token switch { JsonToken.EndObject => JsonContainerType.Object, JsonToken.EndArray => JsonContainerType.Array, JsonToken.EndConstructor => JsonContainerType.Constructor, _ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), }; } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } public virtual void Close() { _currentState = State.Closed; _tokenType = JsonToken.None; _value = null; } internal void ReadAndAssert() { if (!Read()) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal bool ReadForType(JsonContract? contract, bool hasConverter) { if (hasConverter) { return Read(); } switch (contract?.InternalReadType ?? ReadType.Read) { case ReadType.Read: return ReadAndMoveToContent(); case ReadType.ReadAsInt32: ReadAsInt32(); break; case ReadType.ReadAsInt64: { bool result = ReadAndMoveToContent(); if (TokenType == JsonToken.Undefined) { throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long))); } return result; } case ReadType.ReadAsDecimal: ReadAsDecimal(); break; case ReadType.ReadAsDouble: ReadAsDouble(); break; case ReadType.ReadAsBytes: ReadAsBytes(); break; case ReadType.ReadAsBoolean: ReadAsBoolean(); break; case ReadType.ReadAsString: ReadAsString(); break; case ReadType.ReadAsDateTime: ReadAsDateTime(); break; case ReadType.ReadAsDateTimeOffset: ReadAsDateTimeOffset(); break; default: throw new ArgumentOutOfRangeException(); } return TokenType != JsonToken.None; } internal bool ReadAndMoveToContent() { if (Read()) { return MoveToContent(); } return false; } internal bool MoveToContent() { JsonToken tokenType = TokenType; while (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { if (!Read()) { return false; } tokenType = TokenType; } return true; } private JsonToken GetContentToken() { JsonToken tokenType; do { if (!Read()) { SetToken(JsonToken.None); return JsonToken.None; } tokenType = TokenType; } while (tokenType == JsonToken.Comment); return tokenType; } } [Serializable] public class JsonReaderException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonReaderException() { } public JsonReaderException(string message) : base(message) { } public JsonReaderException(string message, Exception innerException) : base(message, innerException) { } public JsonReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonReaderException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonReaderException(message, path, lineNumber, linePosition, ex); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonRequiredAttribute : Attribute { } [Serializable] public class JsonSerializationException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonSerializationException() { } public JsonSerializationException(string message) : base(message) { } public JsonSerializationException(string message, Exception innerException) : base(message, innerException) { } public JsonSerializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonSerializationException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonSerializationException(message, path, lineNumber, linePosition, ex); } } public class JsonSerializer { internal TypeNameHandling _typeNameHandling; internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; internal PreserveReferencesHandling _preserveReferencesHandling; internal ReferenceLoopHandling _referenceLoopHandling; internal MissingMemberHandling _missingMemberHandling; internal ObjectCreationHandling _objectCreationHandling; internal NullValueHandling _nullValueHandling; internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; internal JsonConverterCollection? _converters; internal IContractResolver _contractResolver; internal ITraceWriter? _traceWriter; internal IEqualityComparer? _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver? _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; private DateTimeZoneHandling? _dateTimeZoneHandling; private DateParseHandling? _dateParseHandling; private FloatFormatHandling? _floatFormatHandling; private FloatParseHandling? _floatParseHandling; private StringEscapeHandling? _stringEscapeHandling; private CultureInfo _culture; private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; private string? _dateFormatString; private bool _dateFormatStringSet; public virtual IReferenceResolver? ReferenceResolver { get { return GetReferenceResolver(); } set { if (value == null) { throw new ArgumentNullException("value", "Reference resolver cannot be null."); } _referenceResolver = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { get { if (_serializationBinder is SerializationBinder result) { return result; } if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value); } } public virtual ISerializationBinder SerializationBinder { get { return _serializationBinder; } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = value; } } public virtual ITraceWriter? TraceWriter { get { return _traceWriter; } set { _traceWriter = value; } } public virtual IEqualityComparer? EqualityComparer { get { return _equalityComparer; } set { _equalityComparer = value; } } public virtual TypeNameHandling TypeNameHandling { get { return _typeNameHandling; } set { if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) { throw new ArgumentOutOfRangeException("value"); } _typeNameHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public virtual FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; } set { if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling; } set { if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = value; } } public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } set { if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) { throw new ArgumentOutOfRangeException("value"); } _preserveReferencesHandling = value; } } public virtual ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling; } set { if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) { throw new ArgumentOutOfRangeException("value"); } _referenceLoopHandling = value; } } public virtual MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling; } set { if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _missingMemberHandling = value; } } public virtual NullValueHandling NullValueHandling { get { return _nullValueHandling; } set { if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _nullValueHandling = value; } } public virtual DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling; } set { if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) { throw new ArgumentOutOfRangeException("value"); } _defaultValueHandling = value; } } public virtual ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling; } set { if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) { throw new ArgumentOutOfRangeException("value"); } _objectCreationHandling = value; } } public virtual ConstructorHandling ConstructorHandling { get { return _constructorHandling; } set { if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) { throw new ArgumentOutOfRangeException("value"); } _constructorHandling = value; } } public virtual MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling; } set { if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _metadataPropertyHandling = value; } } public virtual JsonConverterCollection Converters { get { if (_converters == null) { _converters = new JsonConverterCollection(); } return _converters; } } public virtual IContractResolver ContractResolver { get { return _contractResolver; } set { _contractResolver = value ?? DefaultContractResolver.Instance; } } public virtual StreamingContext Context { get { return _context; } set { _context = value; } } public virtual Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public virtual DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public virtual FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public virtual string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public virtual CultureInfo Culture { get { return _culture ?? JsonSerializerSettings.DefaultCulture; } set { _culture = value; } } public virtual int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public virtual bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error; internal bool IsCheckAdditionalContentSet() { return _checkAdditionalContent.HasValue; } public JsonSerializer() { _referenceLoopHandling = ReferenceLoopHandling.Error; _missingMemberHandling = MissingMemberHandling.Ignore; _nullValueHandling = NullValueHandling.Include; _defaultValueHandling = DefaultValueHandling.Include; _objectCreationHandling = ObjectCreationHandling.Auto; _preserveReferencesHandling = PreserveReferencesHandling.None; _constructorHandling = ConstructorHandling.Default; _typeNameHandling = TypeNameHandling.None; _metadataPropertyHandling = MetadataPropertyHandling.Default; _context = JsonSerializerSettings.DefaultContext; _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; } public static JsonSerializer Create() { return new JsonSerializer(); } public static JsonSerializer Create(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = Create(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } public static JsonSerializer CreateDefault() { return Create(JsonConvert.DefaultSettings?.Invoke()); } public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = CreateDefault(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) { if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) { for (int i = 0; i < settings.Converters.Count; i++) { serializer.Converters.Insert(i, settings.Converters[i]); } } if (settings._typeNameHandling.HasValue) { serializer.TypeNameHandling = settings.TypeNameHandling; } if (settings._metadataPropertyHandling.HasValue) { serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; } if (settings._typeNameAssemblyFormatHandling.HasValue) { serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; } if (settings._preserveReferencesHandling.HasValue) { serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; } if (settings._referenceLoopHandling.HasValue) { serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; } if (settings._missingMemberHandling.HasValue) { serializer.MissingMemberHandling = settings.MissingMemberHandling; } if (settings._objectCreationHandling.HasValue) { serializer.ObjectCreationHandling = settings.ObjectCreationHandling; } if (settings._nullValueHandling.HasValue) { serializer.NullValueHandling = settings.NullValueHandling; } if (settings._defaultValueHandling.HasValue) { serializer.DefaultValueHandling = settings.DefaultValueHandling; } if (settings._constructorHandling.HasValue) { serializer.ConstructorHandling = settings.ConstructorHandling; } if (settings._context.HasValue) { serializer.Context = settings.Context; } if (settings._checkAdditionalContent.HasValue) { serializer._checkAdditionalContent = settings._checkAdditionalContent; } if (settings.Error != null) { serializer.Error += settings.Error; } if (settings.ContractResolver != null) { serializer.ContractResolver = settings.ContractResolver; } if (settings.ReferenceResolverProvider != null) { serializer.ReferenceResolver = settings.ReferenceResolverProvider(); } if (settings.TraceWriter != null) { serializer.TraceWriter = settings.TraceWriter; } if (settings.EqualityComparer != null) { serializer.EqualityComparer = settings.EqualityComparer; } if (settings.SerializationBinder != null) { serializer.SerializationBinder = settings.SerializationBinder; } if (settings._formatting.HasValue) { serializer._formatting = settings._formatting; } if (settings._dateFormatHandling.HasValue) { serializer._dateFormatHandling = settings._dateFormatHandling; } if (settings._dateTimeZoneHandling.HasValue) { serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; } if (settings._dateParseHandling.HasValue) { serializer._dateParseHandling = settings._dateParseHandling; } if (settings._dateFormatStringSet) { serializer._dateFormatString = settings._dateFormatString; serializer._dateFormatStringSet = settings._dateFormatStringSet; } if (settings._floatFormatHandling.HasValue) { serializer._floatFormatHandling = settings._floatFormatHandling; } if (settings._floatParseHandling.HasValue) { serializer._floatParseHandling = settings._floatParseHandling; } if (settings._stringEscapeHandling.HasValue) { serializer._stringEscapeHandling = settings._stringEscapeHandling; } if (settings._culture != null) { serializer._culture = settings._culture; } if (settings._maxDepthSet) { serializer._maxDepth = settings._maxDepth; serializer._maxDepthSet = settings._maxDepthSet; } } [DebuggerStepThrough] public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } [DebuggerStepThrough] public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); } internal virtual void PopulateInternal(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader) { return Deserialize(reader, null); } [DebuggerStepThrough] public object? Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } [DebuggerStepThrough] public T? Deserialize<T>(JsonReader reader) { return (T)Deserialize(reader, typeof(T)); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader, Type? objectType) { return DeserializeInternal(reader, objectType); } internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); return result; } private void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture; } else { previousCulture = null; } if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling = reader.DateTimeZoneHandling; reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } else { previousDateTimeZoneHandling = null; } if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling) { previousDateParseHandling = reader.DateParseHandling; reader.DateParseHandling = _dateParseHandling.GetValueOrDefault(); } else { previousDateParseHandling = null; } if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling) { previousFloatParseHandling = reader.FloatParseHandling; reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault(); } else { previousFloatParseHandling = null; } if (_maxDepthSet && reader.MaxDepth != _maxDepth) { previousMaxDepth = reader.MaxDepth; reader.MaxDepth = _maxDepth; } else { previousMaxDepth = null; } if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) { previousDateFormatString = reader.DateFormatString; reader.DateFormatString = _dateFormatString; } else { previousDateFormatString = null; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver) { jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable(); } } private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString) { if (previousCulture != null) { reader.Culture = previousCulture; } if (previousDateTimeZoneHandling.HasValue) { reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault(); } if (previousDateParseHandling.HasValue) { reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault(); } if (previousFloatParseHandling.HasValue) { reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault(); } if (_maxDepthSet) { reader.MaxDepth = previousMaxDepth; } if (_dateFormatStringSet) { reader.DateFormatString = previousDateFormatString; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable()) { jsonTextReader.PropertyNameTable = null; } } public void Serialize(TextWriter textWriter, object? value) { Serialize(new JsonTextWriter(textWriter), value); } public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { SerializeInternal(jsonWriter, value, objectType); } public void Serialize(TextWriter textWriter, object? value, Type objectType) { Serialize(new JsonTextWriter(textWriter), value, objectType); } public void Serialize(JsonWriter jsonWriter, object? value) { SerializeInternal(jsonWriter, value, null); } private TraceJsonReader CreateTraceJsonReader(JsonReader reader) { TraceJsonReader traceJsonReader = new TraceJsonReader(reader); if (reader.TokenType != 0) { traceJsonReader.WriteCurrentToken(); } return traceJsonReader; } internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType) { ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter"); Formatting? formatting = null; if (_formatting.HasValue && jsonWriter.Formatting != _formatting) { formatting = jsonWriter.Formatting; jsonWriter.Formatting = _formatting.GetValueOrDefault(); } DateFormatHandling? dateFormatHandling = null; if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling) { dateFormatHandling = jsonWriter.DateFormatHandling; jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault(); } DateTimeZoneHandling? dateTimeZoneHandling = null; if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling) { dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling; jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } FloatFormatHandling? floatFormatHandling = null; if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling) { floatFormatHandling = jsonWriter.FloatFormatHandling; jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault(); } StringEscapeHandling? stringEscapeHandling = null; if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling) { stringEscapeHandling = jsonWriter.StringEscapeHandling; jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); } CultureInfo cultureInfo = null; if (_culture != null && !_culture.Equals(jsonWriter.Culture)) { cultureInfo = jsonWriter.Culture; jsonWriter.Culture = _culture; } string dateFormatString = null; if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) { dateFormatString = jsonWriter.DateFormatString; jsonWriter.DateFormatString = _dateFormatString; } TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null); new JsonSerializerInternalWriter(this).Serialize(traceJsonWriter ?? jsonWriter, value, objectType); if (traceJsonWriter != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); } if (formatting.HasValue) { jsonWriter.Formatting = formatting.GetValueOrDefault(); } if (dateFormatHandling.HasValue) { jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault(); } if (dateTimeZoneHandling.HasValue) { jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault(); } if (floatFormatHandling.HasValue) { jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault(); } if (stringEscapeHandling.HasValue) { jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault(); } if (_dateFormatStringSet) { jsonWriter.DateFormatString = dateFormatString; } if (cultureInfo != null) { jsonWriter.Culture = cultureInfo; } } internal IReferenceResolver GetReferenceResolver() { if (_referenceResolver == null) { _referenceResolver = new DefaultReferenceResolver(); } return _referenceResolver; } internal JsonConverter? GetMatchingConverter(Type type) { return GetMatchingConverter(_converters, type); } internal static JsonConverter? GetMatchingConverter(IList<JsonConverter>? converters, Type objectType) { if (converters != null) { for (int i = 0; i < converters.Count; i++) { JsonConverter jsonConverter = converters[i]; if (jsonConverter.CanConvert(objectType)) { return jsonConverter; } } } return null; } internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e) { this.Error?.Invoke(this, e); } } public class JsonSerializerSettings { internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error; internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore; internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include; internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include; internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto; internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default; internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default; internal static readonly StreamingContext DefaultContext; internal const Formatting DefaultFormatting = Formatting.None; internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat; internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime; internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double; internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String; internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default; internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; internal static readonly CultureInfo DefaultCulture; internal const bool DefaultCheckAdditionalContent = false; internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; internal const int DefaultMaxDepth = 64; internal Formatting? _formatting; internal DateFormatHandling? _dateFormatHandling; internal DateTimeZoneHandling? _dateTimeZoneHandling; internal DateParseHandling? _dateParseHandling; internal FloatFormatHandling? _floatFormatHandling; internal FloatParseHandling? _floatParseHandling; internal StringEscapeHandling? _stringEscapeHandling; internal CultureInfo? _culture; internal bool? _checkAdditionalContent; internal int? _maxDepth; internal bool _maxDepthSet; internal string? _dateFormatString; internal bool _dateFormatStringSet; internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; internal DefaultValueHandling? _defaultValueHandling; internal PreserveReferencesHandling? _preserveReferencesHandling; internal NullValueHandling? _nullValueHandling; internal ObjectCreationHandling? _objectCreationHandling; internal MissingMemberHandling? _missingMemberHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal StreamingContext? _context; internal ConstructorHandling? _constructorHandling; internal TypeNameHandling? _typeNameHandling; internal MetadataPropertyHandling? _metadataPropertyHandling; public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public IList<JsonConverter> Converters { get; set; } public PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling.GetValueOrDefault(); } set { _preserveReferencesHandling = value; } } public TypeNameHandling TypeNameHandling
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/XUnity.AutoTranslator.Plugin.ExtProtocol.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Package that contains a simple inter-process protocol format used in XUnity.")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.ExtProtocol")] [assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.ExtProtocol")] [assembly: AssemblyVersion("1.0.1.0")] namespace XUnity.AutoTranslator.Plugin.ExtProtocol; public class ConfigurationMessage : ProtocolMessage { public static readonly string Type = "4"; public string Config { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); Config = reader.ReadToEnd(); } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.Write(Config); } } public static class ExtProtocolConvert { private static readonly Dictionary<string, Type> IdToType; private static readonly Dictionary<Type, string> TypeToId; static ExtProtocolConvert() { IdToType = new Dictionary<string, Type>(); TypeToId = new Dictionary<Type, string>(); Register(TranslationRequest.Type, typeof(TranslationRequest)); Register(TranslationResponse.Type, typeof(TranslationResponse)); Register(TranslationError.Type, typeof(TranslationError)); Register(ConfigurationMessage.Type, typeof(ConfigurationMessage)); } public static void Register(string id, Type type) { IdToType[id] = type; TypeToId[type] = id; } public static string Encode(ProtocolMessage message) { StringWriter stringWriter = new StringWriter(); string value = TypeToId[message.GetType()]; stringWriter.WriteLine(value); message.Encode(stringWriter); return Convert.ToBase64String(Encoding.UTF8.GetBytes(stringWriter.ToString()), Base64FormattingOptions.None); } public static ProtocolMessage Decode(string message) { StringReader stringReader = new StringReader(Encoding.UTF8.GetString(Convert.FromBase64String(message))); string key = stringReader.ReadLine(); ProtocolMessage obj = (ProtocolMessage)Activator.CreateInstance(IdToType[key]); obj.Decode(stringReader); return obj; } } public abstract class ProtocolMessage { public Guid Id { get; set; } internal abstract void Decode(TextReader reader); internal abstract void Encode(TextWriter writer); } public enum StatusCode { OK = 0, Blocked = 1, Unknown = 1000 } public class TranslationError : ProtocolMessage { public static readonly string Type = "3"; public string Reason { get; set; } public StatusCode FailureCode { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); FailureCode = (StatusCode)int.Parse(reader.ReadLine()); Reason = reader.ReadToEnd(); } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine((int)FailureCode); writer.Write(Reason); } } public class TranslationRequest : ProtocolMessage { public static readonly string Type = "1"; private string[] _untranslatedTexts; public string SourceLanguage { get; set; } public string DestinationLanguage { get; set; } public string[] UntranslatedTexts => _untranslatedTexts ?? (_untranslatedTexts = UntranslatedTextInfos.Select((TransmittableUntranslatedTextInfo x) => x.UntranslatedText).ToArray()); public TransmittableUntranslatedTextInfo[] UntranslatedTextInfos { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); SourceLanguage = reader.ReadLine(); DestinationLanguage = reader.ReadLine(); int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); TransmittableUntranslatedTextInfo[] array = new TransmittableUntranslatedTextInfo[num]; for (int i = 0; i < num; i++) { TransmittableUntranslatedTextInfo transmittableUntranslatedTextInfo = new TransmittableUntranslatedTextInfo(); transmittableUntranslatedTextInfo.Decode(reader); array[i] = transmittableUntranslatedTextInfo; } UntranslatedTextInfos = array; } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine(SourceLanguage); writer.WriteLine(DestinationLanguage); writer.WriteLine(UntranslatedTextInfos.Length.ToString(CultureInfo.InvariantCulture)); TransmittableUntranslatedTextInfo[] untranslatedTextInfos = UntranslatedTextInfos; for (int i = 0; i < untranslatedTextInfos.Length; i++) { untranslatedTextInfos[i].Encode(writer); } } } public class TranslationResponse : ProtocolMessage { public static readonly string Type = "2"; public string[] TranslatedTexts { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array = new string[num]; for (int i = 0; i < num; i++) { string s = reader.ReadLine(); string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s)); array[i] = @string; } TranslatedTexts = array; } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine(TranslatedTexts.Length.ToString(CultureInfo.InvariantCulture)); string[] translatedTexts = TranslatedTexts; foreach (string s in translatedTexts) { string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None); writer.WriteLine(value); } } } public class TransmittableUntranslatedTextInfo { public string[] ContextBefore { get; set; } public string UntranslatedText { get; set; } public string[] ContextAfter { get; set; } public TransmittableUntranslatedTextInfo(string[] contextBefore, string untranslatedText, string[] contextAfter) { ContextBefore = contextBefore; UntranslatedText = untranslatedText; ContextAfter = contextAfter; } public TransmittableUntranslatedTextInfo() { } internal void Encode(TextWriter writer) { string[] contextBefore = ContextBefore; writer.WriteLine(((contextBefore != null) ? contextBefore.Length : 0).ToString(CultureInfo.InvariantCulture)); if (ContextBefore != null) { string[] contextBefore2 = ContextBefore; foreach (string s in contextBefore2) { string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None); writer.WriteLine(value); } } string[] contextAfter = ContextAfter; writer.WriteLine(((contextAfter != null) ? contextAfter.Length : 0).ToString(CultureInfo.InvariantCulture)); if (ContextAfter != null) { string[] contextBefore2 = ContextAfter; foreach (string s2 in contextBefore2) { string value2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(s2), Base64FormattingOptions.None); writer.WriteLine(value2); } } string value3 = Convert.ToBase64String(Encoding.UTF8.GetBytes(UntranslatedText), Base64FormattingOptions.None); writer.WriteLine(value3); } internal void Decode(TextReader reader) { int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array = new string[num]; for (int i = 0; i < num; i++) { string s = reader.ReadLine(); string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s)); array[i] = @string; } ContextBefore = array; int num2 = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array2 = new string[num2]; for (int j = 0; j < num2; j++) { string s2 = reader.ReadLine(); string string2 = Encoding.UTF8.GetString(Convert.FromBase64String(s2)); array2[j] = string2; } ContextAfter = array2; string s3 = reader.ReadLine(); string string3 = Encoding.UTF8.GetString(Convert.FromBase64String(s3)); UntranslatedText = string3; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/GoogleTranslate.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core; using XUnity.AutoTranslator.Plugin.Core.Constants; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Extensions; using XUnity.AutoTranslator.Plugin.Core.Shims; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.Common.Extensions; using XUnity.Common.Logging; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("GoogleTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GoogleTranslate")] [assembly: AssemblyTitle("GoogleTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace GoogleTranslate; public class GoogleTranslateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "auto", "romaji", "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi", "cy", "xh", "yi", "yo", "zu" }; private static readonly string DefaultApiBackend = "https://translate.googleapis.com"; private static readonly string DefaultUserBackend = "https://translate.google.com"; private static readonly string HttpsServicePointTranslateTemplateUrl = "/translate_a/single?client=webapp&sl={0}&tl={1}&dt=t&tk={2}&q={3}"; private static readonly string HttpsServicePointRomanizeTemplateUrl = "/translate_a/single?client=webapp&sl={0}&tl=en&dt=rm&tk={1}&q={2}"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] Accepts = new string[3] { null, "*/*", "application/json" }; private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; private static readonly string[] AcceptCharsets = new string[2] { null, Encoding.UTF8.WebName }; private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; private static readonly string AcceptCharset = AcceptCharsets[RandomNumbers.Next(AcceptCharsets.Length)]; private string _selectedApiBackend; private string _selectedUserBackend; private string _httpsServicePointTranslateTemplateUrl; private string _httpsServicePointRomanizeTemplateUrl; private CookieContainer _cookieContainer; private bool _hasSetup; private long m = 427761L; private long s = 1179739010L; private int _translationsPerRequest = 10; private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); public override string Id => "GoogleTranslate"; public override string FriendlyName => "Google! Translate"; public override int MaxTranslationsPerRequest => _translationsPerRequest; public GoogleTranslateEndpoint() { _cookieContainer = new CookieContainer(); } private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) if (context.DestinationLanguage == "romaji") { _translationsPerRequest = 1; } _selectedApiBackend = DefaultApiBackend; _selectedUserBackend = DefaultUserBackend; string orCreateSetting = context.GetOrCreateSetting<string>("Google", "ServiceUrl"); if (!StringExtensions.IsNullOrWhiteSpace(orCreateSetting)) { _selectedApiBackend = orCreateSetting; _selectedUserBackend = orCreateSetting; _httpsServicePointTranslateTemplateUrl = _selectedApiBackend + HttpsServicePointTranslateTemplateUrl; _httpsServicePointRomanizeTemplateUrl = _selectedApiBackend + HttpsServicePointRomanizeTemplateUrl; XuaLogger.AutoTranslator.Info("The default backend for google translate was overwritten."); } else { _selectedApiBackend = DefaultApiBackend; _selectedUserBackend = DefaultUserBackend; _httpsServicePointTranslateTemplateUrl = _selectedApiBackend + HttpsServicePointTranslateTemplateUrl; _httpsServicePointRomanizeTemplateUrl = _selectedApiBackend + HttpsServicePointRomanizeTemplateUrl; } context.DisableCertificateChecksFor(new string[2] { new Uri(_selectedApiBackend).Host, new Uri(_selectedUserBackend).Host }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _translationCount = 1; _hasSetup = true; IEnumerator enumerator = SetupTKK(); while (enumerator.MoveNext()) { yield return enumerator.Current; } } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown _translationCount++; string text = string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts); XUnityWebRequest val = ((!(((ITranslationContextBase)context).DestinationLanguage == "romaji")) ? new XUnityWebRequest(string.Format(_httpsServicePointTranslateTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), Tk(text), Uri.EscapeDataString(text))) : new XUnityWebRequest(string.Format(_httpsServicePointRomanizeTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), Tk(text), Uri.EscapeDataString(text)))); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: true); context.Complete(val); } public override void OnInspectResponse(IHttpResponseInspectionContext context) { InspectResponse(context.Response); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) bool flag = ((ITranslationContextBase)context).DestinationLanguage == "romaji"; int num = (flag ? 3 : 0); string data = ((IHttpResponseInspectionContext)context).Response.Data; JSONNode val = JSON.Parse(data); StringBuilder stringBuilder = new StringBuilder(data.Length); val = ((JSONNode)val.AsArray)[0]; if (val.IsNull && flag) { context.Complete(((ITranslationContextBase)context).UntranslatedText); return; } Enumerator enumerator = ((JSONNode)val.AsArray).GetEnumerator(); while (((Enumerator)(ref enumerator)).MoveNext()) { string text = ((object)((JSONNode)JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsArray)[num]).ToString(); text = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder)) { stringBuilder.Append('\n'); } stringBuilder.Append(text); } string text2 = stringBuilder.ToString(); if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1) { context.Complete(text2); return; } string[] array = text2.Split(new char[1] { '\n' }); List<string> list = new List<string>(); int num2 = 0; string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts; for (int i = 0; i < untranslatedTexts.Length; i++) { int num3 = untranslatedTexts[i].Split(new char[1] { '\n' }).Length; string text3 = string.Empty; for (int j = 0; j < num3; j++) { if (num2 >= array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } string text4 = array[num2++]; text3 += text4; if (j != num3 - 1) { text3 += "\n"; } } list.Add(text3); } if (num2 != array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } context.Complete(list.ToArray()); } private XUnityWebRequest CreateWebSiteRequest() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(_selectedUserBackend); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: false); return val; } private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest) { request.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); if (AcceptLanguage != null) { request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage; } if (Accept != null) { request.Headers[HttpRequestHeader.Accept] = Accept; } if (isTranslationRequest) { request.Headers[HttpRequestHeader.Referer] = _selectedUserBackend + "/"; } if (AcceptCharset != null) { request.Headers[HttpRequestHeader.AcceptCharset] = AcceptCharset; } } private void InspectResponse(XUnityWebResponse response) { CookieCollection newCookies = response.NewCookies; if (newCookies == null) { return; } foreach (Cookie item in newCookies) { item.Domain = ".googleapis.com"; } _cookieContainer.Add(newCookies); } public IEnumerator SetupTKK() { _cookieContainer = new CookieContainer(); XUnityWebResponse response; try { XUnityWebClient val = new XUnityWebClient(); XUnityWebRequest val2 = CreateWebSiteRequest(); response = val.Send(val2); } catch (Exception ex) { XuaLogger.AutoTranslator.Warn(ex, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); yield break; } IEnumerator iterator = ((CustomYieldInstructionShim)response).GetSupportedEnumerator(); while (iterator.MoveNext()) { yield return iterator.Current; } if (((CustomYieldInstructionShim)response).IsTimedOut) { XuaLogger.AutoTranslator.Warn("A timeout error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); yield break; } if (response.Error != null) { XuaLogger.AutoTranslator.Warn(response.Error, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); yield break; } if (response.Data == null) { XuaLogger.AutoTranslator.Warn((Exception)null, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); yield break; } InspectResponse(response); try { string data = response.Data; bool flag = false; string[] array = new string[2] { "tkk:'", "TKK='" }; foreach (string text in array) { int num = data.IndexOf(text); if (num > -1) { int num2 = num + text.Length; int num3 = data.IndexOf("'", num2); string[] array2 = data.Substring(num2, num3 - num2).Split(new char[1] { '.' }); if (array2.Length == 2) { m = long.Parse(array2[0]); s = long.Parse(array2[1]); flag = true; break; } } } if (!flag) { XuaLogger.AutoTranslator.Warn("An error occurred while setting up GoogleTranslate TKK. Could not locate TKK value. Using fallback TKK values instead."); } } catch (Exception ex2) { XuaLogger.AutoTranslator.Warn(ex2, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); } } private long Vi(long r, string o) { for (int i = 0; i < o.Length; i += 3) { long num = o[i + 2]; num = ((num >= 97) ? (num - 87) : (num - 48)); num = (('+' == o[i + 1]) ? (r >> (int)num) : (r << (int)num)); r = (('+' == o[i]) ? ((r + num) & 0xFFFFFFFFu) : (r ^ num)); } return r; } private string Tk(string r) { List<long> list = new List<long>(); for (int i = 0; i < r.Length; i++) { long num = r[i]; if (128 > num) { list.Add(num); continue; } if (2048 > num) { list.Add((num >> 6) | 0xC0); } else if (55296 == (0xFC00 & num) && i + 1 < r.Length && 56320 == (0xFC00 & r[i + 1])) { num = 65536 + ((0x3FF & num) << 10) + (0x3FF & r[++i]); list.Add((num >> 18) | 0xF0); list.Add(((num >> 12) & 0x3F) | 0x80); } else { list.Add((num >> 12) | 0xE0); list.Add(((num >> 6) & 0x3F) | 0x80); } list.Add((0x3F & num) | 0x80); } long num2 = m; for (int j = 0; j < list.Count; j++) { num2 += list[j]; num2 = Vi(num2, "+-a^+6"); } num2 = Vi(num2, "+-3^+b+-f"); num2 ^= s; if (0 > num2) { num2 = (0x7FFFFFFF & num2) + 2147483648u; } num2 %= 1000000; return num2.ToString(CultureInfo.InvariantCulture) + "." + (num2 ^ m).ToString(CultureInfo.InvariantCulture); } } public class GoogleTranslateEndpointV2 : HttpEndpoint { private static readonly char[] WordSplitters = new char[3] { ' ', '\r', '\n' }; private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "auto", "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi", "cy", "xh", "yi", "yo", "zu" }; private static readonly string DefaultUserBackend = "https://translate.google.com"; private static readonly string TranslationPostTemplate = "[[[\"{0}\",\"[[\\\"{1}\\\",\\\"{2}\\\",\\\"{3}\\\",true],[null]]\",null,\"generic\"]]]"; private static readonly string HttpsServicePointTranslateTemplateUrl = "/_/TranslateWebserverUi/data/batchexecute"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; private string _selectedUserBackend; private string _httpsServicePointTranslateTemplateUrl; private CookieContainer _cookieContainer; private bool _hasSetup; private long _FSID = LongRandom(long.MinValue, long.MaxValue, RandomNumbers); private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); private string _translateRpcId; private string _version; private bool _useSimplestSuggestion; private long _reqId; public override string Id => "GoogleTranslateV2"; public override string FriendlyName => "Google! Translate (v2)"; public override int MaxTranslationsPerRequest => 10; public GoogleTranslateEndpointV2() { _cookieContainer = new CookieContainer(); } private static long LongRandom(long min, long max, Random rand) { byte[] array = new byte[8]; rand.NextBytes(array); return Math.Abs(BitConverter.ToInt64(array, 0) % (max - min)) + min; } private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) string orCreateSetting = context.GetOrCreateSetting<string>("GoogleV2", "ServiceUrl"); if (!StringExtensions.IsNullOrWhiteSpace(orCreateSetting)) { _selectedUserBackend = orCreateSetting; _httpsServicePointTranslateTemplateUrl = _selectedUserBackend + HttpsServicePointTranslateTemplateUrl; XuaLogger.AutoTranslator.Info("The default backend for google translate was overwritten."); } else { _selectedUserBackend = DefaultUserBackend; _httpsServicePointTranslateTemplateUrl = _selectedUserBackend + HttpsServicePointTranslateTemplateUrl; } _translateRpcId = context.GetOrCreateSetting<string>("GoogleV2", "RPCID", "MkEWBc"); _version = context.GetOrCreateSetting<string>("GoogleV2", "VERSION", "boq_translate-webserver_20210323.10_p0"); _useSimplestSuggestion = context.GetOrCreateSetting<bool>("GoogleV2", "UseSimplest", false); context.DisableCertificateChecksFor(new string[2] { new Uri(_selectedUserBackend).Host, new Uri(_selectedUserBackend).Host }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _translationCount = 1; _reqId = RandomNumbers.Next(0, 100000); _hasSetup = true; IEnumerator enumerator = SetupFSID(); while (enumerator.MoveNext()) { yield return enumerator.Current; } } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown _translationCount++; string text = JsonHelper.Escape(JsonHelper.Escape(string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts))); string text2 = string.Join("&", "rpcids=" + _translateRpcId, "f.sid=" + _FSID.ToString(CultureInfo.InvariantCulture), "bl=" + Uri.EscapeDataString(_version), "hl=en-US", "soc-app=1", "soc-platform=1", "soc-device=1", "_reqid=" + _reqId.ToString(CultureInfo.InvariantCulture), "rt=c"); string text3 = "f.req=" + Uri.EscapeDataString(string.Format(TranslationPostTemplate, _translateRpcId, text, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage))) + "&"; string text4 = _httpsServicePointTranslateTemplateUrl + "?" + text2; XUnityWebRequest val = new XUnityWebRequest("POST", text4, text3); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: true); _reqId += 100000L; context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) string data = ((IHttpResponseInspectionContext)context).Response.Data; data = data.Substring(6); string text = data.Substring(0, data.IndexOf("\n")); int length = int.Parse(text, CultureInfo.InvariantCulture); data = data.Substring(text.Length, length); string text2 = ((object)((JSONNode)((JSONNode)JSON.Parse(data).AsArray)[0].AsArray)[2]).ToString(); string text3 = JsonHelper.Unescape(text2.Substring(1, text2.Length - 2)); JSONNode obj = ((JSONNode)((JSONNode)((JSONNode)((JSONNode)JSON.Parse(text3).AsArray)[1].AsArray)[0].AsArray)[0].AsArray)[5]; StringBuilder stringBuilder = new StringBuilder(text3.Length); Enumerator enumerator = ((JSONNode)obj.AsArray).GetEnumerator(); while (((Enumerator)(ref enumerator)).MoveNext()) { JSONArray asArray = JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsArray; string text4 = ((object)((JSONNode)asArray)[0]).ToString(); text4 = JsonHelper.Unescape(text4.Substring(1, text4.Length - 2)); if (StringExtensions.IsNullOrWhiteSpace(text4)) { continue; } if (_useSimplestSuggestion && ((JSONNode)asArray).Count > 1) { JSONNode obj2 = ((JSONNode)asArray)[1]; JSONArray val = ((obj2 != null) ? obj2.AsArray : null); if ((JSONNode)(object)val != (object)null) { HashSet<string> hashSet = new HashSet<string>(); hashSet.Add(text4); for (int i = 0; i < ((JSONNode)val).Count; i++) { string text5 = ((object)((JSONNode)val)[i]).ToString(); text5 = JsonHelper.Unescape(text5.Substring(1, text5.Length - 2)); hashSet.Add(text5); } if (hashSet.Count > 1) { XuaLogger.AutoTranslator.Debug("[GoogleTranslateV2]: Primary translation is '" + text4 + "', but found multiple suggestion:"); foreach (string item in hashSet) { XuaLogger.AutoTranslator.Debug("[GoogleTranslateV2]: " + item); } int wordsInPrimary = text4.Split(WordSplitters).Length; text4 = (from x in hashSet where x.Split(WordSplitters).Length < wordsInPrimary orderby x.Split(WordSplitters).Length select x).FirstOrDefault() ?? text4; XuaLogger.AutoTranslator.Debug("[GoogleTranslateV2]: Selecting translation: " + text4); } } } if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder)) { stringBuilder.Append('\n'); } stringBuilder.Append(text4); } string text6 = stringBuilder.ToString(); if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1) { context.Complete(text6); return; } string[] array = text6.Split(new char[1] { '\n' }); List<string> list = new List<string>(); int num = 0; string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts; for (int j = 0; j < untranslatedTexts.Length; j++) { int num2 = untranslatedTexts[j].Split(new char[1] { '\n' }).Length; string text7 = string.Empty; for (int k = 0; k < num2; k++) { if (num >= array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } string text8 = array[num++]; text7 += text8; if (k != num2 - 1) { text7 += "\n"; } } list.Add(text7); } if (num != array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } context.Complete(list.ToArray()); } private XUnityWebRequest CreateWebSiteRequest() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(_selectedUserBackend); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: false); return val; } private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest) { request.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); if (AcceptLanguage != null) { request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage; } if (isTranslationRequest) { request.Headers[HttpRequestHeader.Referer] = _selectedUserBackend + "/"; request.Headers["X-Same-Domain"] = "1"; request.Headers["DNT"] = "1"; request.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded;charset=UTF-8"; request.Headers[HttpRequestHeader.Accept] = "*/*"; request.Headers["Origin"] = _selectedUserBackend; } else { request.Headers["Upgrade-Insecure-Requests"] = "1"; } } public IEnumerator SetupFSID() { _cookieContainer = new CookieContainer(); XUnityWebResponse response; try { XUnityWebClient val = new XUnityWebClient(); XUnityWebRequest val2 = CreateWebSiteRequest(); response = val.Send(val2); } catch (Exception ex) { XuaLogger.AutoTranslator.Warn(ex, "An error occurred while setting up GoogleTranslate FSID. Using random instead."); yield break; } IEnumerator iterator = ((CustomYieldInstructionShim)response).GetSupportedEnumerator(); while (iterator.MoveNext()) { yield return iterator.Current; } if (((CustomYieldInstructionShim)response).IsTimedOut) { XuaLogger.AutoTranslator.Warn("A timeout error occurred while setting up GoogleTranslate FSID. Using random instead."); yield break; } if (response.Error != null) { XuaLogger.AutoTranslator.Warn(response.Error, "An error occurred while setting up GoogleTranslate FSID. Using random instead."); yield break; } if (response.Data == null) { XuaLogger.AutoTranslator.Warn((Exception)null, "An error occurred while setting up GoogleTranslate FSID. Using random instead."); yield break; } try { string data = response.Data; bool flag = false; string[] array = new string[1] { "FdrFJe\":\"" }; foreach (string text in array) { int num = data.IndexOf(text); if (num > -1) { int num2 = num + text.Length; int num3 = data.IndexOf("\"", num2); string s = data.Substring(num2, num3 - num2); _FSID = long.Parse(s, CultureInfo.InvariantCulture); flag = true; break; } } if (!flag) { XuaLogger.AutoTranslator.Warn("An error occurred while setting up GoogleTranslate FSID. Could not locate FSID value. Using random instead."); } } catch (Exception ex2) { XuaLogger.AutoTranslator.Warn(ex2, "An error occurred while setting up GoogleTranslate FSID. Using random instead."); } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/GoogleTranslateCompat.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("GoogleTranslateCompat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GoogleTranslateCompat")] [assembly: AssemblyTitle("GoogleTranslateCompat")] [assembly: AssemblyVersion("1.0.0.0")] namespace GoogleTranslateCompat; internal class GoogleTranslateCompatEndpoint : ExtProtocolEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "auto", "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi", "cy", "xh", "yi", "yo", "zu" }; public override string Id => "GoogleTranslateCompat"; public override string FriendlyName => "Google! Translate (Compat)"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) ((ExtProtocolEndpoint)this).Initialize(context); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes("GoogleTranslateCompat.ExtProtocol.GoogleTranslateCompatTranslate, GoogleTranslateCompat.ExtProtocol")); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/GoogleTranslateLegitimate.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("GoogleTranslateLegitimate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GoogleTranslateLegitimate")] [assembly: AssemblyTitle("GoogleTranslateLegitimate")] [assembly: AssemblyVersion("1.0.0.0")] namespace GoogleTranslateLegitimate; internal class GoogleTranslateLegitimateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh", "zh-Hans", "zh-Hant", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi", "cy", "xh", "yi", "yo", "zu" }; private static readonly string HttpsServiceUrl = "https://translation.googleapis.com/language/translate/v2"; private string _key; public override string Id => "GoogleTranslateLegitimate"; public override string FriendlyName => "Google! Translate (Authenticated)"; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) _key = context.GetOrCreateSetting<string>("GoogleLegitimate", "GoogleAPIKey", ""); if (string.IsNullOrEmpty(_key)) { throw new EndpointInitializationException("The GoogleTranslateLegitimate endpoint requires an API key which has not been provided."); } context.DisableCertificateChecksFor(new string[1] { "translation.googleapis.com" }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown StringBuilder stringBuilder = new StringBuilder(HttpsServiceUrl); stringBuilder.Append("?key=").Append(Uri.EscapeDataString(_key)); stringBuilder.Append("&source=").Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage)); stringBuilder.Append("&target=").Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage)); for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++) { string stringToEscape = ((ITranslationContextBase)context).UntranslatedTexts[i]; stringBuilder.Append("&q=").Append(Uri.EscapeDataString(stringToEscape)); } XUnityWebRequest val = new XUnityWebRequest("POST", stringBuilder.ToString()); context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { JSONArray asArray = ((JSONNode)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsObject)["data"].AsObject)["translations"].AsArray; List<string> list = new List<string>(); for (int i = 0; i < ((JSONNode)asArray).Count; i++) { string text = ((object)((JSONNode)((JSONNode)asArray)[i].AsObject)["translatedText"]).ToString(); string item = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); list.Add(item); } context.Complete(list.ToArray()); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/LecPowerTranslator15.dll
Decompiled 10 months agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using Microsoft.Win32; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("LecPowerTranslator15")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LecPowerTranslator15")] [assembly: AssemblyTitle("LecPowerTranslator15")] [assembly: AssemblyVersion("1.0.0.0")] namespace LecPowerTranslator15; internal class LecPowerTranslator15Endpoint : ExtProtocolEndpoint { public override string Id => "LecPowerTranslator15"; public override string FriendlyName => "LEC Power Translator 15"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 50; public override void Initialize(IInitializationContext context) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) string defaultInstallationPath = GetDefaultInstallationPath(); string text = context.GetOrCreateSetting<string>("LecPowerTranslator15", "InstallationPath", defaultInstallationPath); if (string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(defaultInstallationPath)) { context.SetSetting<string>("LecPowerTranslator15", "InstallationPath", defaultInstallationPath); text = defaultInstallationPath; } if (string.IsNullOrEmpty(text)) { throw new EndpointInitializationException("The LecPowerTranslator15 requires the path to the installation folder."); } context.DisableSpamChecks(); string text2 = Path.Combine(context.TranslatorDirectory, Path.Combine("FullNET", "Lec.ExtProtocol.exe")); if (!File.Exists(text2)) { throw new EndpointInitializationException("Could not find any executable at '" + text2 + "'"); } ((ExtProtocolEndpoint)this).ExecutablePath = text2; ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes(text)); if (context.SourceLanguage != "ja") { throw new EndpointInitializationException("Current implementation only supports japanese-to-english."); } if (context.DestinationLanguage != "en") { throw new EndpointInitializationException("Current implementation only supports japanese-to-english."); } } public static string GetDefaultInstallationPath() { try { string text = GetInstallationPathFromRegistry(); if (!string.IsNullOrEmpty(text)) { text = new DirectoryInfo(text).Parent.FullName; } return text ?? string.Empty; } catch { return string.Empty; } } public static string GetInstallationPathFromRegistry() { try { if (IntPtr.Size == 8) { return (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LogoMedia\\LEC Power Translator 15\\Configuration", "ApplicationPath", null); } return (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\LogoMedia\\LEC Power Translator 15\\Configuration", "ApplicationPath", null); } catch { return null; } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/LingoCloudTranslate.dll
Decompiled 10 months agousing System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("LingoCloudTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LingoCloudTranslate")] [assembly: AssemblyTitle("LingoCloudTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace LingoCloudTranslate; internal class LingoCloudTranslateEndpoint : HttpEndpoint { private static readonly Dictionary<string, string> SupportedLanguages = new Dictionary<string, string> { { "en", "en" }, { "ja", "ja" }, { "jp", "ja" }, { "zh", "zh" }, { "zh-Hans", "zh" }, { "zh-CN", "zh" }, { "zh-Hant", "zh" }, { "zh-TW", "zh" } }; private static readonly string HttpServicePointTemplateUrl = "https://api.interpreter.caiyunai.com/v1/translator"; public string _token; public override string Id => "LingoCloudTranslate"; public override string FriendlyName => "CaiYun Translator"; private string FixLanguage(string lang) { if (SupportedLanguages.TryGetValue(lang, out var value)) { return value; } return lang; } public override void Initialize(IInitializationContext context) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) _token = context.GetOrCreateSetting<string>("LingoCloud", "LingoCloudToken", ""); if (string.IsNullOrEmpty(_token)) { throw new EndpointInitializationException("The LingoCloudTranslate endpoint requires an App Id which has not been provided."); } context.DisableCertificateChecksFor(new string[1] { "api.interpreter.caiyunai.com" }); if (!SupportedLanguages.ContainsKey(context.SourceLanguage)) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.ContainsKey(context.DestinationLanguage)) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown JSONObject val = new JSONObject(); string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts; foreach (string text in untranslatedTexts) { ((JSONNode)val)["source"].Add(JSONNode.op_Implicit(text)); } ((JSONNode)val)["trans_type"] = JSONNode.op_Implicit("auto2" + FixLanguage(((ITranslationContextBase)context).DestinationLanguage)); ((JSONNode)val)["request_id"] = JSONNode.op_Implicit("demo"); ((JSONNode)val)["detect"] = JSONNode.op_Implicit("true"); string text2 = ((object)val).ToString(); XUnityWebRequest val2 = new XUnityWebRequest("POST", HttpServicePointTemplateUrl, text2); val2.Headers[HttpRequestHeader.ContentType] = "application/json"; val2.Headers["X-Authorization"] = "token " + _token; context.Complete(val2); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { string text = ((object)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsObject)["target"]).ToString(); string text2 = JsonHelper.Unescape(text.Substring(2, text.Length - 4)); context.Complete(text2); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/PapagoTranslate.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core; using XUnity.AutoTranslator.Plugin.Core.Constants; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Shims; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.Common.Logging; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("PapagoTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PapagoTranslate")] [assembly: AssemblyTitle("PapagoTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace PapagoTranslate; public class PapagoTranslateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "en", "ko", "zh-CN", "zh-TW", "es", "fr", "ru", "vi", "th", "id", "de", "ja", "hi", "pt" }; private static readonly HashSet<string> SMTLanguages = new HashSet<string> { "hi", "pt" }; private static readonly string UrlBase = "https://papago.naver.com"; private static readonly string UrlN2MT = "/apis/n2mt/translate"; private static readonly string UrlNSMT = "/apis/nsmt/translate"; private static readonly string FormUrlEncodedTemplate = "deviceId={0}&locale=en&dict=false&honorific=false&instant=true&source={1}&target={2}&text={3}"; private static readonly Random RandomNumbers = new Random(); private static readonly Guid UUID = Guid.NewGuid(); private static readonly Regex PatternSource = new Regex("/vendors~main[^\"]+", RegexOptions.Singleline); private static readonly Regex PatternVersion = new Regex("v\\d\\.\\d\\.\\d_[^\"]+", RegexOptions.Singleline); private string _version; private bool _isSMT; private int _translationCount; private int _resetAfter; public override string Id => "PapagoTranslate"; public override string FriendlyName => "Papago Translator"; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) context.DisableCertificateChecksFor(new string[1] { "papago.naver.com" }); string text = FixLanguage(context.SourceLanguage); string text2 = FixLanguage(context.DestinationLanguage); _isSMT = SMTLanguages.Contains(text) || SMTLanguages.Contains(text2); if (!SupportedLanguages.Contains(text2)) { throw new EndpointInitializationException("The language '" + context.DestinationLanguage + "' is not supported by Papago Translate."); } if (_isSMT && text != "en" && text2 != "en") { throw new EndpointInitializationException("Translation from '" + context.SourceLanguage + "' to '" + context.DestinationLanguage + "' is not supported by Papago Translate."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { if (_resetAfter == 0 || _translationCount % _resetAfter == 0) { _translationCount = 1; _resetAfter = RandomNumbers.Next(150, 200); IEnumerator enumerator = SetupVersion(); while (enumerator.MoveNext()) { yield return enumerator.Current; } } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown string text = Uri.EscapeDataString(string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts)); XUnityWebRequest val = new XUnityWebRequest("POST", UrlBase + (_isSMT ? UrlNSMT : UrlN2MT), string.Format(FormUrlEncodedTemplate, UUID, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), text)); DateTime utcNow = DateTime.UtcNow; DateTime minValue = DateTime.MinValue; double num = Math.Truncate(utcNow.Subtract(minValue.AddYears(1969)).TotalMilliseconds); byte[] bytes = Encoding.UTF8.GetBytes(_version); byte[] bytes2 = Encoding.UTF8.GetBytes($"{UUID}\n{val.Address}\n{num}"); string arg = Convert.ToBase64String(new HMACMD5(bytes).ComputeHash(bytes2)); val.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); val.Headers["Authorization"] = $"PPG {UUID}:{arg}"; val.Headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"; val.Headers["Timestamp"] = num.ToString(); context.Complete(val); _translationCount++; } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { string text = ((object)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsObject)["translatedText"]).ToString(); string text2 = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1) { context.Complete(text2); return; } string[] array = text2.Split(new char[1] { '\n' }); string[] array2 = new string[((ITranslationContextBase)context).UntranslatedTexts.Length]; int num = 0; for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++) { string[] array3 = ((ITranslationContextBase)context).UntranslatedTexts[i].Split(new char[1] { '\n' }); StringBuilder stringBuilder = new StringBuilder(); for (int j = 0; j < array3.Length; j++) { string value = array[num++]; if (array3.Length - 1 == j) { stringBuilder.Append(value); } else { stringBuilder.AppendLine(value); } } array2[i] = stringBuilder.ToString(); } if (num != array.Length) { ((ITranslationContextBase)context).Fail("Received invalid number of translations in batch."); } context.Complete(array2); } private IEnumerator SetupVersion() { XUnityWebClient client = new XUnityWebClient(); XUnityWebResponse response2 = client.Send(new XUnityWebRequest(UrlBase)); IEnumerator iterator2 = ((CustomYieldInstructionShim)response2).GetSupportedEnumerator(); while (iterator2.MoveNext()) { yield return iterator2.Current; } Match match = PatternSource.Match(response2.Data); if (!match.Success) { XuaLogger.AutoTranslator.Warn("Could not parse papago page"); yield break; } string value = match.Value; response2 = client.Send(new XUnityWebRequest(UrlBase + value)); iterator2 = ((CustomYieldInstructionShim)response2).GetSupportedEnumerator(); while (iterator2.MoveNext()) { yield return iterator2.Current; } Match match2 = PatternVersion.Match(response2.Data); if (!match2.Success) { XuaLogger.AutoTranslator.Warn("Could not parse papago version"); yield break; } XuaLogger.AutoTranslator.Debug("Current papago version is " + match2.Value); _version = match2.Value; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/WatsonTranslate.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Www; using XUnity.AutoTranslator.Plugin.Core.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("WatsonTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("WatsonTranslate")] [assembly: AssemblyTitle("WatsonTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace WatsonTranslate; internal class WatsonTranslateEndpoint : WwwEndpoint { private static readonly HashSet<string> SupportedLanguagePairs = new HashSet<string> { "ar-en", "ca-es", "zh-en", "zh-TW-en", "cs-en", "da-en", "nl-en", "en-ar", "en-cs", "en-da", "en-de", "en-es", "en-fi", "en-fr", "en-hi", "en-it", "en-ja", "en-ko", "en-nb", "en-nl", "en-pl", "en-pt", "en-ru", "en-sv", "en-tr", "en-zh", "en-zh-TW", "fi-en", "fr-de", "fr-en", "fr-es", "de-en", "de-fr", "de-it", "hi-en", "hu-en", "it-de", "it-en", "ja-en", "ko-en", "nb-en", "pl-en", "pt-en", "ru-en", "es-ca", "es-en", "es-fr", "sv-en", "tr-en" }; private string _fullUrl; private string _url; private string _key; public override string Id => "WatsonTranslate"; public override string FriendlyName => "Watson Language Translator"; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-CN": case "zh-Hans": return "zh"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) _url = context.GetOrCreateSetting<string>("Watson", "Url", ""); _key = context.GetOrCreateSetting<string>("Watson", "Key", ""); if (string.IsNullOrEmpty(_url)) { throw new EndpointInitializationException("The WatsonTranslate endpoint requires a url which has not been provided."); } if (string.IsNullOrEmpty(_key)) { throw new EndpointInitializationException("The WatsonTranslate endpoint requires a key which has not been provided."); } _fullUrl = _url.TrimEnd(new char[1] { '/' }) + "/v3/translate?version=2018-05-01"; string text = FixLanguage(context.SourceLanguage) + "-" + FixLanguage(context.DestinationLanguage); if (!SupportedLanguagePairs.Contains(text)) { throw new EndpointInitializationException("The language model '" + text + "' is not supported."); } } public override void OnCreateRequest(IWwwRequestCreationContext context) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{\"text\":["); for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++) { string value = JsonHelper.Escape(((ITranslationContextBase)context).UntranslatedTexts[i]); stringBuilder.Append("\"").Append(value).Append("\""); if (((ITranslationContextBase)context).UntranslatedTexts.Length - 1 != i) { stringBuilder.Append(","); } } stringBuilder.Append("],\"model_id\":\"").Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage)).Append("-") .Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage)) .Append("\"}"); WwwRequestInfo val = new WwwRequestInfo(_fullUrl, stringBuilder.ToString()); val.Headers["Accept"] = "application/json"; val.Headers["Content-Type"] = "application/json"; val.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("apikey:" + _key)); context.Complete(val); } public override void OnExtractTranslation(IWwwTranslationExtractionContext context) { JSONArray asArray = ((JSONNode)JSON.Parse(context.ResponseData).AsObject)["translations"].AsArray; List<string> list = new List<string>(); for (int i = 0; i < ((JSONNode)asArray).Count; i++) { string text = ((object)((JSONNode)((JSONNode)asArray)[i].AsObject)["translation"]).ToString(); string item = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); list.Add(item); } context.Complete(list.ToArray()); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/YandexTranslate.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("YandexTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("YandexTranslate")] [assembly: AssemblyTitle("YandexTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace YandexTranslate; internal class YandexTranslateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "az", "sq", "am", "en", "ar", "hy", "af", "eu", "ba", "be", "bn", "my", "bg", "bs", "cy", "hu", "vi", "ht", "gl", "nl", "mrj", "el", "ka", "gu", "da", "he", "yi", "id", "ga", "it", "is", "es", "kk", "kn", "ca", "ky", "zh", "ko", "xh", "km", "lo", "la", "lv", "lt", "lb", "mg", "ms", "ml", "mt", "mk", "mi", "mr", "mhr", "mn", "de", "ne", "no", "pa", "pap", "fa", "pl", "pt", "ro", "ru", "ceb", "sr", "si", "sk", "sl", "sw", "su", "tg", "th", "tl", "ta", "tt", "te", "tr", "udm", "uz", "uk", "ur", "fi", "fr", "hi", "hr", "cs", "sv", "gd", "et", "eo", "jv", "ja" }; private static readonly string HttpsServicePointTemplateUrl = "https://translate.yandex.net/api/v1.5/tr.json/translate?key={3}&text={2}&lang={0}-{1}&format=plain"; private string _key; public override string Id => "YandexTranslate"; public override string FriendlyName => "Yandex Translate"; private string FixLanguage(string lang) { if (lang == "zh-CN" || lang == "zh-Hans") { return "zh"; } return lang; } public override void Initialize(IInitializationContext context) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) _key = context.GetOrCreateSetting<string>("Yandex", "YandexAPIKey", ""); context.DisableCertificateChecksFor(new string[1] { "translate.yandex.net" }); if (string.IsNullOrEmpty(_key)) { throw new EndpointInitializationException("The YandexTranslate endpoint requires an API key which has not been provided."); } if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(string.Format(HttpsServicePointTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText), _key)); val.Headers[HttpRequestHeader.Accept] = "*/*"; val.Headers[HttpRequestHeader.AcceptCharset] = "UTF-8"; context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { JSONNode obj = JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data); string text = ((object)((JSONNode)obj.AsObject)["code"]).ToString(); if (text != "200") { ((ITranslationContextBase)context).Fail("Received bad response code: " + text); } string text2 = ((object)((JSONNode)obj.AsObject)["text"]).ToString(); string text3 = JsonHelper.Unescape(text2.Substring(2, text2.Length - 4)); if (string.IsNullOrEmpty(text3)) { ((ITranslationContextBase)context).Fail("Received no translation."); } context.Complete(text3); } }
BepInEx/plugins/XUnity.AutoTranslator/XUnity.AutoTranslator.Plugin.BepInEx.dll
Decompiled 10 months agousing System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using ExIni; using XUnity.AutoTranslator.Plugin.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("XUnity.AutoTranslator.Plugin.BepInEx")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("5.3.0.0")] [assembly: AssemblyInformationalVersion("5.3.0")] [assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.BepInEx")] [assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.BepInEx")] [assembly: AssemblyVersion("5.3.0.0")] namespace XUnity.AutoTranslator.Plugin.BepInEx; [BepInPlugin("gravydevsupreme.xunity.autotranslator", "XUnity Auto Translator", "5.3.0")] public class AutoTranslatorPlugin : BaseUnityPlugin, IPluginEnvironment { private IniFile _file; private string _configPath; public IniFile Preferences => _file ?? (_file = ReloadConfig()); public string ConfigPath { get; } public string TranslationPath { get; } public bool AllowDefaultInitializeHarmonyDetourBridge => false; public AutoTranslatorPlugin() { ConfigPath = Paths.ConfigPath; TranslationPath = Paths.BepInExRootPath; _configPath = Path.Combine(ConfigPath, "AutoTranslatorConfig.ini"); } public IniFile ReloadConfig() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!File.Exists(_configPath)) { return (IniFile)(((object)_file) ?? ((object)new IniFile())); } IniFile val = IniFile.FromFile(_configPath); if (_file == null) { return _file = val; } _file.Merge(val); return _file; } public void SaveConfig() { _file.Save(_configPath); } private void Awake() { PluginLoader.LoadWithConfig((IPluginEnvironment)(object)this); } }
BepInEx/plugins/XUnity.AutoTranslator/XUnity.AutoTranslator.Plugin.Core.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Cache; using System.Net.Security; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using DynamicLinq; using ExIni; using Harmony; using ICSharpCode.SharpZipLib.Checksums; using ICSharpCode.SharpZipLib.Core; using ICSharpCode.SharpZipLib.Encryption; using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip.Compression; using ICSharpCode.SharpZipLib.Zip.Compression.Streams; using Microsoft.CodeAnalysis; using MonoMod.RuntimeDetour; using UnityEngine; using UnityEngine.SceneManagement; using XUnity.AutoTranslator.Plugin.Core.AssetRedirection; using XUnity.AutoTranslator.Plugin.Core.Configuration; using XUnity.AutoTranslator.Plugin.Core.Debugging; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Extensions; using XUnity.AutoTranslator.Plugin.Core.Fonts; using XUnity.AutoTranslator.Plugin.Core.Hooks; using XUnity.AutoTranslator.Plugin.Core.Hooks.NGUI; using XUnity.AutoTranslator.Plugin.Core.Hooks.TextMeshPro; using XUnity.AutoTranslator.Plugin.Core.Hooks.UGUI; using XUnity.AutoTranslator.Plugin.Core.Managed.Textures; using XUnity.AutoTranslator.Plugin.Core.Parsing; using XUnity.AutoTranslator.Plugin.Core.Properties; using XUnity.AutoTranslator.Plugin.Core.Shims; using XUnity.AutoTranslator.Plugin.Core.Text; using XUnity.AutoTranslator.Plugin.Core.Textures; using XUnity.AutoTranslator.Plugin.Core.UI; using XUnity.AutoTranslator.Plugin.Core.UIResize; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.AutoTranslator.Plugin.Core.Web.Internal; using XUnity.AutoTranslator.Plugin.ExtProtocol; using XUnity.AutoTranslator.Plugin.Utilities; using XUnity.Common.Constants; using XUnity.Common.Extensions; using XUnity.Common.Harmony; using XUnity.Common.Logging; using XUnity.Common.MonoMod; using XUnity.Common.Utilities; using XUnity.ResourceRedirector; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.Core")] [assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.Core")] [assembly: AssemblyInformationalVersion("5.3.0")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyDescription("Main development dependency for XUnity Auto Translator.")] [assembly: AssemblyFileVersion("5.3.0.0")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: InternalsVisibleTo("XUnity.AutoTranslator.Plugin.Core.Tests")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.3.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DynamicLinq { internal static class DynamicQueryable { public static IQueryable<T> Where<T>(this IQueryable<T> source, string predicate, params object[] values) { return (IQueryable<T>)((IQueryable)source).Where(predicate, values); } public static IQueryable Where(this IQueryable source, string predicate, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } LambdaExpression expression = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values); return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Where", new Type[1] { source.ElementType }, source.Expression, Expression.Quote(expression))); } public static IQueryable Select(this IQueryable source, string selector, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } LambdaExpression lambdaExpression = DynamicExpression.ParseLambda(source.ElementType, null, selector, values); return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Select", new Type[2] { source.ElementType, lambdaExpression.Body.Type }, source.Expression, Expression.Quote(lambdaExpression))); } public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values) { return (IQueryable<T>)((IQueryable)source).OrderBy(ordering, values); } public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (ordering == null) { throw new ArgumentNullException("ordering"); } ParameterExpression[] parameters = new ParameterExpression[1] { Expression.Parameter(source.ElementType, "") }; IEnumerable<DynamicOrdering> enumerable = new ExpressionParser(parameters, ordering, values).ParseOrdering(); Expression expression = source.Expression; string text = "OrderBy"; string text2 = "OrderByDescending"; foreach (DynamicOrdering item in enumerable) { expression = Expression.Call(typeof(Queryable), item.Ascending ? text : text2, new Type[2] { source.ElementType, item.Selector.Type }, expression, Expression.Quote(Expression.Lambda(item.Selector, parameters))); text = "ThenBy"; text2 = "ThenByDescending"; } return source.Provider.CreateQuery(expression); } public static IQueryable Take(this IQueryable source, int count) { if (source == null) { throw new ArgumentNullException("source"); } return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Take", new Type[1] { source.ElementType }, source.Expression, Expression.Constant(count))); } public static IQueryable Skip(this IQueryable source, int count) { if (source == null) { throw new ArgumentNullException("source"); } return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Skip", new Type[1] { source.ElementType }, source.Expression, Expression.Constant(count))); } public static IQueryable GroupBy(this IQueryable source, string keySelector, string elementSelector, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (elementSelector == null) { throw new ArgumentNullException("elementSelector"); } LambdaExpression lambdaExpression = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, values); LambdaExpression lambdaExpression2 = DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, values); return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "GroupBy", new Type[3] { source.ElementType, lambdaExpression.Body.Type, lambdaExpression2.Body.Type }, source.Expression, Expression.Quote(lambdaExpression), Expression.Quote(lambdaExpression2))); } public static bool Any(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } return (bool)source.Provider.Execute(Expression.Call(typeof(Queryable), "Any", new Type[1] { source.ElementType }, source.Expression)); } public static int Count(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } return (int)source.Provider.Execute(Expression.Call(typeof(Queryable), "Count", new Type[1] { source.ElementType }, source.Expression)); } } internal abstract class DynamicClass { public override string ToString() { PropertyInfo[] properties = GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); for (int i = 0; i < properties.Length; i++) { if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(properties[i].Name); stringBuilder.Append("="); stringBuilder.Append(properties[i].GetValue(this, null)); } stringBuilder.Append("}"); return stringBuilder.ToString(); } } internal class DynamicProperty { private string name; private Type type; public string Name => name; public Type Type => type; public DynamicProperty(string name, Type type) { if (name == null) { throw new ArgumentNullException("name"); } if ((object)type == null) { throw new ArgumentNullException("type"); } this.name = name; this.type = type; } } internal static class DynamicExpression { public static Expression Parse(Type resultType, string expression, params object[] values) { return new ExpressionParser(null, expression, values).Parse(resultType); } public static LambdaExpression ParseLambda(Type itType, Type resultType, string expression, params object[] values) { return ParseLambda(new ParameterExpression[1] { Expression.Parameter(itType, "") }, resultType, expression, values); } public static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, params object[] values) { return Expression.Lambda(new ExpressionParser(parameters, expression, values).Parse(resultType), parameters); } public static Expression<Func<T, S>> ParseLambda<T, S>(string expression, params object[] values) { return (Expression<Func<T, S>>)ParseLambda(typeof(T), typeof(S), expression, values); } public static Type CreateClass(params DynamicProperty[] properties) { throw new NotImplementedException(); } public static Type CreateClass(IEnumerable<DynamicProperty> properties) { throw new NotImplementedException(); } } internal class DynamicOrdering { public Expression Selector; public bool Ascending; } internal class Signature : IEquatable<Signature> { public DynamicProperty[] properties; public int hashCode; public Signature(IEnumerable<DynamicProperty> properties) { this.properties = properties.ToArray(); hashCode = 0; foreach (DynamicProperty property in properties) { hashCode ^= property.Name.GetHashCode() ^ property.Type.GetHashCode(); } } public override int GetHashCode() { return hashCode; } public override bool Equals(object obj) { if (!(obj is Signature)) { return false; } return Equals((Signature)obj); } public bool Equals(Signature other) { if (properties.Length != other.properties.Length) { return false; } for (int i = 0; i < properties.Length; i++) { if (properties[i].Name != other.properties[i].Name || (object)properties[i].Type != other.properties[i].Type) { return false; } } return true; } } internal sealed class ParseException : Exception { private int position; public int Position => position; public ParseException(string message, int position) : base(message) { this.position = position; } public override string ToString() { return $"{Message} (at index {position})"; } } internal class ExpressionParser { private struct Token { public TokenId id; public string text; public int pos; } private enum TokenId { Unknown, End, Identifier, StringLiteral, IntegerLiteral, RealLiteral, Exclamation, Percent, Amphersand, OpenParen, CloseParen, Asterisk, Plus, Comma, Minus, Dot, Slash, Colon, LessThan, Equal, GreaterThan, Question, OpenBracket, CloseBracket, Bar, ExclamationEqual, DoubleAmphersand, LessThanEqual, LessGreater, DoubleEqual, GreaterThanEqual, DoubleBar } private interface ILogicalSignatures { void F(bool x, bool y); void F(bool? x, bool? y); } private interface IArithmeticSignatures { void F(int x, int y); void F(uint x, uint y); void F(long x, long y); void F(ulong x, ulong y); void F(float x, float y); void F(double x, double y); void F(decimal x, decimal y); void F(int? x, int? y); void F(uint? x, uint? y); void F(long? x, long? y); void F(ulong? x, ulong? y); void F(float? x, float? y); void F(double? x, double? y); void F(decimal? x, decimal? y); } private interface IRelationalSignatures : IArithmeticSignatures { void F(string x, string y); void F(char x, char y); void F(DateTime x, DateTime y); void F(TimeSpan x, TimeSpan y); void F(char? x, char? y); void F(DateTime? x, DateTime? y); void F(TimeSpan? x, TimeSpan? y); } private interface IEqualitySignatures : IRelationalSignatures, IArithmeticSignatures { void F(bool x, bool y); void F(bool? x, bool? y); } private interface IAddSignatures : IArithmeticSignatures { void F(DateTime x, TimeSpan y); void F(TimeSpan x, TimeSpan y); void F(DateTime? x, TimeSpan? y); void F(TimeSpan? x, TimeSpan? y); } private interface ISubtractSignatures : IAddSignatures, IArithmeticSignatures { void F(DateTime x, DateTime y); void F(DateTime? x, DateTime? y); } private interface INegationSignatures { void F(int x); void F(long x); void F(float x); void F(double x); void F(decimal x); void F(int? x); void F(long? x); void F(float? x); void F(double? x); void F(decimal? x); } private interface INotSignatures { void F(bool x); void F(bool? x); } private interface IEnumerableSignatures { void Where(bool predicate); void Any(); void Any(bool predicate); void All(bool predicate); void Count(); void Count(bool predicate); void Min(object selector); void Max(object selector); void Sum(int selector); void Sum(int? selector); void Sum(long selector); void Sum(long? selector); void Sum(float selector); void Sum(float? selector); void Sum(double selector); void Sum(double? selector); void Sum(decimal selector); void Sum(decimal? selector); void Average(int selector); void Average(int? selector); void Average(long selector); void Average(long? selector); void Average(float selector); void Average(float? selector); void Average(double selector); void Average(double? selector); void Average(decimal selector); void Average(decimal? selector); } private class MethodData { public MethodBase MethodBase; public ParameterInfo[] Parameters; public Expression[] Args; } private static readonly Type[] predefinedTypes = new Type[20] { typeof(object), typeof(bool), typeof(char), typeof(string), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(DateTime), typeof(TimeSpan), typeof(Guid), typeof(Math), typeof(Convert) }; private static readonly Expression trueLiteral = Expression.Constant(true); private static readonly Expression falseLiteral = Expression.Constant(false); private static readonly Expression nullLiteral = Expression.Constant(null); private static readonly string keywordIt = "it"; private static readonly string keywordIif = "iif"; private static readonly string keywordNew = "new"; private static Dictionary<string, object> keywords; private Dictionary<string, object> symbols; private IDictionary<string, object> externals; private Dictionary<Expression, string> literals; private ParameterExpression it; private string text; private int textPos; private int textLen; private char ch; private Token token; public ExpressionParser(ParameterExpression[] parameters, string expression, object[] values) { if (expression == null) { throw new ArgumentNullException("expression"); } if (keywords == null) { keywords = CreateKeywords(); } symbols = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); literals = new Dictionary<Expression, string>(); if (parameters != null) { ProcessParameters(parameters); } if (values != null) { ProcessValues(values); } text = expression; textLen = text.Length; SetTextPos(0); NextToken(); } private void ProcessParameters(ParameterExpression[] parameters) { foreach (ParameterExpression parameterExpression in parameters) { if (!string.IsNullOrEmpty(parameterExpression.Name)) { AddSymbol(parameterExpression.Name, parameterExpression); } } if (parameters.Length == 1 && string.IsNullOrEmpty(parameters[0].Name)) { it = parameters[0]; } } private void ProcessValues(object[] values) { for (int i = 0; i < values.Length; i++) { object obj = values[i]; if (i == values.Length - 1 && obj is IDictionary<string, object>) { externals = (IDictionary<string, object>)obj; } else { AddSymbol("@" + i.ToString(CultureInfo.InvariantCulture), obj); } } } private void AddSymbol(string name, object value) { if (symbols.ContainsKey(name)) { throw ParseError("The identifier '{0}' was defined more than once", name); } symbols.Add(name, value); } public Expression Parse(Type resultType) { int pos = token.pos; Expression expression = ParseExpression(); if ((object)resultType != null && (expression = PromoteExpression(expression, resultType, exact: true)) == null) { throw ParseError(pos, "Expression of type '{0}' expected", GetTypeName(resultType)); } ValidateToken(TokenId.End, "Syntax error"); return expression; } public IEnumerable<DynamicOrdering> ParseOrdering() { List<DynamicOrdering> list = new List<DynamicOrdering>(); while (true) { Expression selector = ParseExpression(); bool ascending = true; if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending")) { NextToken(); } else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending")) { NextToken(); ascending = false; } list.Add(new DynamicOrdering { Selector = selector, Ascending = ascending }); if (token.id != TokenId.Comma) { break; } NextToken(); } ValidateToken(TokenId.End, "Syntax error"); return list; } private Expression ParseExpression() { int pos = token.pos; Expression expression = ParseLogicalOr(); if (token.id == TokenId.Question) { NextToken(); Expression expr = ParseExpression(); ValidateToken(TokenId.Colon, "':' expected"); NextToken(); Expression expr2 = ParseExpression(); expression = GenerateConditional(expression, expr, expr2, pos); } return expression; } private Expression ParseLogicalOr() { Expression left = ParseLogicalAnd(); while (this.token.id == TokenId.DoubleBar || TokenIdentifierIs("or")) { Token token = this.token; NextToken(); Expression right = ParseLogicalAnd(); CheckAndPromoteOperands(typeof(ILogicalSignatures), token.text, ref left, ref right, token.pos); left = Expression.OrElse(left, right); } return left; } private Expression ParseLogicalAnd() { Expression left = ParseComparison(); while (this.token.id == TokenId.DoubleAmphersand || TokenIdentifierIs("and")) { Token token = this.token; NextToken(); Expression right = ParseComparison(); CheckAndPromoteOperands(typeof(ILogicalSignatures), token.text, ref left, ref right, token.pos); left = Expression.AndAlso(left, right); } return left; } private Expression ParseComparison() { Expression left = ParseAdditive(); while (this.token.id == TokenId.Equal || this.token.id == TokenId.DoubleEqual || this.token.id == TokenId.ExclamationEqual || this.token.id == TokenId.LessGreater || this.token.id == TokenId.GreaterThan || this.token.id == TokenId.GreaterThanEqual || this.token.id == TokenId.LessThan || this.token.id == TokenId.LessThanEqual) { Token token = this.token; NextToken(); Expression right = ParseAdditive(); bool flag = token.id == TokenId.Equal || token.id == TokenId.DoubleEqual || token.id == TokenId.ExclamationEqual || token.id == TokenId.LessGreater; if (flag && !left.Type.IsValueType && !right.Type.IsValueType) { if ((object)left.Type != right.Type) { if (left.Type.IsAssignableFrom(right.Type)) { right = Expression.Convert(right, left.Type); } else { if (!right.Type.IsAssignableFrom(left.Type)) { throw IncompatibleOperandsError(token.text, left, right, token.pos); } left = Expression.Convert(left, right.Type); } } } else if (IsEnumType(left.Type) || IsEnumType(right.Type)) { if ((object)left.Type != right.Type) { Expression expression; if ((expression = PromoteExpression(right, left.Type, exact: true)) != null) { right = expression; } else { if ((expression = PromoteExpression(left, right.Type, exact: true)) == null) { throw IncompatibleOperandsError(token.text, left, right, token.pos); } left = expression; } } } else { CheckAndPromoteOperands(flag ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures), token.text, ref left, ref right, token.pos); } switch (token.id) { case TokenId.Equal: case TokenId.DoubleEqual: left = GenerateEqual(left, right); break; case TokenId.ExclamationEqual: case TokenId.LessGreater: left = GenerateNotEqual(left, right); break; case TokenId.GreaterThan: left = GenerateGreaterThan(left, right); break; case TokenId.GreaterThanEqual: left = GenerateGreaterThanEqual(left, right); break; case TokenId.LessThan: left = GenerateLessThan(left, right); break; case TokenId.LessThanEqual: left = GenerateLessThanEqual(left, right); break; } } return left; } private Expression ParseAdditive() { Expression left = ParseMultiplicative(); while (this.token.id == TokenId.Plus || this.token.id == TokenId.Minus || this.token.id == TokenId.Amphersand) { Token token = this.token; NextToken(); Expression right = ParseMultiplicative(); TokenId id = token.id; if (id != TokenId.Amphersand) { if (id != TokenId.Plus) { if (id == TokenId.Minus) { CheckAndPromoteOperands(typeof(ISubtractSignatures), token.text, ref left, ref right, token.pos); left = GenerateSubtract(left, right); } continue; } if ((object)left.Type != typeof(string) && (object)right.Type != typeof(string)) { CheckAndPromoteOperands(typeof(IAddSignatures), token.text, ref left, ref right, token.pos); left = GenerateAdd(left, right); continue; } } left = GenerateStringConcat(left, right); } return left; } private Expression ParseMultiplicative() { Expression left = ParseUnary(); while (this.token.id == TokenId.Asterisk || this.token.id == TokenId.Slash || this.token.id == TokenId.Percent || TokenIdentifierIs("mod")) { Token token = this.token; NextToken(); Expression right = ParseUnary(); CheckAndPromoteOperands(typeof(IArithmeticSignatures), token.text, ref left, ref right, token.pos); switch (token.id) { case TokenId.Asterisk: left = Expression.Multiply(left, right); break; case TokenId.Slash: left = Expression.Divide(left, right); break; case TokenId.Identifier: case TokenId.Percent: left = Expression.Modulo(left, right); break; } } return left; } private Expression ParseUnary() { if (this.token.id == TokenId.Minus || this.token.id == TokenId.Exclamation || TokenIdentifierIs("not")) { Token token = this.token; NextToken(); if (token.id == TokenId.Minus && (this.token.id == TokenId.IntegerLiteral || this.token.id == TokenId.RealLiteral)) { this.token.text = "-" + this.token.text; this.token.pos = token.pos; return ParsePrimary(); } Expression expr = ParseUnary(); if (token.id == TokenId.Minus) { CheckAndPromoteOperand(typeof(INegationSignatures), token.text, ref expr, token.pos); return Expression.Negate(expr); } CheckAndPromoteOperand(typeof(INotSignatures), token.text, ref expr, token.pos); return Expression.Not(expr); } return ParsePrimary(); } private Expression ParsePrimary() { Expression expression = ParsePrimaryStart(); while (true) { if (token.id == TokenId.Dot) { NextToken(); expression = ParseMemberAccess(null, expression); continue; } if (token.id != TokenId.OpenBracket) { break; } expression = ParseElementAccess(expression); } return expression; } private Expression ParsePrimaryStart() { return token.id switch { TokenId.Identifier => ParseIdentifier(), TokenId.StringLiteral => ParseStringLiteral(), TokenId.IntegerLiteral => ParseIntegerLiteral(), TokenId.RealLiteral => ParseRealLiteral(), TokenId.OpenParen => ParseParenExpression(), _ => throw ParseError("Expression expected"), }; } private Expression ParseStringLiteral() { ValidateToken(TokenId.StringLiteral); char c = token.text[0]; string text = token.text.Substring(1, token.text.Length - 2); int startIndex = 0; while (true) { int num = text.IndexOf(c, startIndex); if (num < 0) { break; } text = text.Remove(num, 1); startIndex = num + 1; } if (c == '\'') { if (text.Length != 1) { throw ParseError("Character literal must contain exactly one character"); } NextToken(); return CreateLiteral(text[0], text); } NextToken(); return CreateLiteral(text, text); } private Expression ParseIntegerLiteral() { ValidateToken(TokenId.IntegerLiteral); string text = token.text; if (text[0] != '-') { if (!ulong.TryParse(text, out var result)) { throw ParseError("Invalid integer literal '{0}'", text); } NextToken(); if (result <= int.MaxValue) { return CreateLiteral((int)result, text); } if (result <= uint.MaxValue) { return CreateLiteral((uint)result, text); } if (result <= long.MaxValue) { return CreateLiteral((long)result, text); } return CreateLiteral(result, text); } if (!long.TryParse(text, out var result2)) { throw ParseError("Invalid integer literal '{0}'", text); } NextToken(); if (result2 >= int.MinValue && result2 <= int.MaxValue) { return CreateLiteral((int)result2, text); } return CreateLiteral(result2, text); } private Expression ParseRealLiteral() { ValidateToken(TokenId.RealLiteral); string text = token.text; object obj = null; char c = text[text.Length - 1]; double result2; if (c == 'F' || c == 'f') { if (float.TryParse(text.Substring(0, text.Length - 1), out var result)) { obj = result; } } else if (double.TryParse(text, out result2)) { obj = result2; } if (obj == null) { throw ParseError("Invalid real literal '{0}'", text); } NextToken(); return CreateLiteral(obj, text); } private Expression CreateLiteral(object value, string text) { ConstantExpression constantExpression = Expression.Constant(value); literals.Add(constantExpression, text); return constantExpression; } private Expression ParseParenExpression() { ValidateToken(TokenId.OpenParen, "'(' expected"); NextToken(); Expression result = ParseExpression(); ValidateToken(TokenId.CloseParen, "')' or operator expected"); NextToken(); return result; } private Expression ParseIdentifier() { ValidateToken(TokenId.Identifier); if (keywords.TryGetValue(token.text, out var value)) { if (value is Type) { return ParseTypeAccess((Type)value); } if (value == keywordIt) { return ParseIt(); } if (value == keywordIif) { return ParseIif(); } if (value == keywordNew) { return ParseNew(); } NextToken(); return (Expression)value; } if (symbols.TryGetValue(token.text, out value) || (externals != null && externals.TryGetValue(token.text, out value))) { Expression expression = value as Expression; if (expression == null) { expression = Expression.Constant(value); } else if (expression is LambdaExpression lambda) { return ParseLambdaInvocation(lambda); } NextToken(); return expression; } if (it != null) { return ParseMemberAccess(null, it); } throw ParseError("Unknown identifier '{0}'", token.text); } private Expression ParseIt() { if (it == null) { throw ParseError("No 'it' is in scope"); } NextToken(); return it; } private Expression ParseIif() { int pos = token.pos; NextToken(); Expression[] array = ParseArgumentList(); if (array.Length != 3) { throw ParseError(pos, "The 'iif' function requires three arguments"); } return GenerateConditional(array[0], array[1], array[2], pos); } private Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos) { if ((object)test.Type != typeof(bool)) { throw ParseError(errorPos, "The first expression must be of type 'Boolean'"); } if ((object)expr1.Type != expr2.Type) { Expression expression = ((expr2 != nullLiteral) ? PromoteExpression(expr1, expr2.Type, exact: true) : null); Expression expression2 = ((expr1 != nullLiteral) ? PromoteExpression(expr2, expr1.Type, exact: true) : null); if (expression != null && expression2 == null) { expr1 = expression; } else { if (expression2 == null || expression != null) { string text = ((expr1 != nullLiteral) ? expr1.Type.Name : "null"); string text2 = ((expr2 != nullLiteral) ? expr2.Type.Name : "null"); if (expression != null && expression2 != null) { throw ParseError(errorPos, "Both of the types '{0}' and '{1}' convert to the other", text, text2); } throw ParseError(errorPos, "Neither of the types '{0}' and '{1}' converts to the other", text, text2); } expr2 = expression2; } } return Expression.Condition(test, expr1, expr2); } private Expression ParseNew() { NextToken(); ValidateToken(TokenId.OpenParen, "'(' expected"); NextToken(); List<DynamicProperty> list = new List<DynamicProperty>(); List<Expression> list2 = new List<Expression>(); while (true) { int pos = token.pos; Expression expression = ParseExpression(); string name; if (TokenIdentifierIs("as")) { NextToken(); name = GetIdentifier(); NextToken(); } else { if (!(expression is MemberExpression memberExpression)) { throw ParseError(pos, "Expression is missing an 'as' clause"); } name = memberExpression.Member.Name; } list2.Add(expression); list.Add(new DynamicProperty(name, expression.Type)); if (token.id != TokenId.Comma) { break; } NextToken(); } ValidateToken(TokenId.CloseParen, "')' or ',' expected"); NextToken(); Type type = DynamicExpression.CreateClass(list); MemberBinding[] array = new MemberBinding[list.Count]; for (int i = 0; i < array.Length; i++) { array[i] = Expression.Bind(type.GetProperty(list[i].Name), list2[i]); } return Expression.MemberInit(Expression.New(type), array); } private Expression ParseLambdaInvocation(LambdaExpression lambda) { int pos = token.pos; NextToken(); Expression[] array = ParseArgumentList(); if (FindMethod(lambda.Type, "Invoke", staticAccess: false, array, out var _) != 1) { throw ParseError(pos, "Argument list incompatible with lambda expression"); } return Expression.Invoke(lambda, array); } private Expression ParseTypeAccess(Type type) { int pos = token.pos; NextToken(); if (token.id == TokenId.Question) { if (!type.IsValueType || IsNullableType(type)) { throw ParseError(pos, "Type '{0}' has no nullable form", GetTypeName(type)); } type = typeof(Nullable<>).MakeGenericType(type); NextToken(); } if (token.id == TokenId.OpenParen) { Expression[] array = ParseArgumentList(); MethodBase method; switch (FindBestMethod(type.GetConstructors(), array, out method)) { case 0: if (array.Length == 1) { return GenerateConversion(array[0], type, pos); } throw ParseError(pos, "No matching constructor in type '{0}'", GetTypeName(type)); case 1: return Expression.New((ConstructorInfo)method, array); default: throw ParseError(pos, "Ambiguous invocation of '{0}' constructor", GetTypeName(type)); } } ValidateToken(TokenId.Dot, "'.' or '(' expected"); NextToken(); return ParseMemberAccess(type, null); } private Expression GenerateConversion(Expression expr, Type type, int errorPos) { Type type2 = expr.Type; if ((object)type2 == type) { return expr; } if (type2.IsValueType && type.IsValueType) { if ((IsNullableType(type2) || IsNullableType(type)) && (object)GetNonNullableType(type2) == GetNonNullableType(type)) { return Expression.Convert(expr, type); } if (((IsNumericType(type2) || IsEnumType(type2)) && IsNumericType(type)) || IsEnumType(type)) { return Expression.ConvertChecked(expr, type); } } if (type2.IsAssignableFrom(type) || type.IsAssignableFrom(type2) || type2.IsInterface || type.IsInterface) { return Expression.Convert(expr, type); } throw ParseError(errorPos, "A value of type '{0}' cannot be converted to type '{1}'", GetTypeName(type2), GetTypeName(type)); } private Expression ParseMemberAccess(Type type, Expression instance) { if (instance != null) { type = instance.Type; } int pos = token.pos; string identifier = GetIdentifier(); NextToken(); if (token.id == TokenId.OpenParen) { if (instance != null && (object)type != typeof(string)) { Type type2 = FindGenericType(typeof(IEnumerable<>), type); if ((object)type2 != null) { Type elementType = type2.GetGenericArguments()[0]; return ParseAggregate(instance, elementType, identifier, pos); } } Expression[] array = ParseArgumentList(); MethodBase method; switch (FindMethod(type, identifier, instance == null, array, out method)) { case 0: throw ParseError(pos, "No applicable method '{0}' exists in type '{1}'", identifier, GetTypeName(type)); case 1: { MethodInfo methodInfo = (MethodInfo)method; if (!IsPredefinedType(methodInfo.DeclaringType)) { throw ParseError(pos, "Methods on type '{0}' are not accessible", GetTypeName(methodInfo.DeclaringType)); } if ((object)methodInfo.ReturnType == typeof(void)) { throw ParseError(pos, "Method '{0}' in type '{1}' does not return a value", identifier, GetTypeName(methodInfo.DeclaringType)); } return Expression.Call(instance, methodInfo, array); } default: throw ParseError(pos, "Ambiguous invocation of method '{0}' in type '{1}'", identifier, GetTypeName(type)); } } MemberInfo memberInfo = FindPropertyOrField(type, identifier, instance == null); if ((object)memberInfo == null) { throw ParseError(pos, "No property or field '{0}' exists in type '{1}'", identifier, GetTypeName(type)); } if (!(memberInfo is PropertyInfo)) { return Expression.Field(instance, (FieldInfo)memberInfo); } return Expression.Property(instance, (PropertyInfo)memberInfo); } private static Type FindGenericType(Type generic, Type type) { while ((object)type != null && (object)type != typeof(object)) { if (type.IsGenericType && (object)type.GetGenericTypeDefinition() == generic) { return type; } if (generic.IsInterface) { Type[] interfaces = type.GetInterfaces(); foreach (Type type2 in interfaces) { Type type3 = FindGenericType(generic, type2); if ((object)type3 != null) { return type3; } } } type = type.BaseType; } return null; } private Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos) { ParameterExpression parameterExpression = it; ParameterExpression parameterExpression2 = (it = Expression.Parameter(elementType, "")); Expression[] array = ParseArgumentList(); it = parameterExpression; if (FindMethod(typeof(IEnumerableSignatures), methodName, staticAccess: false, array, out var method) != 1) { throw ParseError(errorPos, "No applicable aggregate method '{0}' exists", methodName); } return Expression.Call(typeArguments: (!(method.Name == "Min") && !(method.Name == "Max")) ? new Type[1] { elementType } : new Type[2] { elementType, array[0].Type }, arguments: (array.Length != 0) ? new Expression[2] { instance, Expression.Lambda(array[0], parameterExpression2) } : new Expression[1] { instance }, type: typeof(Enumerable), methodName: method.Name); } private Expression[] ParseArgumentList() { ValidateToken(TokenId.OpenParen, "'(' expected"); NextToken(); Expression[] result = ((token.id != TokenId.CloseParen) ? ParseArguments() : new Expression[0]); ValidateToken(TokenId.CloseParen, "')' or ',' expected"); NextToken(); return result; } private Expression[] ParseArguments() { List<Expression> list = new List<Expression>(); while (true) { list.Add(ParseExpression()); if (token.id != TokenId.Comma) { break; } NextToken(); } return list.ToArray(); } private Expression ParseElementAccess(Expression expr) { int pos = token.pos; ValidateToken(TokenId.OpenBracket, "'(' expected"); NextToken(); Expression[] array = ParseArguments(); ValidateToken(TokenId.CloseBracket, "']' or ',' expected"); NextToken(); if (expr.Type.IsArray) { if (expr.Type.GetArrayRank() != 1 || array.Length != 1) { throw ParseError(pos, "Indexing of multi-dimensional arrays is not supported"); } Expression expression = PromoteExpression(array[0], typeof(int), exact: true); if (expression == null) { throw ParseError(pos, "Array index must be an integer expression"); } return Expression.ArrayIndex(expr, expression); } MethodBase method; return FindIndexer(expr.Type, array, out method) switch { 0 => throw ParseError(pos, "No applicable indexer exists in type '{0}'", GetTypeName(expr.Type)), 1 => Expression.Call(expr, (MethodInfo)method, array), _ => throw ParseError(pos, "Ambiguous invocation of indexer in type '{0}'", GetTypeName(expr.Type)), }; } private static bool IsPredefinedType(Type type) { Type[] array = predefinedTypes; for (int i = 0; i < array.Length; i++) { if ((object)array[i] == type) { return true; } } return false; } private static bool IsNullableType(Type type) { if (type.IsGenericType) { return (object)type.GetGenericTypeDefinition() == typeof(Nullable<>); } return false; } private static Type GetNonNullableType(Type type) { if (!IsNullableType(type)) { return type; } return type.GetGenericArguments()[0]; } private static string GetTypeName(Type type) { Type nonNullableType = GetNonNullableType(type); string text = nonNullableType.Name; if ((object)type != nonNullableType) { text += "?"; } return text; } private static bool IsNumericType(Type type) { return GetNumericTypeKind(type) != 0; } private static bool IsSignedIntegralType(Type type) { return GetNumericTypeKind(type) == 2; } private static bool IsUnsignedIntegralType(Type type) { return GetNumericTypeKind(type) == 3; } private static int GetNumericTypeKind(Type type) { type = GetNonNullableType(type); if (type.IsEnum) { return 0; } switch (Type.GetTypeCode(type)) { case TypeCode.Char: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return 1; case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: return 2; case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: return 3; default: return 0; } } private static bool IsEnumType(Type type) { return GetNonNullableType(type).IsEnum; } private void CheckAndPromoteOperand(Type signatures, string opName, ref Expression expr, int errorPos) { Expression[] array = new Expression[1] { expr }; if (FindMethod(signatures, "F", staticAccess: false, array, out var _) != 1) { throw ParseError(errorPos, "Operator '{0}' incompatible with operand type '{1}'", opName, GetTypeName(array[0].Type)); } expr = array[0]; } private void CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int errorPos) { Expression[] array = new Expression[2] { left, right }; if (FindMethod(signatures, "F", staticAccess: false, array, out var _) != 1) { throw IncompatibleOperandsError(opName, left, right, errorPos); } left = array[0]; right = array[1]; } private Exception IncompatibleOperandsError(string opName, Expression left, Expression right, int pos) { return ParseError(pos, "Operator '{0}' incompatible with operand types '{1}' and '{2}'", opName, GetTypeName(left.Type), GetTypeName(right.Type)); } private MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | (staticAccess ? BindingFlags.Static : BindingFlags.Instance); foreach (Type item in SelfAndBaseTypes(type)) { MemberInfo[] array = item.FindMembers(MemberTypes.Field | MemberTypes.Property, bindingAttr, Type.FilterNameIgnoreCase, memberName); if (array.Length != 0) { return array[0]; } } return null; } private int FindMethod(Type type, string methodName, bool staticAccess, Expression[] args, out MethodBase method) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | (staticAccess ? BindingFlags.Static : BindingFlags.Instance); foreach (Type item in SelfAndBaseTypes(type)) { MemberInfo[] source = item.FindMembers(MemberTypes.Method, bindingAttr, Type.FilterNameIgnoreCase, methodName); int num = FindBestMethod(source.Cast<MethodBase>(), args, out method); if (num != 0) { return num; } } method = null; return 0; } private int FindIndexer(Type type, Expression[] args, out MethodBase method) { foreach (Type item in SelfAndBaseTypes(type)) { MemberInfo[] defaultMembers = item.GetDefaultMembers(); if (defaultMembers.Length != 0) { IEnumerable<MethodBase> methods = from m in defaultMembers.OfType<PropertyInfo>().Select((Func<PropertyInfo, MethodBase>)((PropertyInfo p) => p.GetGetMethod())) where (object)m != null select m; int num = FindBestMethod(methods, args, out method); if (num != 0) { return num; } } } method = null; return 0; } private static IEnumerable<Type> SelfAndBaseTypes(Type type) { if (type.IsInterface) { List<Type> list = new List<Type>(); AddInterface(list, type); return list; } return SelfAndBaseClasses(type); } private static IEnumerable<Type> SelfAndBaseClasses(Type type) { while ((object)type != null) { yield return type; type = type.BaseType; } } private static void AddInterface(List<Type> types, Type type) { if (!types.Contains(type)) { types.Add(type); Type[] interfaces = type.GetInterfaces(); foreach (Type type2 in interfaces) { AddInterface(types, type2); } } } private int FindBestMethod(IEnumerable<MethodBase> methods, Expression[] args, out MethodBase method) { MethodData[] applicable = (from m in methods select new MethodData { MethodBase = m, Parameters = m.GetParameters() } into m where IsApplicable(m, args) select m).ToArray(); if (applicable.Length > 1) { applicable = applicable.Where((MethodData m) => applicable.All((MethodData n) => m == n || IsBetterThan(args, m, n))).ToArray(); } if (applicable.Length == 1) { MethodData methodData = applicable[0]; for (int i = 0; i < args.Length; i++) { args[i] = methodData.Args[i]; } method = methodData.MethodBase; } else { method = null; } return applicable.Length; } private bool IsApplicable(MethodData method, Expression[] args) { if (method.Parameters.Length != args.Length) { return false; } Expression[] array = new Expression[args.Length]; for (int i = 0; i < args.Length; i++) { ParameterInfo parameterInfo = method.Parameters[i]; if (parameterInfo.IsOut) { return false; } Expression expression = PromoteExpression(args[i], parameterInfo.ParameterType, exact: false); if (expression == null) { return false; } array[i] = expression; } method.Args = array; return true; } private Expression PromoteExpression(Expression expr, Type type, bool exact) { if ((object)expr.Type == type) { return expr; } if (expr is ConstantExpression) { ConstantExpression constantExpression = (ConstantExpression)expr; string value; if (constantExpression == nullLiteral) { if (!type.IsValueType || IsNullableType(type)) { return Expression.Constant(null, type); } } else if (literals.TryGetValue(constantExpression, out value)) { Type nonNullableType = GetNonNullableType(type); object obj = null; switch (Type.GetTypeCode(constantExpression.Type)) { case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: obj = ParseNumber(value, nonNullableType); break; case TypeCode.Double: if ((object)nonNullableType == typeof(decimal)) { obj = ParseNumber(value, nonNullableType); } break; case TypeCode.String: obj = ParseEnum(value, nonNullableType); break; } if (obj != null) { return Expression.Constant(obj, type); } } } if (IsCompatibleWith(expr.Type, type)) { if (type.IsValueType || exact) { return Expression.Convert(expr, type); } return expr; } return null; } private static object ParseNumber(string text, Type type) { switch (Type.GetTypeCode(GetNonNullableType(type))) { case TypeCode.SByte: { if (sbyte.TryParse(text, out var result6)) { return result6; } break; } case TypeCode.Byte: { if (byte.TryParse(text, out var result10)) { return result10; } break; } case TypeCode.Int16: { if (short.TryParse(text, out var result2)) { return result2; } break; } case TypeCode.UInt16: { if (ushort.TryParse(text, out var result8)) { return result8; } break; } case TypeCode.Int32: { if (int.TryParse(text, out var result4)) { return result4; } break; } case TypeCode.UInt32: { if (uint.TryParse(text, out var result11)) { return result11; } break; } case TypeCode.Int64: { if (long.TryParse(text, out var result9)) { return result9; } break; } case TypeCode.UInt64: { if (ulong.TryParse(text, out var result7)) { return result7; } break; } case TypeCode.Single: { if (float.TryParse(text, out var result5)) { return result5; } break; } case TypeCode.Double: { if (double.TryParse(text, out var result3)) { return result3; } break; } case TypeCode.Decimal: { if (decimal.TryParse(text, out var result)) { return result; } break; } } return null; } private static object ParseEnum(string name, Type type) { if (type.IsEnum) { MemberInfo[] array = type.FindMembers(MemberTypes.Field, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public, Type.FilterNameIgnoreCase, name); if (array.Length != 0) { return ((FieldInfo)array[0]).GetValue(null); } } return null; } private static bool IsCompatibleWith(Type source, Type target) { if ((object)source == target) { return true; } if (!target.IsValueType) { return target.IsAssignableFrom(source); } Type nonNullableType = GetNonNullableType(source); Type nonNullableType2 = GetNonNullableType(target); if ((object)nonNullableType != source && (object)nonNullableType2 == target) { return false; } TypeCode typeCode = (nonNullableType.IsEnum ? TypeCode.Object : Type.GetTypeCode(nonNullableType)); TypeCode typeCode2 = (nonNullableType2.IsEnum ? TypeCode.Object : Type.GetTypeCode(nonNullableType2)); switch (typeCode) { case TypeCode.SByte: switch (typeCode2) { case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.Byte: if ((uint)(typeCode2 - 6) <= 9u) { return true; } break; case TypeCode.Int16: switch (typeCode2) { case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.UInt16: if ((uint)(typeCode2 - 8) <= 7u) { return true; } break; case TypeCode.Int32: switch (typeCode2) { case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.UInt32: if ((uint)(typeCode2 - 10) <= 5u) { return true; } break; case TypeCode.Int64: if (typeCode2 == TypeCode.Int64 || (uint)(typeCode2 - 13) <= 2u) { return true; } break; case TypeCode.UInt64: if ((uint)(typeCode2 - 12) <= 3u) { return true; } break; case TypeCode.Single: if ((uint)(typeCode2 - 13) <= 1u) { return true; } break; default: if ((object)nonNullableType == nonNullableType2) { return true; } break; } return false; } private static bool IsBetterThan(Expression[] args, MethodData m1, MethodData m2) { bool result = false; for (int i = 0; i < args.Length; i++) { int num = CompareConversions(args[i].Type, m1.Parameters[i].ParameterType, m2.Parameters[i].ParameterType); if (num < 0) { return false; } if (num > 0) { result = true; } } return result; } private static int CompareConversions(Type s, Type t1, Type t2) { if ((object)t1 == t2) { return 0; } if ((object)s == t1) { return 1; } if ((object)s == t2) { return -1; } bool flag = IsCompatibleWith(t1, t2); bool flag2 = IsCompatibleWith(t2, t1); if (flag && !flag2) { return 1; } if (flag2 && !flag) { return -1; } if (IsSignedIntegralType(t1) && IsUnsignedIntegralType(t2)) { return 1; } if (IsSignedIntegralType(t2) && IsUnsignedIntegralType(t1)) { return -1; } return 0; } private Expression GenerateEqual(Expression left, Expression right) { return Expression.Equal(left, right); } private Expression GenerateNotEqual(Expression left, Expression right) { return Expression.NotEqual(left, right); } private Expression GenerateGreaterThan(Expression left, Expression right) { if ((object)left.Type == typeof(string)) { return Expression.GreaterThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0)); } return Expression.GreaterThan(left, right); } private Expression GenerateGreaterThanEqual(Expression left, Expression right) { if ((object)left.Type == typeof(string)) { return Expression.GreaterThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0)); } return Expression.GreaterThanOrEqual(left, right); } private Expression GenerateLessThan(Expression left, Expression right) { if ((object)left.Type == typeof(string)) { return Expression.LessThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0)); } return Expression.LessThan(left, right); } private Expression GenerateLessThanEqual(Expression left, Expression right) { if ((object)left.Type == typeof(string)) { return Expression.LessThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0)); } return Expression.LessThanOrEqual(left, right); } private Expression GenerateAdd(Expression left, Expression right) { if ((object)left.Type == typeof(string) && (object)right.Type == typeof(string)) { return GenerateStaticMethodCall("Concat", left, right); } return Expression.Add(left, right); } private Expression GenerateSubtract(Expression left, Expression right) { return Expression.Subtract(left, right); } private Expression GenerateStringConcat(Expression left, Expression right) { return Expression.Call(null, typeof(string).GetMethod("Concat", new Type[2] { typeof(object), typeof(object) }), new Expression[2] { left, right }); } private MethodInfo GetStaticMethod(string methodName, Expression left, Expression right) { return left.Type.GetMethod(methodName, new Type[2] { left.Type, right.Type }); } private Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right) { return Expression.Call(null, GetStaticMethod(methodName, left, right), new Expression[2] { left, right }); } private void SetTextPos(int pos) { textPos = pos; ch = ((textPos < textLen) ? text[textPos] : '\0'); } private void NextChar() { if (textPos < textLen) { textPos++; } ch = ((textPos < textLen) ? text[textPos] : '\0'); } private void NextToken() { while (char.IsWhiteSpace(ch)) { NextChar(); } int num = textPos; TokenId id; switch (ch) { case '!': NextChar(); if (ch == '=') { NextChar(); id = TokenId.ExclamationEqual; } else { id = TokenId.Exclamation; } break; case '%': NextChar(); id = TokenId.Percent; break; case '&': NextChar(); if (ch == '&') { NextChar(); id = TokenId.DoubleAmphersand; } else { id = TokenId.Amphersand; } break; case '(': NextChar(); id = TokenId.OpenParen; break; case ')': NextChar(); id = TokenId.CloseParen; break; case '*': NextChar(); id = TokenId.Asterisk; break; case '+': NextChar(); id = TokenId.Plus; break; case ',': NextChar(); id = TokenId.Comma; break; case '-': NextChar(); id = TokenId.Minus; break; case '.': NextChar(); id = TokenId.Dot; break; case '/': NextChar(); id = TokenId.Slash; break; case ':': NextChar(); id = TokenId.Colon; break; case '<': NextChar(); if (ch == '=') { NextChar(); id = TokenId.LessThanEqual; } else if (ch == '>') { NextChar(); id = TokenId.LessGreater; } else { id = TokenId.LessThan; } break; case '=': NextChar(); if (ch == '=') { NextChar(); id = TokenId.DoubleEqual; } else { id = TokenId.Equal; } break; case '>': NextChar(); if (ch == '=') { NextChar(); id = TokenId.GreaterThanEqual; } else { id = TokenId.GreaterThan; } break; case '?': NextChar(); id = TokenId.Question; break; case '[': NextChar(); id = TokenId.OpenBracket; break; case ']': NextChar(); id = TokenId.CloseBracket; break; case '|': NextChar(); if (ch == '|') { NextChar(); id = TokenId.DoubleBar; } else { id = TokenId.Bar; } break; case '"': case '\'': { char c = ch; do { NextChar(); while (textPos < textLen && ch != c) { NextChar(); } if (textPos == textLen) { throw ParseError(textPos, "Unterminated string literal"); } NextChar(); } while (ch == c); id = TokenId.StringLiteral; break; } default: if (char.IsLetter(ch) || ch == '@' || ch == '_') { do { NextChar(); } while (char.IsLetterOrDigit(ch) || ch == '_'); id = TokenId.Identifier; } else if (char.IsDigit(ch)) { id = TokenId.IntegerLiteral; do { NextChar(); } while (char.IsDigit(ch)); if (ch == '.') { id = TokenId.RealLiteral; NextChar(); ValidateDigit(); do { NextChar(); } while (char.IsDigit(ch)); } if (ch == 'E' || ch == 'e') { id = TokenId.RealLiteral; NextChar(); if (ch == '+' || ch == '-') { NextChar(); } ValidateDigit(); do { NextChar(); } while (char.IsDigit(ch)); } if (ch == 'F' || ch == 'f') { NextChar(); } } else { if (textPos != textLen) { throw ParseError(textPos, "Syntax error '{0}'", ch); } id = TokenId.End; } break; } token.id = id; token.text = text.Substring(num, textPos - num); token.pos = num; } private bool TokenIdentifierIs(string id) { if (token.id == TokenId.Identifier) { return string.Equals(id, token.text, StringComparison.OrdinalIgnoreCase); } return false; } private string GetIdentifier() { ValidateToken(TokenId.Identifier, "Identifier expected"); string text = token.text; if (text.Length > 1 && text[0] == '@') { text = text.Substring(1); } return text; } private void ValidateDigit() { if (!char.IsDigit(ch)) { throw ParseError(textPos, "Digit expected"); } } private void ValidateToken(TokenId t, string errorMessage) { if (token.id != t) { throw ParseError(errorMessage); } } private void ValidateToken(TokenId t) { if (token.id != t) { throw ParseError("Syntax error"); } } private Exception ParseError(string format, params object[] args) { return ParseError(token.pos, format, args); } private Exception ParseError(int pos, string format, params object[] args) { return new ParseException(string.Format(CultureInfo.CurrentCulture, format, args), pos); } private static Dictionary<string, object> CreateKeywords() { Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); dictionary.Add("true", trueLiteral); dictionary.Add("false", falseLiteral); dictionary.Add("null", nullLiteral); dictionary.Add(keywordIt, keywordIt); dictionary.Add(keywordIif, keywordIif); dictionary.Add(keywordNew, keywordNew); Type[] array = predefinedTypes; foreach (Type type in array) { dictionary.Add(type.Name, type); } return dictionary; } } internal static class Res { public const string DuplicateIdentifier = "The identifier '{0}' was defined more than once"; public const string ExpressionTypeMismatch = "Expression of type '{0}' expected"; public const string ExpressionExpected = "Expression expected"; public const string InvalidCharacterLiteral = "Character literal must contain exactly one character"; public const string InvalidIntegerLiteral = "Invalid integer literal '{0}'"; public const string InvalidRealLiteral = "Invalid real literal '{0}'"; public const string UnknownIdentifier = "Unknown identifier '{0}'"; public const string NoItInScope = "No 'it' is in scope"; public const string IifRequiresThreeArgs = "The 'iif' function requires three arguments"; public const string FirstExprMustBeBool = "The first expression must be of type 'Boolean'"; public const string BothTypesConvertToOther = "Both of the types '{0}' and '{1}' convert to the other"; public const string NeitherTypeConvertsToOther = "Neither of the types '{0}' and '{1}' converts to the other"; public const string MissingAsClause = "Expression is missing an 'as' clause"; public const string ArgsIncompatibleWithLambda = "Argument list incompatible with lambda expression"; public const string TypeHasNoNullableForm = "Type '{0}' has no nullable form"; public const string NoMatchingConstructor = "No matching constructor in type '{0}'"; public const string AmbiguousConstructorInvocation = "Ambiguous invocation of '{0}' constructor"; public const string CannotConvertValue = "A value of type '{0}' cannot be converted to type '{1}'"; public const string NoApplicableMethod = "No applicable method '{0}' exists in type '{1}'"; public const string MethodsAreInaccessible = "Methods on type '{0}' are not accessible"; public const string MethodIsVoid = "Method '{0}' in type '{1}' does not return a value"; public const string AmbiguousMethodInvocation = "Ambiguous invocation of method '{0}' in type '{1}'"; public const string UnknownPropertyOrField = "No property or field '{0}' exists in type '{1}'"; public const string NoApplicableAggregate = "No applicable aggregate method '{0}' exists"; public const string CannotIndexMultiDimArray = "Indexing of multi-dimensional arrays is not supported"; public const string InvalidIndex = "Array index must be an integer expression"; public const string NoApplicableIndexer = "No applicable indexer exists in type '{0}'"; public const string AmbiguousIndexerInvocation = "Ambiguous invocation of indexer in type '{0}'"; public const string IncompatibleOperand = "Operator '{0}' incompatible with operand type '{1}'"; public const string IncompatibleOperands = "Operator '{0}' incompatible with operand types '{1}' and '{2}'"; public const string UnterminatedStringLiteral = "Unterminated string literal"; public const string InvalidCharacter = "Syntax error '{0}'"; public const string DigitExpected = "Digit expected"; public const string SyntaxError = "Syntax error"; public const string TokenExpected = "{0} expected"; public const string ParseExceptionFormat = "{0} (at index {1})"; public const string ColonExpected = "':' expected"; public const string OpenParenExpected = "'(' expected"; public const string CloseParenOrOperatorExpected = "')' or operator expected"; public const string CloseParenOrCommaExpected = "')' or ',' expected"; public const string DotOrOpenParenExpected = "'.' or '(' expected"; public const string OpenBracketExpected = "'[' expected"; public const string CloseBracketOrCommaExpected = "']' or ',' expected"; public const string IdentifierExpected = "Identifier expected"; } } namespace SimpleJSON { public enum JSONNodeType { Array = 1, Object = 2, String = 3, Number = 4, NullValue = 5, Boolean = 6, None = 7, Custom = 255 } public enum JSONTextMode { Compact, Indent } public abstract class JSONNode { public struct Enumerator { private enum Type { None, Array, Object } private Type type; private Dictionary<string, JSONNode>.Enumerator m_Object; private List<JSONNode>.Enumerator m_Array; public bool IsValid => type != Type.None; public KeyValuePair<string, JSONNode> Current { get { if (type == Type.Array) { return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current); } if (type == Type.Object) { return m_Object.Current; } return new KeyValuePair<string, JSONNode>(string.Empty, null); } } public Enumerator(List<JSONNode>.Enumerator aArrayEnum) { type = Type.Array; m_Object = default(Dictionary<string, JSONNode>.Enumerator); m_Array = aArrayEnum; } public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) { type = Type.Object; m_Object = aDictEnum; m_Array = default(List<JSONNode>.Enumerator); } public bool MoveNext() { if (type == Type.Array) { return m_Array.MoveNext(); } if (type == Type.Object) { return m_Object.MoveNext(); } return false; } } public struct ValueEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Value; public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public ValueEnumerator GetEnumerator() { return this; } } public struct KeyEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Key; public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public KeyEnumerator GetEnumerator() { return this; } } public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable { private JSONNode m_Node; private Enumerator m_Enumerator; public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current; object IEnumerator.Current => m_Enumerator.Current; internal LinqEnumerator(JSONNode aNode) { m_Node = aNode; if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } public bool MoveNext() { return m_Enumerator.MoveNext(); } public void Dispose() { m_Node = null; m_Enumerator = default(Enumerator); } public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator() { return new LinqEnumerator(m_Node); } public void Reset() { if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { return new LinqEnumerator(m_Node); } } public static bool forceASCII; [ThreadStatic] private static StringBuilder m_EscapeBuilder; public abstract JSONNodeType Tag { get; } public virtual JSONNode this[int aIndex] { get { return null; } set { } } public virtual JSONNode this[string aKey] { get { return null; } set { } } public virtual string Value { get { return ""; } set { } } public virtual int Count => 0; public virtual bool IsNumber => false; public virtual bool IsString => false; public virtual bool IsBoolean => false; public virtual bool IsNull => false; public virtual bool IsArray => false; public virtual bool IsObject => false; public virtual bool Inline { get { return false; } set { } } public virtual IEnumerable<JSONNode> Children { get { yield break; } } public IEnumerable<JSONNode> DeepChildren { get { foreach (JSONNode child in Children) { foreach (JSONNode deepChild in child.DeepChildren) { yield return deepChild; } } } } public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this); public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator()); public ValueEnumerator Values => new ValueEnumerator(GetEnumerator()); public virtual double AsDouble { get { double result = 0.0; if (double.TryParse(Value, out result)) { return result; } return 0.0; } set { Value = value.ToString(); } } public virtual int AsInt { get { return (int)AsDouble; } set { AsDouble = value; } } public virtual float AsFloat { get { return (float)AsDouble; } set { AsDouble = value; } } public virtual bool AsBool { get { bool result = false; if (bool.TryParse(Value, out result)) { return result; } return !string.IsNullOrEmpty(Value); } set { Value = (value ? "true" : "false"); } } public virtual JSONArray AsArray => this as JSONArray; public virtual JSONObject AsObject => this as JSONObject; internal static StringBuilder EscapeBuilder { get { if (m_EscapeBuilder == null) { m_EscapeBuilder = new StringBuilder(); } return m_EscapeBuilder; } } public virtual void Add(string aKey, JSONNode aItem) { } public virtual void Add(JSONNode aItem) { Add("", aItem); } public virtual JSONNode Remove(string aKey) { return null; } public virtual JSONNode Remove(int aIndex) { return null; } public virtual JSONNode Remove(JSONNode aNode) { return aNode; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact); return stringBuilder.ToString(); } public virtual string ToString(int aIndent) { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent); return stringBuilder.ToString(); } internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); public abstract Enumerator GetEnumerator(); public static implicit operator JSONNode(string s) { return new JSONString(s); } public static implicit operator string(JSONNode d) { if (!(d == null)) { return d.Value; } return null; } public static implicit operator JSONNode(double n) { return new JSONNumber(n); } public static implicit operator double(JSONNode d) { if (!(d == null)) { return d.AsDouble; } return 0.0; } public static implicit operator JSONNode(float n) { return new JSONNumber(n); } public static implicit operator float(JSONNode d) { if (!(d == null)) { return d.AsFloat; } return 0f; } public static implicit operator JSONNode(int n) { return new JSONNumber(n); } public static implicit operator int(JSONNode d) { if (!(d == null)) { return d.AsInt; } return 0; } public static implicit operator JSONNode(bool b) { return new JSONBool(b); } public static implicit operator bool(JSONNode d) { if (!(d == null)) { return d.AsBool; } return false; } public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue) { return aKeyValue.Value; } public static bool operator ==(JSONNode a, object b) { if ((object)a == b) { return true; } bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator; bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator; if (flag && flag2) { return true; } if (!flag) { return a.Equals(b); } return false; } public static bool operator !=(JSONNode a, object b) { return !(a == b); } public override bool Equals(object obj) { return (object)this == obj; } public override int GetHashCode() { return base.GetHashCode(); } internal static string Escape(string aText) { StringBuilder escapeBuilder = EscapeBuilder; escapeBuilder.Length = 0; if (escapeBuilder.Capacity < aText.Length + aText.Length / 10) { escapeBuilder.Capacity = aText.Length + aText.Length / 10; } foreach (char c in aText) { switch (c) { case '\\': escapeBuilder.Append("\\\\"); continue; case '"': escapeBuilder.Append("\\\""); continue; case '\n': escapeBuilder.Append("\\n"); continue; case '\r': escapeBuilder.Append("\\r"); continue; case '\t': escapeBuilder.Append("\\t"); continue; case '\b': escapeBuilder.Append("\\b"); continue; case '\f': escapeBuilder.Append("\\f"); continue; } if (c < ' ' || (forceASCII && c > '\u007f')) { ushort num = c; escapeBuilder.Append("\\u").Append(num.ToString("X4")); } else { escapeBuilder.Append(c); } } string result = escapeBuilder.ToString(); escapeBuilder.Length = 0; return result; } private static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted) { if (quoted) { ctx.Add(tokenName, token); return; } string text = token.ToLower(); switch (text) { case "false": case "true": ctx.Add(tokenName, text == "true"); return; case "null": ctx.Add(tokenName, null); return; } if (double.TryParse(token, out var result)) { ctx.Add(tokenName, result); } else { ctx.Add(tokenName, token); } } public static JSONNode Parse(string aJSON) { Stack<JSONNode> stack = new Stack<JSONNode>(); JSONNode jSONNode = null; int i = 0; StringBuilder stringBuilder = new StringBuilder(); string text = ""; bool flag = false; bool flag2 = false; for (; i < aJSON.Length; i++) { switch (aJSON[i]) { case '{': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONObject()); if (jSONNode != null) { jSONNode.Add(text, stack.Peek()); } text = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); break; case '[': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONArray()); if (jSONNode != null) { jSONNode.Add(text, stack.Peek()); } text = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); break; case ']': case '}': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stack.Count == 0) { throw new Exception("JSON Parse: Too many closing brackets"); } stack.Pop(); if (stringBuilder.Length > 0 || flag2) { ParseElement(jSONNode, stringBuilder.ToString(), text, flag2); flag2 = false; } text = ""; stringBuilder.Length = 0; if (stack.Count > 0) { jSONNode = stack.Peek(); } break; case ':': if (flag) { stringBuilder.Append(aJSON[i]); break; } text = stringBuilder.ToString(); stringBuilder.Length = 0; flag2 = false; break; case '"': flag = !flag; flag2 = flag2 || flag; break; case ',': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stringBuilder.Length > 0 || flag2) { ParseElement(jSONNode, stringBuilder.ToString(), text, flag2); flag2 = false; } text = ""; stringBuilder.Length = 0; flag2 = false; break; case '\t': case ' ': if (flag) { stringBuilder.Append(aJSON[i]); } break; case '\\': i++; if (flag) { char c = aJSON[i]; switch (c) { case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; case 'n': stringBuilder.Append('\n'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'u': { string s = aJSON.Substring(i + 1, 4); stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier)); i += 4; break; } default: stringBuilder.Append(c); break; } } break; default: stringBuilder.Append(aJSON[i]); break; case '\n': case '\r': break; } } if (flag) { throw new Exception("JSON Parse: Quotation marks seems to be messed up."); } return jSONNode; } } public class JSONArray : JSONNode { private List<JSONNode> m_List = new List<JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Array; public override bool IsArray => true; public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_List.Count) { return new JSONLazyCreator(this); } return m_List[aIndex]; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex < 0 || aIndex >= m_List.Count) { m_List.Add(value); } else { m_List[aIndex] = value; } } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this); } set { if (value == null) { value = JSONNull.CreateOrGet(); } m_List.Add(value); } } public override int Count => m_List.Count; public override IEnumerable<JSONNode> Children { get { foreach (JSONNode item in m_List) { yield return item; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } m_List.Add(aItem); } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_List.Count) { return null; } JSONNode result = m_List[aIndex]; m_List.RemoveAt(aIndex); return result; } public override JSONNode Remove(JSONNode aNode) { m_List.Remove(aNode); return aNode; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('['); int count = m_List.Count; if (inline) { aMode = JSONTextMode.Compact; } for (int i = 0; i < count; i++) { if (i > 0) { aSB.Append(','); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append(']'); } } public class JSONObject : JSONNode { private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Object; public override bool IsObject => true; public override JSONNode this[string aKey] { get { if (m_Dict.ContainsKey(aKey)) { return m_Dict[aKey]; } return new JSONLazyCreator(this, aKey); } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = value; } else { m_Dict.Add(aKey, value); } } } public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } return m_Dict.ElementAt(aIndex).Value; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex >= 0 && aIndex < m_Dict.Count) { string key = m_Dict.ElementAt(aIndex).Key; m_Dict[key] = value; } } } public override int Count => m_Dict.Count; public override IEnumerable<JSONNode> Children { get { foreach (KeyValuePair<string, JSONNode> item in m_Dict) { yield return item.Value; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } if (!string.IsNullOrEmpty(aKey)) { if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = aItem; } else { m_Dict.Add(aKey, aItem); } } else { m_Dict.Add(Guid.NewGuid().ToString(), aItem); } } public override JSONNode Remove(string aKey) { if (!m_Dict.ContainsKey(aKey)) { return null; } JSONNode result = m_Dict[aKey]; m_Dict.Remove(aKey); return result; } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex); m_Dict.Remove(keyValuePair.Key); return keyValuePair.Value; } public override JSONNode Remove(JSONNode aNode) { try { KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First(); m_Dict.Remove(keyValuePair.Key); return aNode; } catch { return null; } } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('{'); bool flag = true; if (inline) { aMode = JSONTextMode.Compact; } foreach (KeyValuePair<string, JSONNode> item in m_Dict) { if (!flag) { aSB.Append(','); } flag = false; if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"'); if (aMode == JSONTextMode.Compact) { aSB.Append(':'); } else { aSB.Append(" : "); } item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append('}'); } } public class JSONString : JSONNode { private string m_Data; public override JSONNodeType Tag => JSONNodeType.String; public override bool IsString => true; public override string Value { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONString(string aData) { m_Data = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"'); } public override bool Equals(object obj) { if (base.Equals(obj)) { return true; } if (obj is string text) { return m_Data == text; } JSONString jSONString = obj as JSONString; if (jSONString != null) { return m_Data == jSONString.m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONNumber : JSONNode { private double m_Data; public override JSONNodeType Tag => JSONNodeType.Number; public override bool IsNumber => true; public override string Value { get { return m_Data.ToString(); } set { if (double.TryParse(value, out var result)) { m_Data = result; } } } public override double AsDouble { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONNumber(double aData) { m_Data = aData; } public JSONNumber(string aData) { Value = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data); } private static bool IsNumeric(object value) { if (!(value is int) && !(value is uint) && !(value is float) && !(value is double) && !(value is decimal) && !(value is long) && !(value is ulong) && !(value is short) && !(value is ushort) && !(value is sbyte)) { return value is byte; } return true; } public override bool Equals(object obj) { if (obj == null) { return false; } if (base.Equals(obj)) { return true; } JSONNumber jSONNumber = obj as JSONNumber; if (jSONNumber != null) { return m_Data == jSONNumber.m_Data; } if (IsNumeric(obj)) { return Convert.ToDouble(obj) == m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONBool : JSONNode { private bool m_Data; public override JSONNodeType Tag => JSONNodeType.Boolean; public override bool IsBoolean => true; public override string Value { get { return m_Data.ToString(); } set { if (bool.TryParse(value, out var result)) { m_Data = result; } } } public override bool AsBool { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONBool(bool aData) { m_Data = aData; } public JSONBool(string aData) { Value = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data ? "true" : "false"); } public override bool Equals(object obj) { if (obj == null) { return false; } if (obj is bool) { return m_Data == (bool)obj; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONNull : JSONNode { private static JSONNull m_StaticInstance = new JSONNull(); public static bool reuseSameInstance = true; public override JSONNodeType Tag => JSONNodeType.NullValue; public override bool IsNull => true; public override string Value { get { return "null"; } set { } } public override bool AsBool { get { return false; } set { } } public static JSONNull CreateOrGet() { if (reuseSameInstance) { return m_StaticInstance; } return new JSONNull(); } private JSONNull() { } public override Enumerator GetEnumerator() { return default(Enumerator); } public override bool Equals(object obj) { if ((object)this == obj) { return true; } return obj is JSONNull; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } internal class JSONLazyCreator : JSONNode { private JSONNode m_Node; private string m_Key; public override JSONNodeType Tag => JSONNodeType.None; public override JSONNode this[int aIndex] { get { return new JSONLazyCreator(this); } set { JSONArray jSONArray = new JSONArray(); jSONArray.Add(value); Set(jSONArray); } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this, aKey); } set { JSONObject jSONObject = new JSONObject(); jSONObject.Add(aKey, value); Set(jSONObject); } } public override int AsInt { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override float AsFloat { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0f; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override double AsDouble { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0.0; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override bool AsBool { get { JSONBool aVal = new JSONBool(aData: false); Set(aVal); return false; } set { JSONBool aVal = new JSONBool(value); Set(aVal); } } public override JSONArray AsArray { get { JSONArray jSONArray = new JSONArray(); Set(jSONArray); return jSONArray; } } public override JSONObject AsObject { get { JSONObject jSONObject = new JSONObject(); Set(jSONObject); return jSONObject; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONLazyCreator(JSONNode aNode) { m_Node = aNode; m_Key = null; } public JSONLazyCreator(JSONNode aNode, string aKey) { m_Node = aNode; m_Key = aKey; } private void Set(JSONNode aVal) { if (m_Key == null) { m_Node.Add(aVal); } else { m_Node.Add(m_Key, aVal); } m_Node = null; } public override void Add(JSONNode aItem) { JSONArray jSONArray = new JSONArray(); jSONArray.Add(aItem); Set(jSONArray); } public override void Add(string aKey, JSONNode aItem) { JSONObject jSONObject = new JSONObject(); jSONObject.Add(aKey, aItem); Set(jSONObject); } public static bool operator ==(JSONLazyCreator a, object b) { if (b == null) { return true; } return (object)a == b; } public static bool operator !=(JSONLazyCreator a, object b) { return !(a == b); } public override bool Equals(object obj) { if (obj == null) { return true; } return (object)this == obj; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } public static class JSON { public static JSONNode Parse(string aJSON) { return JSONNode.Parse(aJSON); } } } namespace XUnity.AutoTranslator.Plugin { internal class SceneLoadInformation { public SceneInformation ActiveScene { get; set; } public List<SceneInformation> LoadedScenes { get; set; } public SceneLoadInformation() { LoadedScenes = new List<SceneInformation>(); if (UnityFeatures.SupportsSceneManager) { LoadBySceneManager(); } else { LoadByApplication(); } } public void LoadBySceneManager() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); ActiveScene = new SceneInformation(((Scene)(ref activeScene)).buildIndex, ((Scene)(ref activeScene)).name); for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); LoadedScenes.Add(new SceneInformation(((Scene)(ref sceneAt)).buildIndex, ((Scene)(ref sceneAt)).name)); } } public void LoadByApplication() { ActiveScene = new SceneInformation(Application.loadedLevel, Application.loadedLevelName); LoadedScenes.Add(new SceneInformation(Application.loadedLevel, Application.loadedLevelName)); } } internal class SceneInformation { public int Id { get; set; } public string Name { get; set; } public SceneInformation(int id, string name) { Id = id; Name = name; } } } namespace XUnity.AutoTranslator.Plugin.Utilities { internal static class TranslationScopeHelper { public static int GetScope(object ui) { if (Settings.EnableTranslationScoping) { try { Component val = (Component)((ui is Component) ? ui : null); if (val != null && Object.op_Implicit((Object)(object)val)) { return GetScopeFromComponent(val); } if (ui is GUIContent) { return -1; } return GetActiveSceneId(); } catch (MissingMemberException ex) { XuaLogger.AutoTranslator.Error((Exception)ex, "A 'missing member' error occurred while retriving translation scope. Disabling translation scopes."); Settings.EnableTranslationScoping = false; } } return -1; } private static int GetScopeFromComponent(Component component) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Scene scene = component.gameObject.scene; return ((Scene)(ref scene)).buildIndex; } public static int GetActiveSceneId() { if (UnityFeatures.SupportsSceneManager) { return GetActiveSceneIdBySceneManager(); } return GetActiveSceneIdByApplication(); } private static int GetActiveSceneIdBySceneManager() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).buildIndex; } public static void RegisterSceneLoadCallback(Action<int> sceneLoaded) { SceneManagerLoader.EnableSceneLoadScanInternal(sceneLoaded); } private static int GetActiveSceneIdByApplication() { return Application.loadedLevel; } } internal static class SceneManagerLoader { public static void EnableSceneLoadScanInternal(Action<int> sceneLoaded) { SceneManager.sceneLoaded += delegate(Scene arg1, LoadSceneMode arg2) { sceneLoaded(((Scene)(ref arg1)).buildIndex); }; } } internal static class TranslationScopes { public const int None = -1; } } namespace XUnity.AutoTranslator.Plugin.Core { public class AutoTranslationPlugin : MonoBehaviour, IMonoBehaviour, IMonoBehaviour_Update, IInternalTranslator, ITranslator, ITranslationRegistry { internal static AutoTranslationPlugin Current; private bool _hasResizedCurrentComponentDuringDiscovery; internal XuaWindow MainWindow; internal TranslationAggregatorWindow TranslationAggregatorWindow; internal TranslationAggregatorOptionsWindow TranslationAggregatorOptionsWindow; internal TranslationManager TranslationManager; internal TextTranslationCache TextCache; internal Dictionary<string, TextTranslationCache> PluginTextCaches = new Dictionary<string, TextTranslationCache>(StringComparer.OrdinalIgnoreCase); internal TextureTranslationCache TextureCache; internal UIResizeCache ResizeCache; internal SpamChecker SpamChecker; private Dictionary<string, UntranslatedText> CachedKeys = new Dictionary<string, UntranslatedText>(StringComparer.Ordinal); private List<Action<ComponentTranslationContext>> _shouldIgnore = new List<Action<ComponentTranslationContext>>(); private List<string> _textsToCopyToClipboardOrdered = new List<string>(); private HashSet<string> _textsToCopyToClipboard = new HashSet<string>(); private float _clipboardUpdated; private HashSet<string> _immediatelyTranslating = new HashSet<string>(); private bool _isInTranslatedMode = true; private bool _textHooksEnabled = true; private float _batchOperationSecondCounter; private bool _hasValidOverrideFont; private bool _hasOverridenFont; private bool _initialized; private bool _started; private bool _temporarilyDisabled; private string _requireSpriteRendererCheckCausedBy; private int _lastSpriteUpdateFrame = -1; private bool _isCalledFromSceneManager; private bool _translationReloadRequest; private bool _hasUiBeenSetup; private static bool _inputSupported = true; public void Initialize() { Current = this; Paths.Initialize(); HarmonyLoader.Load(); Settings.Configure(); DebugConsole.Enable(); InitializeHarmonyDetourBridge(); InitializeTextTranslationCaches(); HooksSetup.InstallTextHooks(); HooksSetup.InstallImageHooks(); HooksSetup.InstallSpriteRendererHooks(); HooksSetup.InstallTextGetterCompatHooks(); HooksSetup.InstallComponentBasedPluginTranslationHooks(); TextureCache = new TextureTranslationCache(); TextureCache.TextureTranslationFileChanged += TextureCache_TextureTranslationFileChanged; ResizeCache = new UIResizeCache(); TranslationManager = new TranslationManager(); TranslationManager.JobCompleted += OnJobCompleted; TranslationManager.JobFailed += OnJobFailed; TranslationManager.InitializeEndpoints(); SpamChecker = new SpamChecker(TranslationManager); UnityTextParsers.Initialize(); InitializeResourceRedirector(); ValidateConfiguration(); EnableSceneLoadScan(); LoadFallbackFont(); LoadTranslations(reload: false); XuaLogger.AutoTranslator.Info("Loaded XUnity.AutoTranslator into Unity [" + Application.unityVersion + "] game."); } private static void LoadFallbackFont() { try { if (!string.IsNullOrEmpty(Settings.FallbackFontTextMeshPro)) { Object orCreateFallbackFontTextMeshPro = FontCache.GetOrCreateFallbackFontTextMeshPro(); if (TMP_Settings_Properties.FallbackFontAssets == null) { XuaLogger.AutoTranslator.Info("Cannot use fallback font because it is not supported in this version."); return; } if (orCreateFallbackFontTextMeshPro == (Object)null) { XuaLogger.AutoTranslator.Warn("Could not load fallback font for TextMesh Pro: " + Settings.FallbackFontTextMeshPro); return; } ((IList)TMP_Settings_Properties.FallbackFontAssets.Get((object)null)).Add(orCreateFallbackFontTextMeshPro); XuaLogger.AutoTranslator.Info("Loaded fallback font for TextMesh Pro: " + Settings.FallbackFontTextMeshPro); } } catch (Exception ex) { XuaLogger.AutoTranslator.Error(ex, "An error occurred while trying to load fallback font for TextMesh Pro."); } } private static void InitializeHarmonyDetourBridge() { try { if (Settings.InitializeHarmonyDetourBridge) { InitializeHarmonyDetourBridgeSafe(); } } catch (Exception ex) { XuaLogger.AutoTranslator.Error(ex, "An error occurred while initializing harmony detour bridge."); } } private static void InitializeHarmonyDetourBridgeSafe() { HarmonyDetourBridge.Init(true, (Type)0); } private void InitializeTextTranslationCaches() { try { TextCache = new TextTranslationCache(); TextCache.TextTranslationFileChanged += TextCache_TextTranslationFileChanged; DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Settings.TranslationsPath, "plugins")); if (directoryInfo.Exists) { DirectoryInfo[] directories = directoryInfo.GetDirectories(); foreach (DirectoryInfo directoryInfo2 in directories) { TextTranslationCache value = new TextTranslationCache(directoryInfo2); PluginTextCaches.Add(directoryInfo2.Name, value); } } } catch (Exception ex) { XuaLogger.AutoTranslator.Error(ex, "An error occurred while initializing text translation caches."); } } private void TextCache_TextTranslationFileChanged() { _translationReloadRequest = true; } private void TextureCache_TextureTranslationFileChanged() { _translationReloadRequest = true; } private static void EnableLogAllLoadedResources() { ResourceRedirection.LogAllLoadedResources = true; } private void EnableTextAssetLoadedHandler() { new TextAssetLoadedHandler(); } private void InitializeResourceRedirector() { try { if (Settings.LogAllLoadedResources) { EnableLogAllLoadedResources(); } if (Settings.EnableTextAssetRedirector) { EnableTextAssetLoadedHandler(); } } catch (Exception ex) { XuaLogger.AutoTranslator.Error(ex, "An error occurred while initializing resource redirectors."); } } private void InitializeGUI() {
BepInEx/plugins/XUnity.AutoTranslator/XUnity.AutoTranslator.Plugin.ExtProtocol.dll
Decompiled 10 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Package that contains a simple inter-process protocol format used in XUnity.")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.ExtProtocol")] [assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.ExtProtocol")] [assembly: AssemblyVersion("1.0.1.0")] namespace XUnity.AutoTranslator.Plugin.ExtProtocol; public class ConfigurationMessage : ProtocolMessage { public static readonly string Type = "4"; public string Config { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); Config = reader.ReadToEnd(); } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.Write(Config); } } public static class ExtProtocolConvert { private static readonly Dictionary<string, Type> IdToType; private static readonly Dictionary<Type, string> TypeToId; static ExtProtocolConvert() { IdToType = new Dictionary<string, Type>(); TypeToId = new Dictionary<Type, string>(); Register(TranslationRequest.Type, typeof(TranslationRequest)); Register(TranslationResponse.Type, typeof(TranslationResponse)); Register(TranslationError.Type, typeof(TranslationError)); Register(ConfigurationMessage.Type, typeof(ConfigurationMessage)); } public static void Register(string id, Type type) { IdToType[id] = type; TypeToId[type] = id; } public static string Encode(ProtocolMessage message) { StringWriter stringWriter = new StringWriter(); string value = TypeToId[message.GetType()]; stringWriter.WriteLine(value); message.Encode(stringWriter); return Convert.ToBase64String(Encoding.UTF8.GetBytes(stringWriter.ToString()), Base64FormattingOptions.None); } public static ProtocolMessage Decode(string message) { StringReader stringReader = new StringReader(Encoding.UTF8.GetString(Convert.FromBase64String(message))); string key = stringReader.ReadLine(); ProtocolMessage obj = (ProtocolMessage)Activator.CreateInstance(IdToType[key]); obj.Decode(stringReader); return obj; } } public abstract class ProtocolMessage { public Guid Id { get; set; } internal abstract void Decode(TextReader reader); internal abstract void Encode(TextWriter writer); } public enum StatusCode { OK = 0, Blocked = 1, Unknown = 1000 } public class TranslationError : ProtocolMessage { public static readonly string Type = "3"; public string Reason { get; set; } public StatusCode FailureCode { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); FailureCode = (StatusCode)int.Parse(reader.ReadLine()); Reason = reader.ReadToEnd(); } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine((int)FailureCode); writer.Write(Reason); } } public class TranslationRequest : ProtocolMessage { public static readonly string Type = "1"; private string[] _untranslatedTexts; public string SourceLanguage { get; set; } public string DestinationLanguage { get; set; } public string[] UntranslatedTexts => _untranslatedTexts ?? (_untranslatedTexts = UntranslatedTextInfos.Select((TransmittableUntranslatedTextInfo x) => x.UntranslatedText).ToArray()); public TransmittableUntranslatedTextInfo[] UntranslatedTextInfos { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); SourceLanguage = reader.ReadLine(); DestinationLanguage = reader.ReadLine(); int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); TransmittableUntranslatedTextInfo[] array = new TransmittableUntranslatedTextInfo[num]; for (int i = 0; i < num; i++) { TransmittableUntranslatedTextInfo transmittableUntranslatedTextInfo = new TransmittableUntranslatedTextInfo(); transmittableUntranslatedTextInfo.Decode(reader); array[i] = transmittableUntranslatedTextInfo; } UntranslatedTextInfos = array; } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine(SourceLanguage); writer.WriteLine(DestinationLanguage); writer.WriteLine(UntranslatedTextInfos.Length.ToString(CultureInfo.InvariantCulture)); TransmittableUntranslatedTextInfo[] untranslatedTextInfos = UntranslatedTextInfos; for (int i = 0; i < untranslatedTextInfos.Length; i++) { untranslatedTextInfos[i].Encode(writer); } } } public class TranslationResponse : ProtocolMessage { public static readonly string Type = "2"; public string[] TranslatedTexts { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array = new string[num]; for (int i = 0; i < num; i++) { string s = reader.ReadLine(); string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s)); array[i] = @string; } TranslatedTexts = array; } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine(TranslatedTexts.Length.ToString(CultureInfo.InvariantCulture)); string[] translatedTexts = TranslatedTexts; foreach (string s in translatedTexts) { string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None); writer.WriteLine(value); } } } public class TransmittableUntranslatedTextInfo { public string[] ContextBefore { get; set; } public string UntranslatedText { get; set; } public string[] ContextAfter { get; set; } public TransmittableUntranslatedTextInfo(string[] contextBefore, string untranslatedText, string[] contextAfter) { ContextBefore = contextBefore; UntranslatedText = untranslatedText; ContextAfter = contextAfter; } public TransmittableUntranslatedTextInfo() { } internal void Encode(TextWriter writer) { string[] contextBefore = ContextBefore; writer.WriteLine(((contextBefore != null) ? contextBefore.Length : 0).ToString(CultureInfo.InvariantCulture)); if (ContextBefore != null) { string[] contextBefore2 = ContextBefore; foreach (string s in contextBefore2) { string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None); writer.WriteLine(value); } } string[] contextAfter = ContextAfter; writer.WriteLine(((contextAfter != null) ? contextAfter.Length : 0).ToString(CultureInfo.InvariantCulture)); if (ContextAfter != null) { string[] contextBefore2 = ContextAfter; foreach (string s2 in contextBefore2) { string value2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(s2), Base64FormattingOptions.None); writer.WriteLine(value2); } } string value3 = Convert.ToBase64String(Encoding.UTF8.GetBytes(UntranslatedText), Base64FormattingOptions.None); writer.WriteLine(value3); } internal void Decode(TextReader reader) { int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array = new string[num]; for (int i = 0; i < num; i++) { string s = reader.ReadLine(); string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s)); array[i] = @string; } ContextBefore = array; int num2 = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array2 = new string[num2]; for (int j = 0; j < num2; j++) { string s2 = reader.ReadLine(); string string2 = Encoding.UTF8.GetString(Convert.FromBase64String(s2)); array2[j] = string2; } ContextAfter = array2; string s3 = reader.ReadLine(); string string3 = Encoding.UTF8.GetString(Convert.FromBase64String(s3)); UntranslatedText = string3; } }
BepInEx/plugins/XUnity.ResourceRedirector/XUnity.ResourceRedirector.BepInEx.dll
Decompiled 10 months agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("XUnity.ResourceRedirector.BepInEx")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.1.0.0")] [assembly: AssemblyInformationalVersion("2.1.0")] [assembly: AssemblyProduct("XUnity.ResourceRedirector.BepInEx")] [assembly: AssemblyTitle("XUnity.ResourceRedirector.BepInEx")] [assembly: AssemblyVersion("2.1.0.0")] namespace XUnity.ResourceRedirector.BepInEx; [BepInPlugin("gravydevsupreme.xunity.resourceredirector", "XUnity Resource Redirector", "2.1.0")] public class ResourceRedirectorPlugin : BaseUnityPlugin { public static ConfigEntry<bool> LogAllLoadedResources { get; set; } public static ConfigEntry<bool> LogCallbackOrder { get; set; } private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown LogAllLoadedResources = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Diagnostics", "Log all loaded resources"), false, (ConfigDescription)null); ResourceRedirection.LogAllLoadedResources = LogAllLoadedResources.Value; LogAllLoadedResources.SettingChanged += delegate { ResourceRedirection.LogAllLoadedResources = LogAllLoadedResources.Value; }; LogCallbackOrder = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Diagnostics", "Log callback order"), false, (ConfigDescription)null); ResourceRedirection.LogCallbackOrder = LogCallbackOrder.Value; LogCallbackOrder.SettingChanged += delegate { ResourceRedirection.LogCallbackOrder = LogCallbackOrder.Value; }; ((BaseUnityPlugin)this).Config.ConfigReloaded += Config_ConfigReloaded; } private static void Config_ConfigReloaded(object sender, EventArgs e) { ResourceRedirection.LogAllLoadedResources = LogAllLoadedResources.Value; ResourceRedirection.LogCallbackOrder = LogCallbackOrder.Value; } }
BepInEx/plugins/XUnity.ResourceRedirector/XUnity.ResourceRedirector.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; using UnityEngine; using XUnity.Common.Constants; using XUnity.Common.Extensions; using XUnity.Common.Harmony; using XUnity.Common.Logging; using XUnity.Common.MonoMod; using XUnity.Common.Utilities; using XUnity.ResourceRedirector.Constants; using XUnity.ResourceRedirector.Hooks; using XUnity.ResourceRedirector.Properties; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Main development dependency for XUnity Resource Redirector.")] [assembly: AssemblyFileVersion("2.1.0.0")] [assembly: AssemblyInformationalVersion("2.1.0")] [assembly: AssemblyProduct("XUnity.ResourceRedirector")] [assembly: AssemblyTitle("XUnity.ResourceRedirector")] [assembly: AssemblyVersion("2.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace XUnity.ResourceRedirector { internal class AssetBundleExtensionData { private string _normalizedPath; private string _path; public string NormalizedPath { get { if (Path != null && _normalizedPath == null) { _normalizedPath = StringExtensions.MakeRelativePath(Path.ToLowerInvariant(), EnvironmentEx.LoweredCurrentDirectory); } return _normalizedPath; } } public string Path { get { return _path; } set { if (_path != value) { _path = value; _normalizedPath = null; } } } } public static class AssetBundleHelper { internal static string PathForLoadedInMemoryBundle; public static AssetBundle CreateEmptyAssetBundle() { byte[] empty = Resources.empty; CabHelper.RandomizeCab(empty); return AssetBundle.LoadFromMemory(empty); } public static AssetBundleCreateRequest CreateEmptyAssetBundleRequest() { byte[] empty = Resources.empty; CabHelper.RandomizeCab(empty); return AssetBundle.LoadFromMemoryAsync(empty); } public static AssetBundle LoadFromMemory(string path, byte[] binary, uint crc) { try { PathForLoadedInMemoryBundle = path; return AssetBundle.LoadFromMemory(binary, crc); } finally { PathForLoadedInMemoryBundle = null; } } public static AssetBundleCreateRequest LoadFromMemoryAsync(string path, byte[] binary, uint crc) { try { PathForLoadedInMemoryBundle = path; return AssetBundle.LoadFromMemoryAsync(binary, crc); } finally { PathForLoadedInMemoryBundle = null; } } public static AssetBundle LoadFromFileWithRandomizedCabIfRequired(string path, uint crc, ulong offset) { return LoadFromFileWithRandomizedCabIfRequired(path, crc, offset, confirmFileExists: true); } internal static AssetBundle LoadFromFileWithRandomizedCabIfRequired(string path, uint crc, ulong offset, bool confirmFileExists) { AssetBundle val = AssetBundle.LoadFromFile(path, crc, offset); if ((Object)(object)val == (Object)null && (!confirmFileExists || File.Exists(path))) { byte[] array; using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read)) { long num = fileStream.Length - (long)offset; fileStream.Seek((long)offset, SeekOrigin.Begin); array = StreamExtensions.ReadFully((Stream)fileStream, (int)num); } CabHelper.RandomizeCabWithAnyLength(array); XuaLogger.ResourceRedirector.Warn("Randomized CAB for '" + path + "' in order to load it because another asset bundle already uses its CAB-string. You can ignore the previous error message, but this is likely caused by two mods incorrectly using the same CAB-string."); return AssetBundle.LoadFromMemory(array); } return val; } } public class AssetBundleLoadedContext { private string _normalizedPath; public AssetBundleLoadingParameters Parameters { get; } public AssetBundle Bundle { get; set; } internal bool SkipRemainingPostfixes { get; private set; } internal AssetBundleLoadedContext(AssetBundleLoadingParameters parameters, AssetBundle bundle) { Parameters = parameters; Bundle = bundle; } public string GetNormalizedPath() { if (_normalizedPath == null && Parameters.Path != null) { _normalizedPath = StringExtensions.MakeRelativePath(StringExtensions.UseCorrectDirectorySeparators(Parameters.Path.ToLowerInvariant()), EnvironmentEx.LoweredCurrentDirectory); } return _normalizedPath; } public void Complete(bool skipRemainingPostfixes = true) { SkipRemainingPostfixes = skipRemainingPostfixes; } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class AssetBundleLoadingContext : IAssetBundleLoadingContext { private string _normalizedPath; public AssetBundleLoadingParameters Parameters { get; } public AssetBundle Bundle { get; set; } internal bool SkipRemainingPrefixes { get; private set; } internal bool SkipOriginalCall { get; private set; } internal bool SkipAllPostfixes { get; private set; } internal AssetBundleLoadingContext(AssetBundleLoadingParameters parameters) { Parameters = parameters; } public string GetNormalizedPath() { if (_normalizedPath == null && Parameters.Path != null) { _normalizedPath = StringExtensions.MakeRelativePath(StringExtensions.UseCorrectDirectorySeparators(Parameters.Path.ToLowerInvariant()), EnvironmentEx.LoweredCurrentDirectory); } return _normalizedPath; } public void Complete() { Complete(skipRemainingPrefixes: true, true, true); } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true) { Complete(skipRemainingPrefixes, skipOriginalCall, true); } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true) { SkipRemainingPrefixes = skipRemainingPrefixes; if (skipOriginalCall.HasValue) { SkipOriginalCall = skipOriginalCall.Value; } if (skipAllPostfixes.HasValue) { SkipAllPostfixes = skipAllPostfixes.Value; } } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class AssetBundleLoadingParameters { public string Path { get; set; } public uint Crc { get; set; } public ulong Offset { get; set; } public Stream Stream { get; set; } public uint ManagedReadBufferSize { get; } public byte[] Binary { get; set; } public AssetBundleLoadType LoadType { get; } internal AssetBundleLoadingParameters(byte[] data, string path, uint crc, ulong offset, Stream stream, uint managedReadBufferSize, AssetBundleLoadType loadType) { Binary = data; Path = path; Crc = crc; Offset = offset; Stream = stream; ManagedReadBufferSize = managedReadBufferSize; LoadType = loadType; } } public enum AssetBundleLoadType { LoadFromFile = 1, LoadFromMemory, LoadFromStream } public class AssetLoadedContext : IAssetOrResourceLoadedContext { private AssetBundleExtensionData _ext; private bool _lookedForExt; private BackingFieldOrArray _backingField; public AssetLoadedParameters Parameters { get; } public AssetBundle Bundle { get; } public Object[] Assets { get { return _backingField.Array; } set { _backingField.Array = value; } } public Object Asset { get { return _backingField.Field; } set { _backingField.Field = value; } } internal bool SkipRemainingPostfixes { get; private set; } internal AssetLoadedContext(AssetLoadedParameters parameters, AssetBundle bundle, Object[] assets) { Parameters = parameters; Bundle = bundle; _backingField = new BackingFieldOrArray(assets); } internal AssetLoadedContext(AssetLoadedParameters parameters, AssetBundle bundle, Object asset) { Parameters = parameters; Bundle = bundle; _backingField = new BackingFieldOrArray(asset); } public bool HasReferenceBeenRedirectedBefore(Object asset) { return ExtensionDataHelper.GetExtensionData<ResourceExtensionData>((object)asset)?.HasBeenRedirected ?? false; } public string GetUniqueFileSystemAssetPath(Object asset) { ResourceExtensionData orCreateExtensionData = ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)asset); if (orCreateExtensionData.FullFileSystemAssetPath == null) { string text = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle)?.NormalizedPath; string path = (string.IsNullOrEmpty(text) ? "unnamed_assetbundle" : text.ToLowerInvariant()); string name = asset.name; if (!string.IsNullOrEmpty(name)) { path = Path.Combine(path, name.ToLowerInvariant()); } else { string text2 = null; if (Assets.Length > 1) { int num = Array.IndexOf(Assets, asset); text2 = ((num != -1) ? ("_" + num.ToString(CultureInfo.InvariantCulture)) : "_with_unknown_index"); } path = Path.Combine(path, (Parameters.LoadType == AssetLoadType.LoadMainAsset) ? "main_asset" : ("unnamed_asset" + text2)); } path = StringExtensions.UseCorrectDirectorySeparators(path); orCreateExtensionData.FullFileSystemAssetPath = path; } return orCreateExtensionData.FullFileSystemAssetPath; } public string GetAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.Path; } public string GetNormalizedAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.NormalizedPath; } public void Complete(bool skipRemainingPostfixes = true) { SkipRemainingPostfixes = skipRemainingPostfixes; } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class AssetLoadedParameters { public string Name { get; } public Type Type { get; } public AssetLoadType LoadType { get; } internal AssetLoadedParameters(string name, Type type, AssetLoadType loadType) { Name = name; Type = type; LoadType = loadType; } } public class AssetLoadingContext : IAssetLoadingContext { private AssetBundleExtensionData _ext; private bool _lookedForExt; private BackingFieldOrArray _backingField; public AssetLoadingParameters Parameters { get; } public AssetBundle Bundle { get; } public Object[] Assets { get { return _backingField.Array; } set { _backingField.Array = value; } } public Object Asset { get { return _backingField.Field; } set { _backingField.Field = value; } } internal bool SkipRemainingPrefixes { get; private set; } internal bool SkipOriginalCall { get; private set; } internal bool SkipAllPostfixes { get; private set; } internal AssetLoadingContext(AssetLoadingParameters parameters, AssetBundle bundle) { Parameters = parameters; Bundle = bundle; } public string GetAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.Path; } public string GetNormalizedAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.NormalizedPath; } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true) { SkipRemainingPrefixes = skipRemainingPrefixes; if (skipOriginalCall.HasValue) { SkipOriginalCall = skipOriginalCall.Value; } if (skipAllPostfixes.HasValue) { SkipAllPostfixes = skipAllPostfixes.Value; } } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class AssetLoadingParameters { public string Name { get; set; } public Type Type { get; set; } public AssetLoadType LoadType { get; } internal AssetLoadingParameters(string name, Type type, AssetLoadType loadType) { Name = name; Type = type; LoadType = loadType; } internal AssetLoadedParameters ToAssetLoadedParameters() { return new AssetLoadedParameters(Name, Type, LoadType); } } public enum AssetLoadType { LoadMainAsset = 1, LoadByType, LoadNamed, LoadNamedWithSubAssets } internal class AsyncAssetBundleLoadInfo { public AssetBundleLoadingParameters Parameters { get; } public AssetBundle Bundle { get; } public bool SkipAllPostfixes { get; } public AsyncAssetBundleLoadingResolve ResolveType { get; } public AsyncAssetBundleLoadInfo(AssetBundleLoadingParameters parameters, AssetBundle bundle, bool skipAllPostfixes, AsyncAssetBundleLoadingResolve resolveType) { Parameters = parameters; Bundle = bundle; SkipAllPostfixes = skipAllPostfixes; ResolveType = resolveType; } } public class AsyncAssetBundleLoadingContext : IAssetBundleLoadingContext { private string _normalizedPath; private AssetBundle _bundle; private AssetBundleCreateRequest _request; public AssetBundleLoadingParameters Parameters { get; } public AssetBundleCreateRequest Request { get { return _request; } set { _request = value; ResolveType = AsyncAssetBundleLoadingResolve.ThroughRequest; } } public AssetBundle Bundle { get { return _bundle; } set { if (!ResourceRedirection.SyncOverAsyncEnabled) { throw new InvalidOperationException("Trying to set the Bundle property in async load operation while 'SyncOverAsyncAssetLoads' is disabled is not allowed. Consider settting the Request property instead if possible or enabling 'SyncOverAsyncAssetLoads' through the method 'ResourceRedirection.EnableSyncOverAsyncAssetLoads()'."); } _bundle = value; ResolveType = AsyncAssetBundleLoadingResolve.ThroughBundle; } } public AsyncAssetBundleLoadingResolve ResolveType { get; set; } internal bool SkipRemainingPrefixes { get; private set; } internal bool SkipOriginalCall { get; set; } internal bool SkipAllPostfixes { get; private set; } internal AsyncAssetBundleLoadingContext(AssetBundleLoadingParameters parameters) { Parameters = parameters; } public string GetNormalizedPath() { if (_normalizedPath == null && Parameters.Path != null) { _normalizedPath = StringExtensions.MakeRelativePath(StringExtensions.UseCorrectDirectorySeparators(Parameters.Path.ToLowerInvariant()), EnvironmentEx.LoweredCurrentDirectory); } return _normalizedPath; } public void Complete() { Complete(skipRemainingPrefixes: true, true, true); } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true) { Complete(skipRemainingPrefixes, skipOriginalCall, true); } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true) { SkipRemainingPrefixes = skipRemainingPrefixes; if (skipOriginalCall.HasValue) { SkipOriginalCall = skipOriginalCall.Value; } if (skipAllPostfixes.HasValue) { SkipAllPostfixes = skipAllPostfixes.Value; } } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public enum AsyncAssetBundleLoadingResolve { ThroughRequest, ThroughBundle } internal class AsyncAssetLoadInfo { public AssetLoadingParameters Parameters { get; } public AssetBundle Bundle { get; } public bool SkipAllPostfixes { get; } public AsyncAssetLoadingResolve ResolveType { get; } public Object[] Assets { get; } public AsyncAssetLoadInfo(AssetLoadingParameters parameters, AssetBundle bundle, bool skipAllPostfixes, AsyncAssetLoadingResolve resolveType, Object[] assets) { Parameters = parameters; Bundle = bundle; SkipAllPostfixes = skipAllPostfixes; ResolveType = resolveType; Assets = assets; } } public class AsyncAssetLoadingContext : IAssetLoadingContext { private AssetBundleExtensionData _ext; private bool _lookedForExt; private Object[] _assets; private AssetBundleRequest _request; private BackingFieldOrArray _backingField; public AssetLoadingParameters Parameters { get; } public AssetBundle Bundle { get; } public AssetBundleRequest Request { get { return _request; } set { _request = value; ResolveType = AsyncAssetLoadingResolve.ThroughRequest; } } public Object[] Assets { get { return _backingField.Array; } set { if (!ResourceRedirection.SyncOverAsyncEnabled) { throw new InvalidOperationException("Trying to set the Assets/Asset property in async load operation while 'SyncOverAsyncAssetLoads' is disabled is not allowed. Consider settting the Request property instead if possible or enabling 'SyncOverAsyncAssetLoads' through the method 'ResourceRedirection.EnableSyncOverAsyncAssetLoads()'."); } _backingField.Array = value; ResolveType = AsyncAssetLoadingResolve.ThroughAssets; } } public Object Asset { get { return _backingField.Field; } set { if (!ResourceRedirection.SyncOverAsyncEnabled) { throw new InvalidOperationException("Trying to set the Assets/Asset property in async load operation while 'SyncOverAsyncAssetLoads' is disabled is not allowed. Consider settting the Request property instead if possible or enabling 'SyncOverAsyncAssetLoads' through the method 'ResourceRedirection.EnableSyncOverAsyncAssetLoads()'."); } _backingField.Field = value; ResolveType = AsyncAssetLoadingResolve.ThroughAssets; } } public AsyncAssetLoadingResolve ResolveType { get; set; } internal bool SkipRemainingPrefixes { get; private set; } internal bool SkipOriginalCall { get; set; } internal bool SkipAllPostfixes { get; private set; } internal AsyncAssetLoadingContext(AssetLoadingParameters parameters, AssetBundle bundle) { Parameters = parameters; Bundle = bundle; } public string GetAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.Path; } public string GetNormalizedAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.NormalizedPath; } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true) { SkipRemainingPrefixes = skipRemainingPrefixes; if (skipOriginalCall.HasValue) { SkipOriginalCall = skipOriginalCall.Value; } if (skipAllPostfixes.HasValue) { SkipAllPostfixes = skipAllPostfixes.Value; } } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public enum AsyncAssetLoadingResolve { ThroughRequest, ThroughAssets } internal struct BackingFieldOrArray { private Object _field; private Object[] _array; private BackingSource _source; public Object Field { get { if (_source == BackingSource.None) { return null; } if (_source == BackingSource.SingleField) { return _field; } if (_array == null || _array.Length == 0) { return null; } return _array[0]; } set { _field = value; _array = null; _source = BackingSource.SingleField; } } public Object[] Array { get { if (_source == BackingSource.Array) { return _array; } if (_field == (Object)null) { Array = (Object[])(object)new Object[0]; } else { Array = (Object[])(object)new Object[1] { _field }; } return _array; } set { _field = null; _array = value; _source = BackingSource.Array; } } public BackingFieldOrArray(Object field) { _field = field; _array = null; _source = BackingSource.SingleField; } public BackingFieldOrArray(Object[] array) { _field = null; _array = array; _source = BackingSource.Array; } public IEnumerable<Object> IterateObjects() { if (_array != null) { Object[] array = _array; for (int i = 0; i < array.Length; i++) { yield return array[i]; } } else if (_field != (Object)null) { yield return _field; } } } internal enum BackingSource : byte { None, SingleField, Array } public static class CallbackPriority { public const int Default = 0; } public enum HookBehaviour { OneCallbackPerLoadCall = 1, OneCallbackPerResourceLoaded } public interface IAssetBundleLoadingContext { AssetBundleLoadingParameters Parameters { get; } AssetBundle Bundle { get; set; } string GetNormalizedPath(); void Complete(); void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true); void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true); void DisableRecursion(); } public interface IAssetLoadingContext { AssetLoadingParameters Parameters { get; } AssetBundle Bundle { get; } Object[] Assets { get; set; } Object Asset { get; set; } string GetAssetBundlePath(); string GetNormalizedAssetBundlePath(); void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true); void DisableRecursion(); } public interface IAssetOrResourceLoadedContext { Object[] Assets { get; set; } Object Asset { get; set; } bool HasReferenceBeenRedirectedBefore(Object asset); string GetUniqueFileSystemAssetPath(Object asset); void Complete(bool skipRemainingPostfixes = true); void DisableRecursion(); } internal class PrioritizedCallback { public static PrioritizedCallback<TCallback> Create<TCallback>(TCallback item, int priority) where TCallback : Delegate { return new PrioritizedCallback<TCallback>(item, priority); } } internal class PrioritizedCallback<TCallback> : PrioritizedCallback, IComparable<PrioritizedCallback<TCallback>>, IEquatable<PrioritizedCallback<TCallback>> where TCallback : Delegate { public TCallback Callback { get; } public int Priority { get; } public Type TargetType { get; set; } public bool IsBeingCalled { get; set; } public PrioritizedCallback(TCallback callback, int priority) { Callback = callback; Priority = priority; TargetType = callback.Target?.GetType(); } public int CompareTo(PrioritizedCallback<TCallback> other) { return other.Priority.CompareTo(Priority); } public override bool Equals(object obj) { return Equals(obj as PrioritizedCallback<TCallback>); } public bool Equals(PrioritizedCallback<TCallback> other) { return EqualityComparer<TCallback>.Default.Equals(Callback, other.Callback); } public override int GetHashCode() { return -1406788065 * -1521134295 + EqualityComparer<TCallback>.Default.GetHashCode(Callback); } public override string ToString() { return "[" + Priority + "] " + (TargetType?.Name ?? Callback.Method.DeclaringType?.Name) + "." + Callback.Method?.Name; } } internal class ResourceExtensionData { public bool HasBeenRedirected { get; set; } public string FullFileSystemAssetPath { get; set; } } public class ResourceLoadedContext : IAssetOrResourceLoadedContext { private BackingFieldOrArray _backingField; public ResourceLoadedParameters Parameters { get; } public Object[] Assets { get { return _backingField.Array; } set { _backingField.Array = value; } } public Object Asset { get { return _backingField.Field; } set { _backingField.Field = value; } } internal bool SkipRemainingPostfixes { get; set; } internal ResourceLoadedContext(ResourceLoadedParameters parameters, Object[] assets) { Parameters = parameters; _backingField = new BackingFieldOrArray(assets); } internal ResourceLoadedContext(ResourceLoadedParameters parameters, Object asset) { Parameters = parameters; _backingField = new BackingFieldOrArray(asset); } public bool HasReferenceBeenRedirectedBefore(Object asset) { return ExtensionDataHelper.GetExtensionData<ResourceExtensionData>((object)asset)?.HasBeenRedirected ?? false; } public string GetUniqueFileSystemAssetPath(Object asset) { ResourceExtensionData orCreateExtensionData = ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)asset); if (orCreateExtensionData.FullFileSystemAssetPath == null) { string text = string.Empty; if (!string.IsNullOrEmpty(Parameters.Path)) { text = Parameters.Path.ToLowerInvariant(); } if (Parameters.LoadType == ResourceLoadType.LoadByType) { string name = asset.name; if (!string.IsNullOrEmpty(name)) { text = Path.Combine(text, name.ToLowerInvariant()); } else { string text2 = null; if (Assets.Length > 1) { int num = Array.IndexOf(Assets, asset); text2 = ((num != -1) ? ("_" + num.ToString(CultureInfo.InvariantCulture)) : "_with_unknown_index"); } text = Path.Combine(text, "unnamed_asset" + text2); } } text = StringExtensions.UseCorrectDirectorySeparators(text); orCreateExtensionData.FullFileSystemAssetPath = text; } return orCreateExtensionData.FullFileSystemAssetPath; } public void Complete(bool skipRemainingPostfixes = true) { SkipRemainingPostfixes = skipRemainingPostfixes; } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class ResourceLoadedParameters { public string Path { get; set; } public Type Type { get; set; } public ResourceLoadType LoadType { get; } internal ResourceLoadedParameters(string path, Type type, ResourceLoadType loadType) { Path = path; Type = type; LoadType = loadType; } } public enum ResourceLoadType { LoadByType = 1, LoadNamed, LoadNamedBuiltIn } public static class ResourceRedirection { private static readonly List<PrioritizedCallback<Action<AssetLoadedContext>>> PostfixRedirectionsForAssetsPerCall = new List<PrioritizedCallback<Action<AssetLoadedContext>>>(); private static readonly List<PrioritizedCallback<Action<AssetLoadedContext>>> PostfixRedirectionsForAssetsPerResource = new List<PrioritizedCallback<Action<AssetLoadedContext>>>(); private static readonly List<PrioritizedCallback<Action<ResourceLoadedContext>>> PostfixRedirectionsForResourcesPerCall = new List<PrioritizedCallback<Action<ResourceLoadedContext>>>(); private static readonly List<PrioritizedCallback<Action<ResourceLoadedContext>>> PostfixRedirectionsForResourcesPerResource = new List<PrioritizedCallback<Action<ResourceLoadedContext>>>(); private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAssetsPerCall = new List<PrioritizedCallback<Delegate>>(); private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAsyncAssetsPerCall = new List<PrioritizedCallback<Delegate>>(); private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAssetBundles = new List<PrioritizedCallback<Delegate>>(); private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAsyncAssetBundles = new List<PrioritizedCallback<Delegate>>(); private static readonly List<PrioritizedCallback<Action<AssetBundleLoadedContext>>> PostfixRedirectionsForAssetBundles = new List<PrioritizedCallback<Action<AssetBundleLoadedContext>>>(); private static Action<AssetBundleLoadingContext> _emulateAssetBundles; private static Action<AsyncAssetBundleLoadingContext> _emulateAssetBundlesAsync; private static Action<AssetBundleLoadingContext> _redirectionMissingAssetBundlesToEmpty; private static Action<AsyncAssetBundleLoadingContext> _redirectionMissingAssetBundlesToEmptyAsync; private static bool _enabledRandomizeCabIfConflict = false; private static Action<AssetBundleLoadingContext> _enableCabRandomizationPrefix; private static Action<AsyncAssetBundleLoadingContext> _enableCabRandomizationPrefixAsync; private static Action<AssetBundleLoadedContext> _enableCabRandomizationPostfix; private static bool _initialized = false; private static bool _initializedSyncOverAsyncEnabled = false; private static bool _logAllLoadedResources = false; private static bool _isFiringAssetBundle; private static bool _isFiringResource; private static bool _isFiringAsset; private static bool _isRecursionDisabledPermanently; internal static bool RecursionEnabled = true; internal static bool SyncOverAsyncEnabled = false; public static bool LogAllLoadedResources { get { return _logAllLoadedResources; } set { if (value) { Initialize(); } _logAllLoadedResources = value; } } public static bool LogCallbackOrder { get; set; } public static void Initialize() { if (!_initialized) { _initialized = true; HookingHelper.PatchAll((IEnumerable<Type>)ResourceAndAssetHooks.GeneralHooks, false); } } public static void EnableSyncOverAsyncAssetLoads() { Initialize(); if (!_initializedSyncOverAsyncEnabled) { _initializedSyncOverAsyncEnabled = true; SyncOverAsyncEnabled = true; HookingHelper.PatchAll((IEnumerable<Type>)ResourceAndAssetHooks.SyncOverAsyncHooks, false); } } public static void DisableRecursionPermanently() { _isRecursionDisabledPermanently = true; } public static void EnableEmulateAssetBundles(int priority, string emulationDirectory) { if (_emulateAssetBundles == null && _emulateAssetBundlesAsync == null) { _emulateAssetBundles = delegate(AssetBundleLoadingContext ctx) { HandleAssetBundleEmulation<AssetBundleLoadingContext>(ctx, SetBundle); }; _emulateAssetBundlesAsync = delegate(AsyncAssetBundleLoadingContext ctx) { HandleAssetBundleEmulation<AsyncAssetBundleLoadingContext>(ctx, SetRequest); }; RegisterAssetBundleLoadingHook(priority, _emulateAssetBundles); RegisterAsyncAssetBundleLoadingHook(priority, _emulateAssetBundlesAsync); } void HandleAssetBundleEmulation<T>(T context, Action<T, string> changeBundle) where T : IAssetBundleLoadingContext { if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromFile) { string normalizedPath = context.GetNormalizedPath(); string text = Path.Combine(emulationDirectory, normalizedPath); if (File.Exists(text)) { changeBundle(context, text); ref T reference = ref context; T val = default(T); if (val == null) { val = reference; reference = ref val; } reference.Complete(skipRemainingPrefixes: true, true); XuaLogger.ResourceRedirector.Debug("Redirected asset bundle: '" + context.Parameters.Path + "' => '" + text + "'"); } } } static void SetBundle(AssetBundleLoadingContext context, string path) { context.Bundle = AssetBundle.LoadFromFile(path, context.Parameters.Crc, context.Parameters.Offset); } static void SetRequest(AsyncAssetBundleLoadingContext context, string path) { context.Request = AssetBundle.LoadFromFileAsync(path, context.Parameters.Crc, context.Parameters.Offset); } } public static void DisableEmulateAssetBundles() { if (_emulateAssetBundles != null && _emulateAssetBundlesAsync != null) { UnregisterAssetBundleLoadingHook(_emulateAssetBundles); UnregisterAsyncAssetBundleLoadingHook(_emulateAssetBundlesAsync); _emulateAssetBundles = null; _emulateAssetBundlesAsync = null; } } public static void EnableRedirectMissingAssetBundlesToEmptyAssetBundle(int priority) { if (_redirectionMissingAssetBundlesToEmpty == null && _redirectionMissingAssetBundlesToEmptyAsync == null) { _redirectionMissingAssetBundlesToEmpty = delegate(AssetBundleLoadingContext ctx) { HandleMissingBundle<AssetBundleLoadingContext>(ctx, SetBundle); }; _redirectionMissingAssetBundlesToEmptyAsync = delegate(AsyncAssetBundleLoadingContext ctx) { HandleMissingBundle<AsyncAssetBundleLoadingContext>(ctx, SetRequest); }; RegisterAssetBundleLoadingHook(priority, _redirectionMissingAssetBundlesToEmpty); RegisterAsyncAssetBundleLoadingHook(priority, _redirectionMissingAssetBundlesToEmptyAsync); } static void HandleMissingBundle<TContext>(TContext context, Action<TContext, byte[]> changeBundle) where TContext : IAssetBundleLoadingContext { if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromFile && !File.Exists(context.Parameters.Path)) { byte[] empty = Resources.empty; CabHelper.RandomizeCab(empty); changeBundle(context, empty); ref TContext reference = ref context; TContext val = default(TContext); if (val == null) { val = reference; reference = ref val; } reference.Complete(skipRemainingPrefixes: true, true); XuaLogger.ResourceRedirector.Warn("Tried to load non-existing asset bundle: " + context.Parameters.Path); } } static void SetBundle(AssetBundleLoadingContext context, byte[] assetBundleData) { AssetBundle bundle = AssetBundle.LoadFromMemory(assetBundleData); context.Bundle = bundle; } static void SetRequest(AsyncAssetBundleLoadingContext context, byte[] assetBundleData) { AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(assetBundleData); context.Request = request; } } public static void EnableRandomizeCabIfConflict(int priority, bool forceRandomizeWhenInMemory) { if (_enabledRandomizeCabIfConflict) { return; } _enabledRandomizeCabIfConflict = true; if (forceRandomizeWhenInMemory) { _enableCabRandomizationPrefix = delegate(AssetBundleLoadingContext ctx) { HandleCabRandomizePrefix(ctx); }; _enableCabRandomizationPrefixAsync = delegate(AsyncAssetBundleLoadingContext ctx) { HandleCabRandomizePrefix(ctx); }; RegisterAssetBundleLoadingHook(priority, _enableCabRandomizationPrefix); RegisterAsyncAssetBundleLoadingHook(priority, _enableCabRandomizationPrefixAsync); } _enableCabRandomizationPostfix = delegate(AssetBundleLoadedContext ctx) { HandleCabRandomizePostfix(ctx); }; RegisterAssetBundleLoadedHook(priority, _enableCabRandomizationPostfix); void HandleCabRandomizePostfix(AssetBundleLoadedContext context) { if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromFile) { if ((Object)(object)context.Bundle == (Object)null && File.Exists(context.Parameters.Path)) { XuaLogger.ResourceRedirector.Warn("The asset bundle '" + context.Parameters.Path + "' could not be loaded likely due to conflicting CAB-string. Retrying in-memory with randomized CAB-string."); byte[] array; using (FileStream fileStream = new FileStream(context.Parameters.Path, FileMode.Open, FileAccess.Read)) { long length = fileStream.Length; long offset = (long)context.Parameters.Offset; long num = length - offset; fileStream.Seek(offset, SeekOrigin.Begin); array = StreamExtensions.ReadFully((Stream)fileStream, (int)num); } if (!forceRandomizeWhenInMemory) { CabHelper.RandomizeCabWithAnyLength(array); } AssetBundle val = AssetBundle.LoadFromMemory(array, 0u); if ((Object)(object)val != (Object)null) { context.Bundle = val; context.Complete(); } } } else if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromMemory) { if ((Object)(object)context.Bundle == (Object)null && !forceRandomizeWhenInMemory) { string text = AssetBundleHelper.PathForLoadedInMemoryBundle ?? "Unnamed"; XuaLogger.ResourceRedirector.Warn("Could not load an in-memory asset bundle (" + text + ") likely due to conflicting CAB-string. Retrying with randomized CAB-string."); CabHelper.RandomizeCabWithAnyLength(context.Parameters.Binary); AssetBundle val2 = AssetBundle.LoadFromMemory(context.Parameters.Binary, 0u); if ((Object)(object)val2 != (Object)null) { context.Bundle = val2; context.Complete(); } } } else if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromStream && (Object)(object)context.Bundle == (Object)null) { string text2 = AssetBundleHelper.PathForLoadedInMemoryBundle ?? "Unnamed"; XuaLogger.ResourceRedirector.Warn("Could not load a stream asset bundle (" + text2 + ") likely due to conflicting CAB-string. Retrying with randomized CAB-string."); byte[] array2 = StreamExtensions.ReadFully(context.Parameters.Stream, 0); if (!forceRandomizeWhenInMemory) { CabHelper.RandomizeCabWithAnyLength(array2); } AssetBundle val3 = AssetBundle.LoadFromMemory(array2, 0u); if ((Object)(object)val3 != (Object)null) { context.Bundle = val3; context.Complete(); } } } static void HandleCabRandomizePrefix(IAssetBundleLoadingContext context) { if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromMemory) { CabHelper.RandomizeCabWithAnyLength(context.Parameters.Binary); } } } public static void DisableRandomizeCabIfConflict() { if (_enabledRandomizeCabIfConflict) { _enabledRandomizeCabIfConflict = false; if (_enableCabRandomizationPrefix != null) { UnregisterAssetBundleLoadingHook(_enableCabRandomizationPrefix); _enableCabRandomizationPrefix = null; } if (_enableCabRandomizationPrefixAsync != null) { UnregisterAsyncAssetBundleLoadingHook(_enableCabRandomizationPrefixAsync); _enableCabRandomizationPrefixAsync = null; } if (_enableCabRandomizationPostfix != null) { UnregisterAssetBundleLoadedHook(_enableCabRandomizationPostfix); _enableCabRandomizationPostfix = null; } } } public static void DisableRedirectMissingAssetBundlesToEmptyAssetBundle() { if (_redirectionMissingAssetBundlesToEmpty != null && _redirectionMissingAssetBundlesToEmptyAsync != null) { UnregisterAssetBundleLoadingHook(_redirectionMissingAssetBundlesToEmpty); UnregisterAsyncAssetBundleLoadingHook(_redirectionMissingAssetBundlesToEmptyAsync); _redirectionMissingAssetBundlesToEmpty = null; _redirectionMissingAssetBundlesToEmptyAsync = null; } } internal static bool TryGetAssetBundleLoadInfo(AssetBundleRequest request, out AsyncAssetLoadInfo result) { result = ExtensionDataHelper.GetExtensionData<AsyncAssetLoadInfo>((object)request); return result != null; } internal static bool TryGetAssetBundle(AssetBundleCreateRequest request, out AsyncAssetBundleLoadInfo result) { result = ExtensionDataHelper.GetExtensionData<AsyncAssetBundleLoadInfo>((object)request); return result != null; } internal static bool ShouldBlockAsyncOperationMethods(AssetBundleRequest operation) { if (TryGetAssetBundleLoadInfo(operation, out var result)) { return result.ResolveType == AsyncAssetLoadingResolve.ThroughAssets; } return false; } internal static bool ShouldBlockAsyncOperationMethods(AssetBundleCreateRequest operation) { if (TryGetAssetBundle(operation, out var result)) { return result.ResolveType == AsyncAssetBundleLoadingResolve.ThroughBundle; } return false; } internal static bool ShouldBlockAsyncOperationMethods(AsyncOperation operation) { if (SyncOverAsyncEnabled) { AssetBundleRequest operation2 = default(AssetBundleRequest); if (!ObjectExtensions.TryCastTo<AssetBundleRequest>((object)operation, ref operation2) || !ShouldBlockAsyncOperationMethods(operation2)) { AssetBundleCreateRequest operation3 = default(AssetBundleCreateRequest); if (ObjectExtensions.TryCastTo<AssetBundleCreateRequest>((object)operation, ref operation3)) { return ShouldBlockAsyncOperationMethods(operation3); } return false; } return true; } return false; } internal static AssetBundleLoadingContext Hook_AssetBundleLoading_Prefix(AssetBundleLoadingParameters parameters, out AssetBundle bundle) { AssetBundleLoadingContext assetBundleLoadingContext = new AssetBundleLoadingContext(parameters); if (_isFiringAssetBundle && (_isRecursionDisabledPermanently || !RecursionEnabled)) { bundle = null; return assetBundleLoadingContext; } try { _isFiringAssetBundle = true; if (_logAllLoadedResources) { XuaLogger.ResourceRedirector.Debug("Loading Asset Bundle: (" + assetBundleLoadingContext.GetNormalizedPath() + ")."); } List<PrioritizedCallback<Delegate>> prefixRedirectionsForAssetBundles = PrefixRedirectionsForAssetBundles; int count = prefixRedirectionsForAssetBundles.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAssetBundles[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; if (prioritizedCallback.Callback is Action<AssetBundleLoadingContext> action) { action(assetBundleLoadingContext); } else if (prioritizedCallback.Callback is Action<IAssetBundleLoadingContext> action2) { action2(assetBundleLoadingContext); } if (assetBundleLoadingContext.SkipRemainingPrefixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetBundleLoading event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetBundleLoading event."); } finally { _isFiringAssetBundle = false; } bundle = assetBundleLoadingContext.Bundle; return assetBundleLoadingContext; } internal static AssetBundleLoadedContext Hook_AssetBundleLoaded_Postfix(AssetBundleLoadingParameters parameters, ref AssetBundle bundle) { AssetBundleLoadedContext assetBundleLoadedContext = new AssetBundleLoadedContext(parameters, bundle); if (_isFiringAssetBundle && (_isRecursionDisabledPermanently || !RecursionEnabled)) { bundle = null; return assetBundleLoadedContext; } try { _isFiringAssetBundle = true; List<PrioritizedCallback<Action<AssetBundleLoadedContext>>> postfixRedirectionsForAssetBundles = PostfixRedirectionsForAssetBundles; int count = postfixRedirectionsForAssetBundles.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Action<AssetBundleLoadedContext>> prioritizedCallback = postfixRedirectionsForAssetBundles[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; prioritizedCallback.Callback(assetBundleLoadedContext); if (assetBundleLoadedContext.SkipRemainingPostfixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetBundleLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetBundleLoaded event."); } finally { _isFiringAssetBundle = false; } bundle = assetBundleLoadedContext.Bundle; return assetBundleLoadedContext; } internal static AsyncAssetBundleLoadingContext Hook_AssetBundleLoading_Prefix(AssetBundleLoadingParameters parameters, out AssetBundleCreateRequest request) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown AsyncAssetBundleLoadingContext asyncAssetBundleLoadingContext = new AsyncAssetBundleLoadingContext(parameters); if (_isFiringAssetBundle && (_isRecursionDisabledPermanently || !RecursionEnabled)) { request = null; return asyncAssetBundleLoadingContext; } try { _isFiringAssetBundle = true; if (_logAllLoadedResources) { XuaLogger.ResourceRedirector.Debug("Loading Asset Bundle (async): (" + asyncAssetBundleLoadingContext.GetNormalizedPath() + ")."); } List<PrioritizedCallback<Delegate>> prefixRedirectionsForAsyncAssetBundles = PrefixRedirectionsForAsyncAssetBundles; int count = prefixRedirectionsForAsyncAssetBundles.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAsyncAssetBundles[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; if (prioritizedCallback.Callback is Action<AsyncAssetBundleLoadingContext> action) { action(asyncAssetBundleLoadingContext); } else if (prioritizedCallback.Callback is Action<IAssetBundleLoadingContext> action2) { action2(asyncAssetBundleLoadingContext); } if (asyncAssetBundleLoadingContext.SkipRemainingPrefixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetBundleLoading event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AsyncAssetBundleLoading event."); } finally { _isFiringAssetBundle = false; } if (asyncAssetBundleLoadingContext.ResolveType == AsyncAssetBundleLoadingResolve.ThroughRequest) { request = asyncAssetBundleLoadingContext.Request; } else { if (asyncAssetBundleLoadingContext.ResolveType != AsyncAssetBundleLoadingResolve.ThroughBundle) { throw new InvalidOperationException("Found invalid ResolveType on context: " + asyncAssetBundleLoadingContext.ResolveType); } request = new AssetBundleCreateRequest(); if (!asyncAssetBundleLoadingContext.SkipOriginalCall) { XuaLogger.ResourceRedirector.Warn("Resolving sync over async asset load, but 'SkipOriginalCall' was not set to true. Forcing it to true."); asyncAssetBundleLoadingContext.SkipOriginalCall = true; } } return asyncAssetBundleLoadingContext; } internal static void Hook_AssetBundleLoading_Postfix(AsyncAssetBundleLoadingContext context, AssetBundleCreateRequest request) { if (request != null) { ExtensionDataHelper.SetExtensionData<AsyncAssetBundleLoadInfo>((object)request, new AsyncAssetBundleLoadInfo(context.Parameters, context.Bundle, context.SkipAllPostfixes, context.ResolveType)); } } internal static void Hook_AssetLoading_Postfix(AsyncAssetLoadingContext context, AssetBundleRequest request) { if (request != null) { ExtensionDataHelper.SetExtensionData<AsyncAssetLoadInfo>((object)request, new AsyncAssetLoadInfo(context.Parameters, context.Bundle, context.SkipAllPostfixes, context.ResolveType, context.Assets)); } } internal static AssetLoadingContext Hook_AssetLoading_Prefix(AssetLoadingParameters parameters, AssetBundle parentBundle, ref Object asset) { Object[] assets = null; AssetLoadingContext result = Hook_AssetLoading_Prefix(parameters, parentBundle, ref assets); if (assets == null || assets.Length == 0) { asset = null; return result; } if (assets.Length > 1) { XuaLogger.ResourceRedirector.Warn("Illegal behaviour by redirection handler in AssetLoadeding event. Returned more than one asset to call requiring only a single asset."); asset = assets[0]; return result; } if (assets.Length == 1) { asset = assets[0]; } return result; } internal static AssetLoadingContext Hook_AssetLoading_Prefix(AssetLoadingParameters parameters, AssetBundle bundle, ref Object[] assets) { AssetLoadingContext assetLoadingContext = new AssetLoadingContext(parameters, bundle); try { if (_isFiringAsset && (_isRecursionDisabledPermanently || !RecursionEnabled)) { return assetLoadingContext; } _isFiringAsset = true; List<PrioritizedCallback<Delegate>> prefixRedirectionsForAssetsPerCall = PrefixRedirectionsForAssetsPerCall; int count = prefixRedirectionsForAssetsPerCall.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAssetsPerCall[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; if (prioritizedCallback.Callback is Action<AssetLoadingContext> action) { action(assetLoadingContext); } else if (prioritizedCallback.Callback is Action<IAssetLoadingContext> action2) { action2(assetLoadingContext); } if (assetLoadingContext.SkipRemainingPrefixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetLoading event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } assets = assetLoadingContext.Assets; } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetLoading event."); } finally { _isFiringAsset = false; } return assetLoadingContext; } internal static AsyncAssetLoadingContext Hook_AsyncAssetLoading_Prefix(AssetLoadingParameters parameters, AssetBundle bundle, ref AssetBundleRequest request) { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown AsyncAssetLoadingContext asyncAssetLoadingContext = new AsyncAssetLoadingContext(parameters, bundle); try { if (_isFiringAsset && (_isRecursionDisabledPermanently || !RecursionEnabled)) { return asyncAssetLoadingContext; } _isFiringAsset = true; List<PrioritizedCallback<Delegate>> prefixRedirectionsForAsyncAssetsPerCall = PrefixRedirectionsForAsyncAssetsPerCall; int count = prefixRedirectionsForAsyncAssetsPerCall.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAsyncAssetsPerCall[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; if (prioritizedCallback.Callback is Action<AsyncAssetLoadingContext> action) { action(asyncAssetLoadingContext); } else if (prioritizedCallback.Callback is Action<IAssetLoadingContext> action2) { action2(asyncAssetLoadingContext); } if (asyncAssetLoadingContext.SkipRemainingPrefixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AsyncAssetLoading event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } if (asyncAssetLoadingContext.ResolveType == AsyncAssetLoadingResolve.ThroughRequest) { request = asyncAssetLoadingContext.Request; } else { if (asyncAssetLoadingContext.ResolveType != AsyncAssetLoadingResolve.ThroughAssets) { throw new InvalidOperationException("Found invalid ResolveType on context: " + asyncAssetLoadingContext.ResolveType); } request = new AssetBundleRequest(); if (!asyncAssetLoadingContext.SkipOriginalCall) { XuaLogger.ResourceRedirector.Warn("Resolving sync over async asset load, but 'SkipOriginalCall' was not set to true. Forcing it to true."); asyncAssetLoadingContext.SkipOriginalCall = true; } } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AsyncAssetLoading event."); } finally { _isFiringAsset = false; } return asyncAssetLoadingContext; } internal static void Hook_AssetLoaded_Postfix(AssetLoadingParameters parameters, AssetBundle parentBundle, ref Object asset) { Object[] assets = (Object[])(object)((!(asset == (Object)null)) ? new Object[1] { asset } : new Object[0]); Hook_AssetLoaded_Postfix(parameters, parentBundle, ref assets); if (assets == null || assets.Length == 0) { asset = null; } else if (assets.Length > 1) { XuaLogger.ResourceRedirector.Warn("Illegal behaviour by redirection handler in AssetLoaded event. Returned more than one asset to call requiring only a single asset."); asset = assets[0]; } else if (assets.Length == 1) { asset = assets[0]; } } internal static void Hook_AssetLoaded_Postfix(AssetLoadingParameters parameters, AssetBundle bundle, ref Object[] assets) { FireAssetLoadedEvent(parameters.ToAssetLoadedParameters(), bundle, ref assets); } internal static void Hook_ResourceLoaded_Postfix(ResourceLoadedParameters parameters, ref Object asset) { Object[] assets = (Object[])(object)((!(asset == (Object)null)) ? new Object[1] { asset } : new Object[0]); Hook_ResourceLoaded_Postfix(parameters, ref assets); if (assets == null || assets.Length == 0) { asset = null; } else if (assets.Length > 1) { XuaLogger.ResourceRedirector.Warn("Illegal behaviour by redirection handler in ResourceLoaded event. Returned more than one asset to call requiring only a single asset."); asset = assets[0]; } else if (assets.Length == 1) { asset = assets[0]; } } internal static void Hook_ResourceLoaded_Postfix(ResourceLoadedParameters parameters, ref Object[] assets) { FireResourceLoadedEvent(parameters, ref assets); } internal static void FireAssetLoadedEvent(AssetLoadedParameters parameters, AssetBundle assetBundle, ref Object[] assets) { Object[] array = assets?.ToArray(); try { AssetLoadedContext assetLoadedContext = new AssetLoadedContext(parameters, assetBundle, assets); if (_isFiringAsset && (_isRecursionDisabledPermanently || !RecursionEnabled)) { return; } _isFiringAsset = true; if (_logAllLoadedResources && assets != null) { for (int i = 0; i < assets.Length; i++) { Object val = assets[i]; if (val != (Object)null) { string uniqueFileSystemAssetPath = assetLoadedContext.GetUniqueFileSystemAssetPath(val); XuaLogger.ResourceRedirector.Debug("Loaded Asset: '" + ObjectExtensions.GetUnityType((object)val).FullName + "', Load Type: '" + parameters.LoadType.ToString() + "', Unique Path: (" + uniqueFileSystemAssetPath + ")."); } } } List<PrioritizedCallback<Action<AssetLoadedContext>>> postfixRedirectionsForAssetsPerCall = PostfixRedirectionsForAssetsPerCall; int count = postfixRedirectionsForAssetsPerCall.Count; for (int j = 0; j < count; j++) { PrioritizedCallback<Action<AssetLoadedContext>> prioritizedCallback = postfixRedirectionsForAssetsPerCall[j]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; prioritizedCallback.Callback(assetLoadedContext); if (assetLoadedContext.SkipRemainingPostfixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } assets = assetLoadedContext.Assets; if (assetLoadedContext.SkipRemainingPostfixes || assets == null) { return; } int num = assets.Length; for (int k = 0; k < num; k++) { Object val2 = assets[k]; if (val2 != (Object)null) { AssetLoadedContext assetLoadedContext2 = new AssetLoadedContext(parameters, assetBundle, val2); List<PrioritizedCallback<Action<AssetLoadedContext>>> postfixRedirectionsForAssetsPerResource = PostfixRedirectionsForAssetsPerResource; int count2 = postfixRedirectionsForAssetsPerResource.Count; for (int l = 0; l < count2; l++) { PrioritizedCallback<Action<AssetLoadedContext>> prioritizedCallback2 = postfixRedirectionsForAssetsPerResource[l]; if (prioritizedCallback2.IsBeingCalled) { continue; } try { prioritizedCallback2.IsBeingCalled = true; prioritizedCallback2.Callback(assetLoadedContext2); if (assetLoadedContext2.Asset != (Object)null) { assets[k] = assetLoadedContext2.Asset; } else { XuaLogger.ResourceRedirector.Warn($"Illegal behaviour by redirection handler in AssetLoaded event. You must not remove an asset reference when hooking with behaviour {HookBehaviour.OneCallbackPerResourceLoaded}."); } if (assetLoadedContext2.SkipRemainingPostfixes) { break; } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback2.IsBeingCalled = false; } } } else { XuaLogger.ResourceRedirector.Error("Found unexpected null asset during AssetLoaded event."); } } } catch (Exception ex3) { XuaLogger.ResourceRedirector.Error(ex3, "An error occurred while invoking AssetLoaded event."); } finally { _isFiringAsset = false; if (array != null) { Object[] array2 = array; for (int m = 0; m < array2.Length; m++) { ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)array2[m]).HasBeenRedirected = true; } } } } internal static void FireResourceLoadedEvent(ResourceLoadedParameters parameters, ref Object[] assets) { Object[] array = assets?.ToArray(); try { ResourceLoadedContext resourceLoadedContext = new ResourceLoadedContext(parameters, assets); if (_isFiringResource && (_isRecursionDisabledPermanently || !RecursionEnabled)) { return; } _isFiringResource = true; if (_logAllLoadedResources && assets != null) { for (int i = 0; i < assets.Length; i++) { Object val = assets[i]; if (val != (Object)null) { string uniqueFileSystemAssetPath = resourceLoadedContext.GetUniqueFileSystemAssetPath(val); XuaLogger.ResourceRedirector.Debug("Loaded Asset: '" + ObjectExtensions.GetUnityType((object)val).FullName + "', Load Type: '" + parameters.LoadType.ToString() + "', Unique Path: (" + uniqueFileSystemAssetPath + ")."); } } } List<PrioritizedCallback<Action<ResourceLoadedContext>>> postfixRedirectionsForResourcesPerCall = PostfixRedirectionsForResourcesPerCall; int count = postfixRedirectionsForResourcesPerCall.Count; for (int j = 0; j < count; j++) { PrioritizedCallback<Action<ResourceLoadedContext>> prioritizedCallback = postfixRedirectionsForResourcesPerCall[j]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; prioritizedCallback.Callback(resourceLoadedContext); if (resourceLoadedContext.SkipRemainingPostfixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking ResourceLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } assets = resourceLoadedContext.Assets; if (resourceLoadedContext.SkipRemainingPostfixes || assets == null) { return; } int num = assets.Length; for (int k = 0; k < num; k++) { Object val2 = assets[k]; if (val2 != (Object)null) { ResourceLoadedContext resourceLoadedContext2 = new ResourceLoadedContext(parameters, val2); List<PrioritizedCallback<Action<ResourceLoadedContext>>> postfixRedirectionsForResourcesPerResource = PostfixRedirectionsForResourcesPerResource; int count2 = postfixRedirectionsForResourcesPerResource.Count; for (int l = 0; l < count2; l++) { PrioritizedCallback<Action<ResourceLoadedContext>> prioritizedCallback2 = postfixRedirectionsForResourcesPerResource[l]; if (prioritizedCallback2.IsBeingCalled) { continue; } try { prioritizedCallback2.IsBeingCalled = true; prioritizedCallback2.Callback(resourceLoadedContext2); if (resourceLoadedContext2.Asset != (Object)null) { assets[k] = resourceLoadedContext2.Asset; } else { XuaLogger.ResourceRedirector.Warn($"Illegal behaviour by redirection handler in ResourceLoaded event. You must not remove an asset reference when hooking with behaviour {HookBehaviour.OneCallbackPerResourceLoaded}."); } if (resourceLoadedContext2.SkipRemainingPostfixes) { break; } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking ResourceLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback2.IsBeingCalled = false; } } } else { XuaLogger.ResourceRedirector.Error("Found unexpected null asset during ResourceLoaded event."); } } } catch (Exception ex3) { XuaLogger.ResourceRedirector.Error(ex3, "An error occurred while invoking ResourceLoaded event."); } finally { _isFiringResource = false; if (array != null) { Object[] array2 = array; for (int m = 0; m < array2.Length; m++) { ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)array2[m]).HasBeenRedirected = true; } } } } private static void LogEventRegistration(string eventType, IEnumerable callbacks) { XuaLogger.ResourceRedirector.Debug("Registered new callback for " + eventType + "."); LogNewCallbackOrder(eventType, callbacks); } private static void LogEventUnregistration(string eventType, IEnumerable callbacks) { XuaLogger.ResourceRedirector.Debug("Unregistered callback for " + eventType + "."); LogNewCallbackOrder(eventType, callbacks); } private static void LogNewCallbackOrder(string eventType, IEnumerable callbacks) { if (!LogCallbackOrder) { return; } XuaLogger.ResourceRedirector.Debug("New callback order for " + eventType + ":"); foreach (object callback in callbacks) { XuaLogger.ResourceRedirector.Debug(callback.ToString()); } } public static void RegisterAssetBundleLoadedHook(int priority, Action<AssetBundleLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Action<AssetBundleLoadedContext>> prioritizedCallback = PrioritizedCallback.Create(action, priority); if (PostfixRedirectionsForAssetBundles.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<AssetBundleLoadedContext>>>(PostfixRedirectionsForAssetBundles, prioritizedCallback); LogEventRegistration("AssetBundleLoaded", PostfixRedirectionsForAssetBundles); } public static void RegisterAssetBundleLoadedHook(Action<AssetBundleLoadedContext> action) { RegisterAssetBundleLoadedHook(0, action); } public static void UnregisterAssetBundleLoadedHook(Action<AssetBundleLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PostfixRedirectionsForAssetBundles.RemoveAll((PrioritizedCallback<Action<AssetBundleLoadedContext>> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetBundleLoaded", PostfixRedirectionsForAssetBundles); } public static void RegisterAssetLoadingHook(int priority, Action<AssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAssetsPerCall.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetsPerCall, prioritizedCallback); LogEventRegistration("AssetLoading", PrefixRedirectionsForAssetsPerCall); } public static void RegisterAssetLoadingHook(Action<AssetLoadingContext> action) { RegisterAssetLoadingHook(0, action); } public static void UnregisterAssetLoadingHook(Action<AssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetLoading", PrefixRedirectionsForAssetsPerCall); } public static void RegisterAsyncAssetLoadingHook(int priority, Action<AsyncAssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAsyncAssetsPerCall.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetsPerCall, prioritizedCallback); LogEventRegistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall); } public static void RegisterAsyncAssetLoadingHook(Action<AsyncAssetLoadingContext> action) { RegisterAsyncAssetLoadingHook(0, action); } public static void UnregisterAsyncAssetLoadingHook(Action<AsyncAssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAsyncAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall); } public static void RegisterAsyncAndSyncAssetLoadingHook(int priority, Action<IAssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAsyncAssetsPerCall.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetsPerCall, prioritizedCallback); LogEventRegistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetsPerCall, prioritizedCallback); LogEventRegistration("AssetLoading", PrefixRedirectionsForAssetsPerCall); } public static void RegisterAsyncAndSyncAssetLoadingHook(Action<IAssetLoadingContext> action) { RegisterAsyncAndSyncAssetLoadingHook(0, action); } public static void UnregisterAsyncAndSyncAssetLoadingHook(Action<IAssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAsyncAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall); PrefixRedirectionsForAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetLoading", PrefixRedirectionsForAssetsPerCall); } public static void RegisterAssetLoadedHook(HookBehaviour behaviour, int priority, Action<AssetLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Action<AssetLoadedContext>> prioritizedCallback = PrioritizedCallback.Create(action, priority); if (PostfixRedirectionsForAssetsPerCall.Contains(prioritizedCallback) || PostfixRedirectionsForAssetsPerResource.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); switch (behaviour) { case HookBehaviour.OneCallbackPerLoadCall: ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<AssetLoadedContext>>>(PostfixRedirectionsForAssetsPerCall, prioritizedCallback); LogEventRegistration("AssetLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForAssetsPerCall); break; case HookBehaviour.OneCallbackPerResourceLoaded: ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<AssetLoadedContext>>>(PostfixRedirectionsForAssetsPerResource, prioritizedCallback); LogEventRegistration("AssetLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForAssetsPerResource); break; } } public static void RegisterAssetLoadedHook(HookBehaviour behaviour, Action<AssetLoadedContext> action) { RegisterAssetLoadedHook(behaviour, 0, action); } public static void UnregisterAssetLoadedHook(Action<AssetLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } if (PostfixRedirectionsForAssetsPerCall.RemoveAll((PrioritizedCallback<Action<AssetLoadedContext>> x) => x.Callback == action) > 0) { LogEventRegistration("AssetLoaded (" + HookBehaviour.OneCallbackPerLoadCall.ToString() + ")", PostfixRedirectionsForAssetsPerCall); } if (PostfixRedirectionsForAssetsPerResource.RemoveAll((PrioritizedCallback<Action<AssetLoadedContext>> x) => x.Callback == action) > 0) { LogEventRegistration("AssetLoaded (" + HookBehaviour.OneCallbackPerResourceLoaded.ToString() + ")", PostfixRedirectionsForAssetsPerResource); } } public static void RegisterAssetBundleLoadingHook(int priority, Action<AssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAssetBundles.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetBundles, prioritizedCallback); LogEventRegistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles); } public static void RegisterAssetBundleLoadingHook(Action<AssetBundleLoadingContext> action) { RegisterAssetBundleLoadingHook(0, action); } public static void UnregisterAssetBundleLoadingHook(Action<AssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles); } public static void RegisterAsyncAssetBundleLoadingHook(int priority, Action<AsyncAssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAsyncAssetBundles.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetBundles, prioritizedCallback); LogEventRegistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles); } public static void RegisterAsyncAssetBundleLoadingHook(Action<AsyncAssetBundleLoadingContext> action) { RegisterAsyncAssetBundleLoadingHook(0, action); } public static void UnregisterAsyncAssetBundleLoadingHook(Action<AsyncAssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAsyncAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles); } public static void RegisterAsyncAndSyncAssetBundleLoadingHook(int priority, Action<IAssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAssetBundles.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetBundles, prioritizedCallback); LogEventRegistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetBundles, prioritizedCallback); LogEventRegistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles); } public static void RegisterAsyncAndSyncAssetBundleLoadingHook(Action<IAssetBundleLoadingContext> action) { RegisterAsyncAndSyncAssetBundleLoadingHook(0, action); } public static void UnregisterAsyncAndSyncAssetBundleLoadingHook(Action<IAssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles); PrefixRedirectionsForAsyncAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles); } public static void RegisterResourceLoadedHook(HookBehaviour behaviour, int priority, Action<ResourceLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Action<ResourceLoadedContext>> prioritizedCallback = PrioritizedCallback.Create(action, priority); if (PostfixRedirectionsForResourcesPerCall.Contains(prioritizedCallback) || PostfixRedirectionsForResourcesPerResource.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); switch (behaviour) { case HookBehaviour.OneCallbackPerLoadCall: ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<ResourceLoadedContext>>>(PostfixRedirectionsForResourcesPerCall, prioritizedCallback); LogEventRegistration("ResourceLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForResourcesPerCall); break; case HookBehaviour.OneCallbackPerResourceLoaded: ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<ResourceLoadedContext>>>(PostfixRedirectionsForResourcesPerResource, prioritizedCallback); LogEventRegistration("ResourceLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForResourcesPerResource); break; } } public static void RegisterResourceLoadedHook(HookBehaviour behaviour, Action<ResourceLoadedContext> action) { RegisterResourceLoadedHook(behaviour, 0, action); } public static void UnregisterResourceLoadedHook(Action<ResourceLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } if (PostfixRedirectionsForResourcesPerCall.RemoveAll((PrioritizedCallback<Action<ResourceLoadedContext>> x) => x.Callback == action) > 0) { LogEventRegistration("ResourceLoaded (" + HookBehaviour.OneCallbackPerLoadCall.ToString() + ")", PostfixRedirectionsForResourcesPerCall); } if (PostfixRedirectionsForResourcesPerResource.RemoveAll((PrioritizedCallback<Action<ResourceLoadedContext>> x) => x.Callback == action) > 0) { LogEventRegistration("ResourceLoaded (" + HookBehaviour.OneCallbackPerResourceLoaded.ToString() + ")", PostfixRedirectionsForResourcesPerResource); } } } } namespace XUnity.ResourceRedirector.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { resourceMan = new ResourceManager("XUnity.ResourceRedirector.Properties.Resources", typeof(Resources).Assembly); } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static byte[] empty => (byte[])ResourceManager.GetObject("empty", resourceCulture); internal Resources() { } } } namespace XUnity.ResourceRedirector.Hooks { internal static class ResourceAndAssetHooks { public static readonly Type[] GeneralHooks = new Type[21] { typeof(AssetBundle_LoadFromFileAsync_Hook), typeof(AssetBundle_LoadFromFile_Hook), typeof(AssetBundle_LoadFromMemoryAsync_Hook), typeof(AssetBundle_LoadFromMemory_Hook), typeof(AssetBundle_LoadFromStreamAsync_Hook), typeof(AssetBundle_LoadFromStream_Hook), typeof(AssetBundle_mainAsset_Hook), typeof(AssetBundle_returnMainAsset_Hook), typeof(AssetBundle_Load_Hook), typeof(AssetBundle_LoadAsync_Hook), typeof(AssetBundle_LoadAll_Hook), typeof(AssetBundle_LoadAsset_Internal_Hook), typeof(AssetBundle_LoadAssetAsync_Internal_Hook), typeof(AssetBundle_LoadAssetWithSubAssets_Internal_Hook), typeof(AssetBundle_LoadAssetWithSubAssetsAsync_Internal_Hook), typeof(AssetBundleRequest_asset_Hook), typeof(AssetBundleRequest_allAssets_Hook), typeof(Resources_Load_Hook), typeof(Resources_LoadAll_Hook), typeof(Resources_GetBuiltinResource_Old_Hook), typeof(Resources_GetBuiltinResource_New_Hook) }; public static readonly Type[] SyncOverAsyncHooks = new Type[10] { typeof(AssetBundleCreateRequest_assetBundle_Hook), typeof(AssetBundleCreateRequest_DisableCompatibilityChecks_Hook), typeof(AssetBundleCreateRequest_SetEnableCompatibilityChecks_Hook), typeof(AsyncOperation_isDone_Hook), typeof(AsyncOperation_progress_Hook), typeof(AsyncOperation_priority_Hook), typeof(AsyncOperation_set_priority_Hook), typeof(AsyncOperation_allowSceneActivation_Hook), typeof(AsyncOperation_set_allowSceneActivation_Hook), typeof(AsyncOperation_Finalize_Hook) }; } internal static class AssetBundleCreateRequest_assetBundle_Hook { private delegate AssetBundle OriginalMethod(AssetBundleCreateRequest __instance); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundleCreateRequest != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return AccessToolsShim.Property((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "assetBundle")?.GetGetMethod(); } private static bool Prefix(AssetBundleCreateRequest __instance, ref AssetBundle __result, ref AsyncAssetBundleLoadInfo __state) { if (ResourceRedirection.TryGetAssetBundle(__instance, out __state)) { if (__state.ResolveType == AsyncAssetBundleLoadingResolve.ThroughBundle) { __result = __state.Bundle; return false; } return true; } return true; } private static void Postfix(ref AssetBundle __result, ref AsyncAssetBundleLoadInfo __state) { if (__state == null) { return; } if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result); } if ((Object)(object)__result != (Object)null && __state != null) { string path = __state.Parameters.Path; if (path != null) { ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = path; } } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundle MM_Detour(AssetBundleCreateRequest __instance) { AssetBundle __result = null; AsyncAssetBundleLoadInfo __state = null; if (Prefix(__instance, ref __result, ref __state)) { __result = _original(__instance); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundleCreateRequest_DisableCompatibilityChecks_Hook { private delegate void OriginalMethod(AssetBundleCreateRequest __instance); private static OriginalMethod _original; private static bool Prepare(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return (object)AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "SetEnableCompatibilityChecks", new Type[1] { typeof(bool) }) == null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "DisableCompatibilityChecks", new Type[0]); } private static bool Prefix(AssetBundleCreateRequest __instance) { return !ResourceRedirection.ShouldBlockAsyncOperationMethods(__instance); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static void MM_Detour(AssetBundleCreateRequest __instance) { if (Prefix(__instance)) { _original(__instance); } } } internal static class AssetBundleCreateRequest_SetEnableCompatibilityChecks_Hook { private delegate void OriginalMethod(AssetBundleCreateRequest __instance, bool set); private static OriginalMethod _original; private static bool Prepare(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return (object)AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "SetEnableCompatibilityChecks", new Type[1] { typeof(bool) }) != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "SetEnableCompatibilityChecks", new Type[1] { typeof(bool) }); } private static bool Prefix(AssetBundleCreateRequest __instance, bool set) { return !ResourceRedirection.ShouldBlockAsyncOperationMethods(__instance); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static void MM_Detour(AssetBundleCreateRequest __instance, bool set) { if (Prefix(__instance, set)) { _original(__instance, set); } } } internal static class AssetBundle_LoadFromFileAsync_Hook { private delegate AssetBundleCreateRequest OriginalMethod(string path, uint crc, ulong offset); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromFileAsync_Internal", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromFileAsync", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }); } return methodInfo; } private static bool Prefix(ref string path, ref uint crc, ref ulong offset, ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, path, crc, offset, null, 0u, AssetBundleLoadType.LoadFromFile); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; path = parameters2.Path; crc = parameters2.Crc; offset = parameters2.Offset; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { ResourceRedirection.Hook_AssetBundleLoading_Postfix(__state, __result); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundleCreateRequest MM_Detour(string path, uint crc, ulong offset) { AssetBundleCreateRequest __result = null; AsyncAssetBundleLoadingContext __state = null; if (Prefix(ref path, ref crc, ref offset, ref __result, ref __state)) { __result = _original(path, crc, offset); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromFile_Hook { private delegate AssetBundle OriginalMethod(string path, uint crc, ulong offset); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromFile_Internal", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromFile", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }); } return methodInfo; } private static bool Prefix(ref string path, ref uint crc, ref ulong offset, ref AssetBundle __result, ref AssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, path, crc, offset, null, 0u, AssetBundleLoadType.LoadFromFile); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; path = parameters2.Path; crc = parameters2.Crc; offset = parameters2.Offset; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundle __result, ref AssetBundleLoadingContext __state) { if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result); } if ((Object)(object)__result != (Object)null && __state.Parameters.Path != null) { ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = __state.Parameters.Path; } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundle MM_Detour(string path, uint crc, ulong offset) { AssetBundle __result = null; AssetBundleLoadingContext __state = null; if (Prefix(ref path, ref crc, ref offset, ref __result, ref __state)) { __result = _original(path, crc, offset); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromMemoryAsync_Hook { private delegate AssetBundleCreateRequest OriginalMethod(byte[] binary, uint crc); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromMemoryAsync_Internal", new Type[2] { typeof(byte[]), typeof(uint) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromMemoryAsync", new Type[2] { typeof(byte[]), typeof(uint) }); } return methodInfo; } private static bool Prefix(ref byte[] binary, ref uint crc, ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(binary, null, crc, 0uL, null, 0u, AssetBundleLoadType.LoadFromMemory); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; binary = parameters2.Binary; crc = parameters2.Crc; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { ResourceRedirection.Hook_AssetBundleLoading_Postfix(__state, __result); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundleCreateRequest MM_Detour(byte[] binary, uint crc) { AssetBundleCreateRequest __result = null; AsyncAssetBundleLoadingContext __state = null; if (Prefix(ref binary, ref crc, ref __result, ref __state)) { __result = _original(binary, crc); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromMemory_Hook { private delegate AssetBundle OriginalMethod(byte[] binary, uint crc); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromMemory_Internal", new Type[2] { typeof(byte[]), typeof(uint) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromMemory", new Type[2] { typeof(byte[]), typeof(uint) }); } return methodInfo; } private static bool Prefix(ref byte[] binary, ref uint crc, ref AssetBundle __result, ref AssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(binary, null, crc, 0uL, null, 0u, AssetBundleLoadType.LoadFromMemory); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; binary = parameters2.Binary; crc = parameters2.Crc; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundle __result, ref AssetBundleLoadingContext __state) { if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result); } if ((Object)(object)__result != (Object)null && __state.Parameters.Path != null) { ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = __state.Parameters.Path; } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundle MM_Detour(byte[] binary, uint crc) { AssetBundle __result = null; AssetBundleLoadingContext __state = null; if (Prefix(ref binary, ref crc, ref __result, ref __state)) { __result = _original(binary, crc); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromStreamAsync_Hook { private delegate AssetBundleCreateRequest OriginalMethod(Stream stream, uint crc, uint managedReadBufferSize); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromStreamAsyncInternal", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromStreamAsync", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }); } return methodInfo; } private static bool Prefix(ref Stream stream, ref uint crc, ref uint managedReadBufferSize, ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, null, crc, 0uL, stream, managedReadBufferSize, AssetBundleLoadType.LoadFromMemory); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; stream = parameters2.Stream; crc = parameters2.Crc; managedReadBufferSize = parameters2.ManagedReadBufferSize; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { ResourceRedirection.Hook_AssetBundleLoading_Postfix(__state, __result); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundleCreateRequest MM_Detour(Stream stream, uint crc, uint managedReadBufferSize) { AssetBundleCreateRequest __result = null; AsyncAssetBundleLoadingContext __state = null; if (Prefix(ref stream, ref crc, ref managedReadBufferSize, ref __result, ref __state)) { __result = _original(stream, crc, managedReadBufferSize); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromStream_Hook { private delegate AssetBundle OriginalMethod(Stream stream, uint crc, uint managedReadBufferSize); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromStreamInternal", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromStream", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }); } return methodInfo; } private static bool Prefix(ref Stream stream, ref uint crc, ref uint managedReadBufferSize, ref AssetBundle __result, ref AssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, null, crc, 0uL, stream, managedReadBufferSize, AssetBundleLoadType.LoadFromMemory); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; stream = parameters2.Stream; crc = parameters2.Crc; managedReadBufferSize = parameters2.ManagedReadBufferSize; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundle __result, ref AssetBundleLoadingContext __state) { if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result); } if ((Object)(object)__result != (Object)null && __state.Parameters.Path != null) { ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = __state.Parameters.Path; } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundle MM_Detour(Stream stream, uint crc, uint managedReadBufferSize) { AssetBundle __result = null; AssetBundleLoadingContext __state = null; if (Prefix(ref stream, ref crc, ref managedReadBufferSize, ref __result, ref __state)) { __result = _original(stream, crc, managedReadBufferSize); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_mainAsset_Hook { private delegate Object OriginalMethod(AssetBundle __instance); private static OriginalMethod _original; private static bool Prepare(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; return (object)AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "returnMainAsset", new Type[1] { typeof(AssetBundle) }) == null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; return AccessToolsShim.Property((assetBundle != null) ? assetBundle.ClrType : null, "mainAsset")?.GetGetMethod(); } private static bool Prefix(AssetBundle __instance, ref Object __result, ref AssetLoadingContext __state) { AssetLoadingParameters parameters = new AssetLoadingParameters(null, null, AssetLoadType.LoadMainAsset); __state = ResourceRedirection.Hook_AssetLoading_Prefix(parameters, __instance, ref __result); return !__state.SkipOriginalCall; } private static void Postfix(AssetBundle __instance, ref Object __result, ref AssetLoadingContext __state) { if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetLoaded_Postfix(__state.Parameters, __instance, ref __result); } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static Object MM_Detour(AssetBundle __instance) { Object __result = null; AssetLoadingContext __state = null; if (Prefix(__instance, ref __result, ref __state)) { __result = _original(__instance); } Postfix(__instance, ref __result, ref __state); return __result; } } internal static class AssetBundle_returnMainAsset_Hook { private delegate Object OriginalMethod(AssetBundle __instance); private static OriginalMethod _original; private static bool Prepare(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; return (object)AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "returnMainAsset", new Type[1] { typeof(AssetBundle) }) != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; return AccessToolsShim.Method((assetBundle != null) ? assetBu