Decompiled source of InfernoProtocolInteropFix v1.0.0
BepInEx\patchers\InfernoProtocolInteropFix\dnlib.dll
Decompiled 5 days 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.Diagnostics.SymbolStore; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Xml; using Microsoft.CodeAnalysis; using Microsoft.Win32.SafeHandles; using dnlib.DotNet; using dnlib.DotNet.Emit; using dnlib.DotNet.MD; using dnlib.DotNet.Pdb; using dnlib.DotNet.Pdb.Dss; using dnlib.DotNet.Pdb.Managed; using dnlib.DotNet.Pdb.Portable; using dnlib.DotNet.Pdb.Symbols; using dnlib.DotNet.Pdb.WindowsPdb; using dnlib.DotNet.Writer; using dnlib.IO; using dnlib.PE; using dnlib.Threading; using dnlib.Utils; using dnlib.W32Resources; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("0xd4d")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (C) 2012-2019 [email protected]")] [assembly: AssemblyDescription("Reads and writes .NET assemblies and modules")] [assembly: AssemblyFileVersion("4.5.0.0")] [assembly: AssemblyInformationalVersion("4.5.0+c78d296c522aae0520df2afd825d48266321cf36")] [assembly: AssemblyProduct("dnlib")] [assembly: AssemblyTitle("dnlib (thread safe)")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/0xd4d/dnlib")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(System.Security.Permissions.SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("4.5.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 System { internal static class Array2 { private static class EmptyClass<T> { public static readonly T[] Empty = new T[0]; } public static T[] Empty<T>() { return EmptyClass<T>.Empty; } } } namespace dnlib { public static class Settings { public static bool IsThreadSafe => true; } } namespace dnlib.W32Resources { public sealed class ResourceData : ResourceDirectoryEntry { private readonly DataReaderFactory dataReaderFactory; private readonly uint resourceStartOffset; private readonly uint resourceLength; private uint codePage; private uint reserved; public uint CodePage { get { return codePage; } set { codePage = value; } } public uint Reserved { get { return reserved; } set { reserved = value; } } public DataReader CreateReader() { return dataReaderFactory.CreateReader(resourceStartOffset, resourceLength); } public ResourceData(ResourceName name) : this(name, ByteArrayDataReaderFactory.Create(Array2.Empty<byte>(), null), 0u, 0u) { } public ResourceData(ResourceName name, DataReaderFactory dataReaderFactory, uint offset, uint length) : this(name, dataReaderFactory, offset, length, 0u, 0u) { } public ResourceData(ResourceName name, DataReaderFactory dataReaderFactory, uint offset, uint length, uint codePage, uint reserved) : base(name) { this.dataReaderFactory = dataReaderFactory ?? throw new ArgumentNullException("dataReaderFactory"); resourceStartOffset = offset; resourceLength = length; this.codePage = codePage; this.reserved = reserved; } } public abstract class ResourceDirectory : ResourceDirectoryEntry { protected uint characteristics; protected uint timeDateStamp; protected ushort majorVersion; protected ushort minorVersion; private protected LazyList<ResourceDirectory> directories; private protected LazyList<ResourceData> data; public uint Characteristics { get { return characteristics; } set { characteristics = value; } } public uint TimeDateStamp { get { return timeDateStamp; } set { timeDateStamp = value; } } public ushort MajorVersion { get { return majorVersion; } set { majorVersion = value; } } public ushort MinorVersion { get { return minorVersion; } set { minorVersion = value; } } public IList<ResourceDirectory> Directories => directories; public IList<ResourceData> Data => data; protected ResourceDirectory(ResourceName name) : base(name) { } public ResourceDirectory FindDirectory(ResourceName name) { foreach (ResourceDirectory directory in directories) { if (directory.Name == name) { return directory; } } return null; } public ResourceData FindData(ResourceName name) { foreach (ResourceData datum in data) { if (datum.Name == name) { return datum; } } return null; } } public class ResourceDirectoryUser : ResourceDirectory { public ResourceDirectoryUser(ResourceName name) : base(name) { directories = new LazyList<ResourceDirectory>(); data = new LazyList<ResourceData>(); } } public sealed class ResourceDirectoryPE : ResourceDirectory { private readonly struct EntryInfo { public readonly ResourceName name; public readonly uint offset; public EntryInfo(ResourceName name, uint offset) { this.name = name; this.offset = offset; } public override string ToString() { return $"{offset:X8} {name}"; } } private const uint MAX_DIR_DEPTH = 10u; private readonly Win32ResourcesPE resources; private uint depth; private List<EntryInfo> dataInfos; private List<EntryInfo> dirInfos; public ResourceDirectoryPE(uint depth, ResourceName name, Win32ResourcesPE resources, ref DataReader reader) : base(name) { this.resources = resources; this.depth = depth; Initialize(ref reader); } private void Initialize(ref DataReader reader) { if (depth > 10 || !reader.CanRead(16u)) { InitializeDefault(); return; } characteristics = reader.ReadUInt32(); timeDateStamp = reader.ReadUInt32(); majorVersion = reader.ReadUInt16(); minorVersion = reader.ReadUInt16(); ushort num = reader.ReadUInt16(); ushort num2 = reader.ReadUInt16(); int num3 = num + num2; if (!reader.CanRead((uint)(num3 * 8))) { InitializeDefault(); return; } dataInfos = new List<EntryInfo>(); dirInfos = new List<EntryInfo>(); uint num4 = reader.Position; int num5 = 0; while (num5 < num3) { reader.Position = num4; uint num6 = reader.ReadUInt32(); uint num7 = reader.ReadUInt32(); ResourceName resourceName = (((num6 & 0x80000000u) == 0) ? new ResourceName((int)num6) : new ResourceName(ReadString(ref reader, num6 & 0x7FFFFFFF) ?? string.Empty)); if ((num7 & 0x80000000u) == 0) { dataInfos.Add(new EntryInfo(resourceName, num7)); } else { dirInfos.Add(new EntryInfo(resourceName, num7 & 0x7FFFFFFF)); } num5++; num4 += 8; } directories = new LazyList<ResourceDirectory, object>(dirInfos.Count, null, (object ctx, int i) => ReadResourceDirectory(i)); data = new LazyList<ResourceData, object>(dataInfos.Count, null, (object ctx, int i) => ReadResourceData(i)); } private static string ReadString(ref DataReader reader, uint offset) { reader.Position = offset; if (!reader.CanRead(2u)) { return null; } int num = reader.ReadUInt16() * 2; if (!reader.CanRead((uint)num)) { return null; } try { return reader.ReadUtf16String(num / 2); } catch { return null; } } private ResourceDirectory ReadResourceDirectory(int i) { EntryInfo entryInfo = dirInfos[i]; DataReader reader = resources.GetResourceReader(); reader.Position = Math.Min(reader.Length, entryInfo.offset); return new ResourceDirectoryPE(depth + 1, entryInfo.name, resources, ref reader); } private ResourceData ReadResourceData(int i) { EntryInfo entryInfo = dataInfos[i]; DataReader resourceReader = resources.GetResourceReader(); resourceReader.Position = Math.Min(resourceReader.Length, entryInfo.offset); if (resourceReader.CanRead(16u)) { RVA rva = (RVA)resourceReader.ReadUInt32(); uint size = resourceReader.ReadUInt32(); uint codePage = resourceReader.ReadUInt32(); uint reserved = resourceReader.ReadUInt32(); resources.GetDataReaderInfo(rva, size, out var dataReaderFactory, out var dataOffset, out var dataLength); return new ResourceData(entryInfo.name, dataReaderFactory, dataOffset, dataLength, codePage, reserved); } return new ResourceData(entryInfo.name); } private void InitializeDefault() { directories = new LazyList<ResourceDirectory>(); data = new LazyList<ResourceData>(); } } public abstract class ResourceDirectoryEntry { private ResourceName name; public ResourceName Name { get { return name; } set { name = value; } } protected ResourceDirectoryEntry(ResourceName name) { this.name = name; } public override string ToString() { return name.ToString(); } } public readonly struct ResourceName : IComparable<ResourceName>, IEquatable<ResourceName> { private readonly int id; private readonly string name; public bool HasId => name == null; public bool HasName => name != null; public int Id => id; public string Name => name; public ResourceName(int id) { this.id = id; name = null; } public ResourceName(string name) { id = 0; this.name = name; } public static implicit operator ResourceName(int id) { return new ResourceName(id); } public static implicit operator ResourceName(string name) { return new ResourceName(name); } public static bool operator <(ResourceName left, ResourceName right) { return left.CompareTo(right) < 0; } public static bool operator <=(ResourceName left, ResourceName right) { return left.CompareTo(right) <= 0; } public static bool operator >(ResourceName left, ResourceName right) { return left.CompareTo(right) > 0; } public static bool operator >=(ResourceName left, ResourceName right) { return left.CompareTo(right) >= 0; } public static bool operator ==(ResourceName left, ResourceName right) { return left.Equals(right); } public static bool operator !=(ResourceName left, ResourceName right) { return !left.Equals(right); } public int CompareTo(ResourceName other) { if (HasId != other.HasId) { if (!HasName) { return 1; } return -1; } if (HasId) { return id.CompareTo(other.id); } return name.ToUpperInvariant().CompareTo(other.name.ToUpperInvariant()); } public bool Equals(ResourceName other) { return CompareTo(other) == 0; } public override bool Equals(object obj) { if (!(obj is ResourceName)) { return false; } return Equals((ResourceName)obj); } public override int GetHashCode() { if (HasId) { return id; } return name.GetHashCode(); } public override string ToString() { if (!HasId) { return name; } return id.ToString(); } } public abstract class Win32Resources : IDisposable { public abstract ResourceDirectory Root { get; set; } public ResourceDirectory Find(ResourceName type) { return Root?.FindDirectory(type); } public ResourceDirectory Find(ResourceName type, ResourceName name) { return Find(type)?.FindDirectory(name); } public ResourceData Find(ResourceName type, ResourceName name, ResourceName langId) { return Find(type, name)?.FindData(langId); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { Root = null; } } } public class Win32ResourcesUser : Win32Resources { private ResourceDirectory root = new ResourceDirectoryUser(new ResourceName("root")); public override ResourceDirectory Root { get { return root; } set { Interlocked.Exchange(ref root, value); } } } public sealed class Win32ResourcesPE : Win32Resources { private readonly IRvaFileOffsetConverter rvaConverter; private DataReaderFactory dataReader_factory; private uint dataReader_offset; private uint dataReader_length; private bool owns_dataReader_factory; private DataReaderFactory rsrcReader_factory; private uint rsrcReader_offset; private uint rsrcReader_length; private bool owns_rsrcReader_factory; private UserValue<ResourceDirectory> root; private readonly Lock theLock = Lock.Create(); public override ResourceDirectory Root { get { return root.Value; } set { if (!root.IsValueInitialized || root.Value != value) { root.Value = value; } } } internal DataReader GetResourceReader() { return rsrcReader_factory.CreateReader(rsrcReader_offset, rsrcReader_length); } public Win32ResourcesPE(IRvaFileOffsetConverter rvaConverter, DataReaderFactory rsrcReader_factory, uint rsrcReader_offset, uint rsrcReader_length, bool owns_rsrcReader_factory, DataReaderFactory dataReader_factory, uint dataReader_offset, uint dataReader_length, bool owns_dataReader_factory) { this.rvaConverter = rvaConverter ?? throw new ArgumentNullException("rvaConverter"); this.rsrcReader_factory = rsrcReader_factory ?? throw new ArgumentNullException("rsrcReader_factory"); this.rsrcReader_offset = rsrcReader_offset; this.rsrcReader_length = rsrcReader_length; this.owns_rsrcReader_factory = owns_rsrcReader_factory; this.dataReader_factory = dataReader_factory ?? throw new ArgumentNullException("dataReader_factory"); this.dataReader_offset = dataReader_offset; this.dataReader_length = dataReader_length; this.owns_dataReader_factory = owns_dataReader_factory; Initialize(); } public Win32ResourcesPE(IPEImage peImage) : this(peImage, null, 0u, 0u, owns_rsrcReader_factory: false) { } public Win32ResourcesPE(IPEImage peImage, DataReaderFactory rsrcReader_factory, uint rsrcReader_offset, uint rsrcReader_length, bool owns_rsrcReader_factory) { rvaConverter = peImage ?? throw new ArgumentNullException("peImage"); dataReader_factory = peImage.DataReaderFactory; dataReader_offset = 0u; dataReader_length = dataReader_factory.Length; if (rsrcReader_factory != null) { this.rsrcReader_factory = rsrcReader_factory; this.rsrcReader_offset = rsrcReader_offset; this.rsrcReader_length = rsrcReader_length; this.owns_rsrcReader_factory = owns_rsrcReader_factory; } else { ImageDataDirectory imageDataDirectory = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[2]; if (imageDataDirectory.VirtualAddress != 0 && imageDataDirectory.Size != 0) { DataReader dataReader = peImage.CreateReader(imageDataDirectory.VirtualAddress, imageDataDirectory.Size); this.rsrcReader_factory = peImage.DataReaderFactory; this.rsrcReader_offset = dataReader.StartOffset; this.rsrcReader_length = dataReader.Length; } else { this.rsrcReader_factory = ByteArrayDataReaderFactory.Create(Array2.Empty<byte>(), null); this.rsrcReader_offset = 0u; this.rsrcReader_length = 0u; } } Initialize(); } private void Initialize() { root.ReadOriginalValue = delegate { DataReaderFactory dataReaderFactory = rsrcReader_factory; if (dataReaderFactory == null) { return (ResourceDirectory)null; } DataReader reader = dataReaderFactory.CreateReader(rsrcReader_offset, rsrcReader_length); return new ResourceDirectoryPE(0u, new ResourceName("root"), this, ref reader); }; root.Lock = theLock; } public DataReader CreateReader(RVA rva, uint size) { GetDataReaderInfo(rva, size, out var dataReaderFactory, out var dataOffset, out var dataLength); return dataReaderFactory.CreateReader(dataOffset, dataLength); } internal void GetDataReaderInfo(RVA rva, uint size, out DataReaderFactory dataReaderFactory, out uint dataOffset, out uint dataLength) { dataOffset = (uint)rvaConverter.ToFileOffset(rva); if ((ulong)((long)dataOffset + (long)size) <= (ulong)dataReader_factory.Length) { dataReaderFactory = dataReader_factory; dataLength = size; } else { dataReaderFactory = ByteArrayDataReaderFactory.Create(Array2.Empty<byte>(), null); dataOffset = 0u; dataLength = 0u; } } protected override void Dispose(bool disposing) { if (disposing) { if (owns_dataReader_factory) { dataReader_factory?.Dispose(); } if (owns_rsrcReader_factory) { rsrcReader_factory?.Dispose(); } dataReader_factory = null; rsrcReader_factory = null; base.Dispose(disposing); } } } } namespace dnlib.Utils { internal class CollectionDebugView<TValue> { private readonly ICollection<TValue> list; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public TValue[] Items { get { TValue[] array = new TValue[list.Count]; list.CopyTo(array, 0); return array; } } public CollectionDebugView(ICollection<TValue> list) { this.list = list ?? throw new ArgumentNullException("list"); } } internal class CollectionDebugView<TValue, TOther> : CollectionDebugView<TValue> { public CollectionDebugView(ICollection<TValue> list) : base(list) { } } internal sealed class LocalList_CollectionDebugView : CollectionDebugView<Local> { public LocalList_CollectionDebugView(LocalList list) : base((ICollection<Local>)list) { } } internal sealed class ParameterList_CollectionDebugView : CollectionDebugView<Parameter> { public ParameterList_CollectionDebugView(ParameterList list) : base((ICollection<Parameter>)list) { } } internal interface ILazyList<TValue> : IList<TValue>, ICollection<TValue>, IEnumerable<TValue>, IEnumerable { } public interface IListListener<TListValue> { void OnLazyAdd(int index, ref TListValue value); void OnAdd(int index, TListValue value); void OnRemove(int index, TListValue value); void OnResize(int index); void OnClear(); } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(CollectionDebugView<>))] public class LazyList<TValue> : ILazyList<TValue>, IList<TValue>, ICollection<TValue>, IEnumerable<TValue>, IEnumerable where TValue : class { private protected class Element { protected TValue value; public virtual bool IsInitialized_NoLock => true; protected Element() { } public Element(TValue data) { value = data; } public virtual TValue GetValue_NoLock(int index) { return value; } public virtual void SetValue_NoLock(int index, TValue value) { this.value = value; } public override string ToString() { return value?.ToString() ?? string.Empty; } } public struct Enumerator : IEnumerator<TValue>, IEnumerator, IDisposable { private readonly LazyList<TValue> list; private readonly int id; private int index; private TValue current; public TValue Current => current; object IEnumerator.Current => current; internal Enumerator(LazyList<TValue> list) { this.list = list; index = 0; current = null; list.theLock.EnterReadLock(); try { id = list.id; } finally { list.theLock.ExitReadLock(); } } public bool MoveNext() { list.theLock.EnterWriteLock(); try { if (list.id == id && index < list.Count_NoLock) { current = list.list[index].GetValue_NoLock(index); index++; return true; } return MoveNextDoneOrThrow_NoLock(); } finally { list.theLock.ExitWriteLock(); } } private bool MoveNextDoneOrThrow_NoLock() { if (list.id != id) { throw new InvalidOperationException("List was modified"); } current = null; return false; } public void Dispose() { } void IEnumerator.Reset() { throw new NotSupportedException(); } } private protected readonly List<Element> list; private int id; private protected readonly IListListener<TValue> listener; private readonly Lock theLock = Lock.Create(); public int Count { get { theLock.EnterReadLock(); try { return Count_NoLock; } finally { theLock.ExitReadLock(); } } } internal int Count_NoLock => list.Count; public bool IsReadOnly => false; public TValue this[int index] { get { theLock.EnterWriteLock(); try { return Get_NoLock(index); } finally { theLock.ExitWriteLock(); } } set { theLock.EnterWriteLock(); try { Set_NoLock(index, value); } finally { theLock.ExitWriteLock(); } } } internal TValue Get_NoLock(int index) { return list[index].GetValue_NoLock(index); } private void Set_NoLock(int index, TValue value) { if (listener != null) { listener.OnRemove(index, list[index].GetValue_NoLock(index)); listener.OnAdd(index, value); } list[index].SetValue_NoLock(index, value); id++; } public LazyList() : this((IListListener<TValue>)null) { } public LazyList(IListListener<TValue> listener) { this.listener = listener; list = new List<Element>(); } private protected LazyList(int length, IListListener<TValue> listener) { this.listener = listener; list = new List<Element>(length); } public int IndexOf(TValue item) { theLock.EnterWriteLock(); try { return IndexOf_NoLock(item); } finally { theLock.ExitWriteLock(); } } private int IndexOf_NoLock(TValue item) { for (int i = 0; i < list.Count; i++) { if (list[i].GetValue_NoLock(i) == item) { return i; } } return -1; } public void Insert(int index, TValue item) { theLock.EnterWriteLock(); try { Insert_NoLock(index, item); } finally { theLock.ExitWriteLock(); } } private void Insert_NoLock(int index, TValue item) { if (listener != null) { listener.OnAdd(index, item); } list.Insert(index, new Element(item)); if (listener != null) { listener.OnResize(index); } id++; } public void RemoveAt(int index) { theLock.EnterWriteLock(); try { RemoveAt_NoLock(index); } finally { theLock.ExitWriteLock(); } } private void RemoveAt_NoLock(int index) { if (listener != null) { listener.OnRemove(index, list[index].GetValue_NoLock(index)); } list.RemoveAt(index); if (listener != null) { listener.OnResize(index); } id++; } public void Add(TValue item) { theLock.EnterWriteLock(); try { Add_NoLock(item); } finally { theLock.ExitWriteLock(); } } private void Add_NoLock(TValue item) { int count = list.Count; if (listener != null) { listener.OnAdd(count, item); } list.Add(new Element(item)); if (listener != null) { listener.OnResize(count); } id++; } public void Clear() { theLock.EnterWriteLock(); try { Clear_NoLock(); } finally { theLock.ExitWriteLock(); } } private void Clear_NoLock() { if (listener != null) { listener.OnClear(); } list.Clear(); if (listener != null) { listener.OnResize(0); } id++; } public bool Contains(TValue item) { return IndexOf(item) >= 0; } public void CopyTo(TValue[] array, int arrayIndex) { theLock.EnterWriteLock(); try { CopyTo_NoLock(array, arrayIndex); } finally { theLock.ExitWriteLock(); } } private void CopyTo_NoLock(TValue[] array, int arrayIndex) { for (int i = 0; i < list.Count; i++) { array[arrayIndex + i] = list[i].GetValue_NoLock(i); } } public bool Remove(TValue item) { theLock.EnterWriteLock(); try { return Remove_NoLock(item); } finally { theLock.ExitWriteLock(); } } private bool Remove_NoLock(TValue item) { int num = IndexOf_NoLock(item); if (num < 0) { return false; } RemoveAt_NoLock(num); return true; } internal bool IsInitialized(int index) { theLock.EnterReadLock(); try { return IsInitialized_NoLock(index); } finally { theLock.ExitReadLock(); } } private bool IsInitialized_NoLock(int index) { if ((uint)index >= (uint)list.Count) { return false; } return list[index].IsInitialized_NoLock; } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() { return GetEnumerator(); } internal IEnumerable<TValue> GetEnumerable_NoLock() { int id2 = id; for (int i = 0; i < list.Count; i++) { if (id != id2) { throw new InvalidOperationException("List was modified"); } yield return list[i].GetValue_NoLock(i); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(CollectionDebugView<, >))] public class LazyList<TValue, TContext> : LazyList<TValue>, ILazyList<TValue>, IList<TValue>, ICollection<TValue>, IEnumerable<TValue>, IEnumerable where TValue : class { private sealed class LazyElement : Element { internal readonly int origIndex; private LazyList<TValue, TContext> lazyList; public override bool IsInitialized_NoLock => lazyList == null; public override TValue GetValue_NoLock(int index) { if (lazyList != null) { value = lazyList.ReadOriginalValue_NoLock(index, origIndex); lazyList = null; } return value; } public override void SetValue_NoLock(int index, TValue value) { base.value = value; lazyList = null; } public LazyElement(int origIndex, LazyList<TValue, TContext> lazyList) { this.origIndex = origIndex; this.lazyList = lazyList; } public override string ToString() { if (lazyList != null) { value = lazyList.ReadOriginalValue_NoLock(this); lazyList = null; } if (value != null) { return value.ToString(); } return string.Empty; } } private TContext context; private readonly Func<TContext, int, TValue> readOriginalValue; public LazyList() : this((IListListener<TValue>)null) { } public LazyList(IListListener<TValue> listener) : base(listener) { } public LazyList(int length, TContext context, Func<TContext, int, TValue> readOriginalValue) : this(length, (IListListener<TValue>)null, context, readOriginalValue) { } public LazyList(int length, IListListener<TValue> listener, TContext context, Func<TContext, int, TValue> readOriginalValue) : base(length, listener) { this.context = context; this.readOriginalValue = readOriginalValue; for (int i = 0; i < length; i++) { list.Add(new LazyElement(i, this)); } } private TValue ReadOriginalValue_NoLock(LazyElement elem) { return ReadOriginalValue_NoLock(list.IndexOf(elem), elem.origIndex); } private TValue ReadOriginalValue_NoLock(int index, int origIndex) { TValue value = readOriginalValue(context, origIndex); listener?.OnLazyAdd(index, ref value); return value; } } [DebuggerDisplay("Count = {Length}")] internal sealed class SimpleLazyList<T> where T : class { [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] private readonly T[] elements; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Func<uint, T> readElementByRID; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly uint length; public uint Length => length; public T this[uint index] { get { if (index >= length) { return null; } if (elements[index] == null) { Interlocked.CompareExchange(ref elements[index], readElementByRID(index + 1), null); } return elements[index]; } } public SimpleLazyList(uint length, Func<uint, T> readElementByRID) { this.length = length; this.readElementByRID = readElementByRID; elements = new T[length]; } } [DebuggerDisplay("Count = {Length}")] internal sealed class SimpleLazyList2<T> where T : class, IContainsGenericParameter2 { [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] private readonly T[] elements; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Func<uint, GenericParamContext, T> readElementByRID; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly uint length; public uint Length => length; public T this[uint index, GenericParamContext gpContext] { get { if (index >= length) { return null; } if (elements[index] == null) { T val = readElementByRID(index + 1, gpContext); if (val.ContainsGenericParameter) { return val; } Interlocked.CompareExchange(ref elements[index], val, null); } return elements[index]; } } public SimpleLazyList2(uint length, Func<uint, GenericParamContext, T> readElementByRID) { this.length = length; this.readElementByRID = readElementByRID; elements = new T[length]; } } [DebuggerDisplay("{value}")] internal struct UserValue<TValue> { private Lock theLock; private Func<TValue> readOriginalValue; private TValue value; private bool isUserValue; private bool isValueInitialized; public Lock Lock { set { theLock = value; } } public Func<TValue> ReadOriginalValue { set { readOriginalValue = value; } } public TValue Value { get { theLock?.EnterWriteLock(); try { if (!isValueInitialized) { value = readOriginalValue(); readOriginalValue = null; isValueInitialized = true; } return value; } finally { theLock?.ExitWriteLock(); } } set { theLock?.EnterWriteLock(); try { this.value = value; readOriginalValue = null; isUserValue = true; isValueInitialized = true; } finally { theLock?.ExitWriteLock(); } } } public bool IsValueInitialized { get { theLock?.EnterReadLock(); try { return isValueInitialized; } finally { theLock?.ExitReadLock(); } } } public bool IsUserValue { get { theLock?.EnterReadLock(); try { return isUserValue; } finally { theLock?.ExitReadLock(); } } } } } namespace dnlib.Threading { public interface ICancellationToken { void ThrowIfCancellationRequested(); } [Serializable] internal class LockException : Exception { public LockException() { } public LockException(string msg) : base(msg) { } protected LockException(SerializationInfo info, StreamingContext context) : base(info, context) { } } internal class Lock { private readonly object lockObj; private int recurseCount; public static Lock Create() { return new Lock(); } private Lock() { lockObj = new object(); recurseCount = 0; } public void EnterReadLock() { Monitor.Enter(lockObj); if (recurseCount != 0) { Monitor.Exit(lockObj); throw new LockException("Recursive locks aren't supported"); } recurseCount++; } public void ExitReadLock() { if (recurseCount <= 0) { throw new LockException("Too many exit lock method calls"); } recurseCount--; Monitor.Exit(lockObj); } public void EnterWriteLock() { Monitor.Enter(lockObj); if (recurseCount != 0) { Monitor.Exit(lockObj); throw new LockException("Recursive locks aren't supported"); } recurseCount--; } public void ExitWriteLock() { if (recurseCount >= 0) { throw new LockException("Too many exit lock method calls"); } recurseCount++; Monitor.Exit(lockObj); } } } namespace dnlib.PE { [Flags] public enum Characteristics : ushort { RelocsStripped = 1, ExecutableImage = 2, LineNumsStripped = 4, LocalSymsStripped = 8, AggressiveWsTrim = 0x10, LargeAddressAware = 0x20, Reserved1 = 0x40, BytesReversedLo = 0x80, Bit32Machine = 0x100, DebugStripped = 0x200, RemovableRunFromSwap = 0x400, NetRunFromSwap = 0x800, System = 0x1000, Dll = 0x2000, UpSystemOnly = 0x4000, BytesReversedHi = 0x8000 } [Flags] public enum DllCharacteristics : ushort { Reserved1 = 1, Reserved2 = 2, Reserved3 = 4, Reserved4 = 8, Reserved5 = 0x10, HighEntropyVA = 0x20, DynamicBase = 0x40, ForceIntegrity = 0x80, NxCompat = 0x100, NoIsolation = 0x200, NoSeh = 0x400, NoBind = 0x800, AppContainer = 0x1000, WdmDriver = 0x2000, GuardCf = 0x4000, TerminalServerAware = 0x8000 } public interface IImageOptionalHeader : IFileSection { ushort Magic { get; } byte MajorLinkerVersion { get; } byte MinorLinkerVersion { get; } uint SizeOfCode { get; } uint SizeOfInitializedData { get; } uint SizeOfUninitializedData { get; } RVA AddressOfEntryPoint { get; } RVA BaseOfCode { get; } RVA BaseOfData { get; } ulong ImageBase { get; } uint SectionAlignment { get; } uint FileAlignment { get; } ushort MajorOperatingSystemVersion { get; } ushort MinorOperatingSystemVersion { get; } ushort MajorImageVersion { get; } ushort MinorImageVersion { get; } ushort MajorSubsystemVersion { get; } ushort MinorSubsystemVersion { get; } uint Win32VersionValue { get; } uint SizeOfImage { get; } uint SizeOfHeaders { get; } uint CheckSum { get; } Subsystem Subsystem { get; } DllCharacteristics DllCharacteristics { get; } ulong SizeOfStackReserve { get; } ulong SizeOfStackCommit { get; } ulong SizeOfHeapReserve { get; } ulong SizeOfHeapCommit { get; } uint LoaderFlags { get; } uint NumberOfRvaAndSizes { get; } ImageDataDirectory[] DataDirectories { get; } } [DebuggerDisplay("{virtualAddress} {dataSize}")] public sealed class ImageDataDirectory : FileSection { private readonly RVA virtualAddress; private readonly uint dataSize; public RVA VirtualAddress => virtualAddress; public uint Size => dataSize; public ImageDataDirectory() { } public ImageDataDirectory(ref DataReader reader, bool verify) { SetStartOffset(ref reader); virtualAddress = (RVA)reader.ReadUInt32(); dataSize = reader.ReadUInt32(); SetEndoffset(ref reader); } } [DebuggerDisplay("{type}: TS:{timeDateStamp,h} V:{majorVersion,d}.{minorVersion,d} SZ:{sizeOfData} RVA:{addressOfRawData,h} FO:{pointerToRawData,h}")] public sealed class ImageDebugDirectory : FileSection { private readonly uint characteristics; private readonly uint timeDateStamp; private readonly ushort majorVersion; private readonly ushort minorVersion; private readonly ImageDebugType type; private readonly uint sizeOfData; private readonly uint addressOfRawData; private readonly uint pointerToRawData; public uint Characteristics => characteristics; public uint TimeDateStamp => timeDateStamp; public ushort MajorVersion => majorVersion; public ushort MinorVersion => minorVersion; public ImageDebugType Type => type; public uint SizeOfData => sizeOfData; public RVA AddressOfRawData => (RVA)addressOfRawData; public FileOffset PointerToRawData => (FileOffset)pointerToRawData; public ImageDebugDirectory(ref DataReader reader, bool verify) { SetStartOffset(ref reader); characteristics = reader.ReadUInt32(); timeDateStamp = reader.ReadUInt32(); majorVersion = reader.ReadUInt16(); minorVersion = reader.ReadUInt16(); type = (ImageDebugType)reader.ReadUInt32(); sizeOfData = reader.ReadUInt32(); addressOfRawData = reader.ReadUInt32(); pointerToRawData = reader.ReadUInt32(); SetEndoffset(ref reader); } } public enum ImageDebugType : uint { Unknown = 0u, Coff = 1u, CodeView = 2u, FPO = 3u, Misc = 4u, Exception = 5u, Fixup = 6u, OmapToSrc = 7u, OmapFromSrc = 8u, Borland = 9u, Reserved10 = 10u, CLSID = 11u, VcFeature = 12u, POGO = 13u, ILTCG = 14u, MPX = 15u, Reproducible = 16u, EmbeddedPortablePdb = 17u, PdbChecksum = 19u } public sealed class ImageDosHeader : FileSection { private readonly uint ntHeadersOffset; public uint NTHeadersOffset => ntHeadersOffset; public ImageDosHeader(ref DataReader reader, bool verify) { SetStartOffset(ref reader); ushort num = reader.ReadUInt16(); if (verify && num != 23117) { throw new BadImageFormatException("Invalid DOS signature"); } reader.Position = (uint)(startOffset + 60); ntHeadersOffset = reader.ReadUInt32(); SetEndoffset(ref reader); } } public sealed class ImageFileHeader : FileSection { private readonly Machine machine; private readonly ushort numberOfSections; private readonly uint timeDateStamp; private readonly uint pointerToSymbolTable; private readonly uint numberOfSymbols; private readonly ushort sizeOfOptionalHeader; private readonly Characteristics characteristics; public Machine Machine => machine; public int NumberOfSections => numberOfSections; public uint TimeDateStamp => timeDateStamp; public uint PointerToSymbolTable => pointerToSymbolTable; public uint NumberOfSymbols => numberOfSymbols; public uint SizeOfOptionalHeader => sizeOfOptionalHeader; public Characteristics Characteristics => characteristics; public ImageFileHeader(ref DataReader reader, bool verify) { SetStartOffset(ref reader); machine = (Machine)reader.ReadUInt16(); numberOfSections = reader.ReadUInt16(); timeDateStamp = reader.ReadUInt32(); pointerToSymbolTable = reader.ReadUInt32(); numberOfSymbols = reader.ReadUInt32(); sizeOfOptionalHeader = reader.ReadUInt16(); characteristics = (Characteristics)reader.ReadUInt16(); SetEndoffset(ref reader); if (verify && sizeOfOptionalHeader == 0) { throw new BadImageFormatException("Invalid SizeOfOptionalHeader"); } } } public sealed class ImageNTHeaders : FileSection { private readonly uint signature; private readonly ImageFileHeader imageFileHeader; private readonly IImageOptionalHeader imageOptionalHeader; public uint Signature => signature; public ImageFileHeader FileHeader => imageFileHeader; public IImageOptionalHeader OptionalHeader => imageOptionalHeader; public ImageNTHeaders(ref DataReader reader, bool verify) { SetStartOffset(ref reader); signature = reader.ReadUInt32(); if (verify && (ushort)signature != 17744) { throw new BadImageFormatException("Invalid NT headers signature"); } imageFileHeader = new ImageFileHeader(ref reader, verify); imageOptionalHeader = CreateImageOptionalHeader(ref reader, verify); SetEndoffset(ref reader); } private IImageOptionalHeader CreateImageOptionalHeader(ref DataReader reader, bool verify) { ushort num = reader.ReadUInt16(); reader.Position -= 2u; return num switch { 267 => new ImageOptionalHeader32(ref reader, imageFileHeader.SizeOfOptionalHeader, verify), 523 => new ImageOptionalHeader64(ref reader, imageFileHeader.SizeOfOptionalHeader, verify), _ => throw new BadImageFormatException("Invalid optional header magic"), }; } } public sealed class ImageOptionalHeader32 : FileSection, IImageOptionalHeader, IFileSection { private readonly ushort magic; private readonly byte majorLinkerVersion; private readonly byte minorLinkerVersion; private readonly uint sizeOfCode; private readonly uint sizeOfInitializedData; private readonly uint sizeOfUninitializedData; private readonly RVA addressOfEntryPoint; private readonly RVA baseOfCode; private readonly RVA baseOfData; private readonly uint imageBase; private readonly uint sectionAlignment; private readonly uint fileAlignment; private readonly ushort majorOperatingSystemVersion; private readonly ushort minorOperatingSystemVersion; private readonly ushort majorImageVersion; private readonly ushort minorImageVersion; private readonly ushort majorSubsystemVersion; private readonly ushort minorSubsystemVersion; private readonly uint win32VersionValue; private readonly uint sizeOfImage; private readonly uint sizeOfHeaders; private readonly uint checkSum; private readonly Subsystem subsystem; private readonly DllCharacteristics dllCharacteristics; private readonly uint sizeOfStackReserve; private readonly uint sizeOfStackCommit; private readonly uint sizeOfHeapReserve; private readonly uint sizeOfHeapCommit; private readonly uint loaderFlags; private readonly uint numberOfRvaAndSizes; private readonly ImageDataDirectory[] dataDirectories = new ImageDataDirectory[16]; public ushort Magic => magic; public byte MajorLinkerVersion => majorLinkerVersion; public byte MinorLinkerVersion => minorLinkerVersion; public uint SizeOfCode => sizeOfCode; public uint SizeOfInitializedData => sizeOfInitializedData; public uint SizeOfUninitializedData => sizeOfUninitializedData; public RVA AddressOfEntryPoint => addressOfEntryPoint; public RVA BaseOfCode => baseOfCode; public RVA BaseOfData => baseOfData; public ulong ImageBase => imageBase; public uint SectionAlignment => sectionAlignment; public uint FileAlignment => fileAlignment; public ushort MajorOperatingSystemVersion => majorOperatingSystemVersion; public ushort MinorOperatingSystemVersion => minorOperatingSystemVersion; public ushort MajorImageVersion => majorImageVersion; public ushort MinorImageVersion => minorImageVersion; public ushort MajorSubsystemVersion => majorSubsystemVersion; public ushort MinorSubsystemVersion => minorSubsystemVersion; public uint Win32VersionValue => win32VersionValue; public uint SizeOfImage => sizeOfImage; public uint SizeOfHeaders => sizeOfHeaders; public uint CheckSum => checkSum; public Subsystem Subsystem => subsystem; public DllCharacteristics DllCharacteristics => dllCharacteristics; public ulong SizeOfStackReserve => sizeOfStackReserve; public ulong SizeOfStackCommit => sizeOfStackCommit; public ulong SizeOfHeapReserve => sizeOfHeapReserve; public ulong SizeOfHeapCommit => sizeOfHeapCommit; public uint LoaderFlags => loaderFlags; public uint NumberOfRvaAndSizes => numberOfRvaAndSizes; public ImageDataDirectory[] DataDirectories => dataDirectories; public ImageOptionalHeader32(ref DataReader reader, uint totalSize, bool verify) { if (totalSize < 96) { throw new BadImageFormatException("Invalid optional header size"); } if (verify && (ulong)((long)reader.Position + (long)totalSize) > (ulong)reader.Length) { throw new BadImageFormatException("Invalid optional header size"); } SetStartOffset(ref reader); magic = reader.ReadUInt16(); majorLinkerVersion = reader.ReadByte(); minorLinkerVersion = reader.ReadByte(); sizeOfCode = reader.ReadUInt32(); sizeOfInitializedData = reader.ReadUInt32(); sizeOfUninitializedData = reader.ReadUInt32(); addressOfEntryPoint = (RVA)reader.ReadUInt32(); baseOfCode = (RVA)reader.ReadUInt32(); baseOfData = (RVA)reader.ReadUInt32(); imageBase = reader.ReadUInt32(); sectionAlignment = reader.ReadUInt32(); fileAlignment = reader.ReadUInt32(); majorOperatingSystemVersion = reader.ReadUInt16(); minorOperatingSystemVersion = reader.ReadUInt16(); majorImageVersion = reader.ReadUInt16(); minorImageVersion = reader.ReadUInt16(); majorSubsystemVersion = reader.ReadUInt16(); minorSubsystemVersion = reader.ReadUInt16(); win32VersionValue = reader.ReadUInt32(); sizeOfImage = reader.ReadUInt32(); sizeOfHeaders = reader.ReadUInt32(); checkSum = reader.ReadUInt32(); subsystem = (Subsystem)reader.ReadUInt16(); dllCharacteristics = (DllCharacteristics)reader.ReadUInt16(); sizeOfStackReserve = reader.ReadUInt32(); sizeOfStackCommit = reader.ReadUInt32(); sizeOfHeapReserve = reader.ReadUInt32(); sizeOfHeapCommit = reader.ReadUInt32(); loaderFlags = reader.ReadUInt32(); numberOfRvaAndSizes = reader.ReadUInt32(); for (int i = 0; i < dataDirectories.Length; i++) { if ((uint)(reader.Position - startOffset + 8) <= totalSize) { dataDirectories[i] = new ImageDataDirectory(ref reader, verify); } else { dataDirectories[i] = new ImageDataDirectory(); } } reader.Position = (uint)(startOffset + totalSize); SetEndoffset(ref reader); } } public sealed class ImageOptionalHeader64 : FileSection, IImageOptionalHeader, IFileSection { private readonly ushort magic; private readonly byte majorLinkerVersion; private readonly byte minorLinkerVersion; private readonly uint sizeOfCode; private readonly uint sizeOfInitializedData; private readonly uint sizeOfUninitializedData; private readonly RVA addressOfEntryPoint; private readonly RVA baseOfCode; private readonly ulong imageBase; private readonly uint sectionAlignment; private readonly uint fileAlignment; private readonly ushort majorOperatingSystemVersion; private readonly ushort minorOperatingSystemVersion; private readonly ushort majorImageVersion; private readonly ushort minorImageVersion; private readonly ushort majorSubsystemVersion; private readonly ushort minorSubsystemVersion; private readonly uint win32VersionValue; private readonly uint sizeOfImage; private readonly uint sizeOfHeaders; private readonly uint checkSum; private readonly Subsystem subsystem; private readonly DllCharacteristics dllCharacteristics; private readonly ulong sizeOfStackReserve; private readonly ulong sizeOfStackCommit; private readonly ulong sizeOfHeapReserve; private readonly ulong sizeOfHeapCommit; private readonly uint loaderFlags; private readonly uint numberOfRvaAndSizes; private readonly ImageDataDirectory[] dataDirectories = new ImageDataDirectory[16]; public ushort Magic => magic; public byte MajorLinkerVersion => majorLinkerVersion; public byte MinorLinkerVersion => minorLinkerVersion; public uint SizeOfCode => sizeOfCode; public uint SizeOfInitializedData => sizeOfInitializedData; public uint SizeOfUninitializedData => sizeOfUninitializedData; public RVA AddressOfEntryPoint => addressOfEntryPoint; public RVA BaseOfCode => baseOfCode; public RVA BaseOfData => (RVA)0u; public ulong ImageBase => imageBase; public uint SectionAlignment => sectionAlignment; public uint FileAlignment => fileAlignment; public ushort MajorOperatingSystemVersion => majorOperatingSystemVersion; public ushort MinorOperatingSystemVersion => minorOperatingSystemVersion; public ushort MajorImageVersion => majorImageVersion; public ushort MinorImageVersion => minorImageVersion; public ushort MajorSubsystemVersion => majorSubsystemVersion; public ushort MinorSubsystemVersion => minorSubsystemVersion; public uint Win32VersionValue => win32VersionValue; public uint SizeOfImage => sizeOfImage; public uint SizeOfHeaders => sizeOfHeaders; public uint CheckSum => checkSum; public Subsystem Subsystem => subsystem; public DllCharacteristics DllCharacteristics => dllCharacteristics; public ulong SizeOfStackReserve => sizeOfStackReserve; public ulong SizeOfStackCommit => sizeOfStackCommit; public ulong SizeOfHeapReserve => sizeOfHeapReserve; public ulong SizeOfHeapCommit => sizeOfHeapCommit; public uint LoaderFlags => loaderFlags; public uint NumberOfRvaAndSizes => numberOfRvaAndSizes; public ImageDataDirectory[] DataDirectories => dataDirectories; public ImageOptionalHeader64(ref DataReader reader, uint totalSize, bool verify) { if (totalSize < 112) { throw new BadImageFormatException("Invalid optional header size"); } if (verify && (ulong)((long)reader.Position + (long)totalSize) > (ulong)reader.Length) { throw new BadImageFormatException("Invalid optional header size"); } SetStartOffset(ref reader); magic = reader.ReadUInt16(); majorLinkerVersion = reader.ReadByte(); minorLinkerVersion = reader.ReadByte(); sizeOfCode = reader.ReadUInt32(); sizeOfInitializedData = reader.ReadUInt32(); sizeOfUninitializedData = reader.ReadUInt32(); addressOfEntryPoint = (RVA)reader.ReadUInt32(); baseOfCode = (RVA)reader.ReadUInt32(); imageBase = reader.ReadUInt64(); sectionAlignment = reader.ReadUInt32(); fileAlignment = reader.ReadUInt32(); majorOperatingSystemVersion = reader.ReadUInt16(); minorOperatingSystemVersion = reader.ReadUInt16(); majorImageVersion = reader.ReadUInt16(); minorImageVersion = reader.ReadUInt16(); majorSubsystemVersion = reader.ReadUInt16(); minorSubsystemVersion = reader.ReadUInt16(); win32VersionValue = reader.ReadUInt32(); sizeOfImage = reader.ReadUInt32(); sizeOfHeaders = reader.ReadUInt32(); checkSum = reader.ReadUInt32(); subsystem = (Subsystem)reader.ReadUInt16(); dllCharacteristics = (DllCharacteristics)reader.ReadUInt16(); sizeOfStackReserve = reader.ReadUInt64(); sizeOfStackCommit = reader.ReadUInt64(); sizeOfHeapReserve = reader.ReadUInt64(); sizeOfHeapCommit = reader.ReadUInt64(); loaderFlags = reader.ReadUInt32(); numberOfRvaAndSizes = reader.ReadUInt32(); for (int i = 0; i < dataDirectories.Length; i++) { if ((uint)(reader.Position - startOffset + 8) <= totalSize) { dataDirectories[i] = new ImageDataDirectory(ref reader, verify); } else { dataDirectories[i] = new ImageDataDirectory(); } } reader.Position = (uint)(startOffset + totalSize); SetEndoffset(ref reader); } } [DebuggerDisplay("RVA:{virtualAddress} VS:{virtualSize} FO:{pointerToRawData} FS:{sizeOfRawData} {displayName}")] public sealed class ImageSectionHeader : FileSection { private readonly string displayName; private readonly byte[] name; private readonly uint virtualSize; private readonly RVA virtualAddress; private readonly uint sizeOfRawData; private readonly uint pointerToRawData; private readonly uint pointerToRelocations; private readonly uint pointerToLinenumbers; private readonly ushort numberOfRelocations; private readonly ushort numberOfLinenumbers; private readonly uint characteristics; public string DisplayName => displayName; public byte[] Name => name; public uint VirtualSize => virtualSize; public RVA VirtualAddress => virtualAddress; public uint SizeOfRawData => sizeOfRawData; public uint PointerToRawData => pointerToRawData; public uint PointerToRelocations => pointerToRelocations; public uint PointerToLinenumbers => pointerToLinenumbers; public ushort NumberOfRelocations => numberOfRelocations; public ushort NumberOfLinenumbers => numberOfLinenumbers; public uint Characteristics => characteristics; public ImageSectionHeader(ref DataReader reader, bool verify) { SetStartOffset(ref reader); name = reader.ReadBytes(8); virtualSize = reader.ReadUInt32(); virtualAddress = (RVA)reader.ReadUInt32(); sizeOfRawData = reader.ReadUInt32(); pointerToRawData = reader.ReadUInt32(); pointerToRelocations = reader.ReadUInt32(); pointerToLinenumbers = reader.ReadUInt32(); numberOfRelocations = reader.ReadUInt16(); numberOfLinenumbers = reader.ReadUInt16(); characteristics = reader.ReadUInt32(); SetEndoffset(ref reader); displayName = ToString(name); } private static string ToString(byte[] name) { StringBuilder stringBuilder = new StringBuilder(name.Length); foreach (byte b in name) { if (b == 0) { break; } stringBuilder.Append((char)b); } return stringBuilder.ToString(); } } public interface IRvaFileOffsetConverter { RVA ToRVA(FileOffset offset); FileOffset ToFileOffset(RVA rva); } public interface IPEImage : IRvaFileOffsetConverter, IDisposable { bool IsFileImageLayout { get; } bool MayHaveInvalidAddresses { get; } string Filename { get; } ImageDosHeader ImageDosHeader { get; } ImageNTHeaders ImageNTHeaders { get; } IList<ImageSectionHeader> ImageSectionHeaders { get; } IList<ImageDebugDirectory> ImageDebugDirectories { get; } Win32Resources Win32Resources { get; set; } DataReaderFactory DataReaderFactory { get; } DataReader CreateReader(FileOffset offset); DataReader CreateReader(FileOffset offset, uint length); DataReader CreateReader(RVA rva); DataReader CreateReader(RVA rva, uint length); DataReader CreateReader(); } public interface IInternalPEImage : IPEImage, IRvaFileOffsetConverter, IDisposable { bool IsMemoryMappedIO { get; } void UnsafeDisableMemoryMappedIO(); } public static class PEExtensions { public static ResourceData FindWin32ResourceData(this IPEImage self, ResourceName type, ResourceName name, ResourceName langId) { return self.Win32Resources?.Find(type, name, langId); } internal static uint CalculatePECheckSum(this Stream stream, long length, long checkSumOffset) { if ((length & 1) != 0L) { ThrowInvalidOperationException("Invalid PE length"); } byte[] buffer = new byte[(int)Math.Min(length, 8192L)]; uint checkSum = 0u; checkSum = CalculatePECheckSum(stream, checkSumOffset, checkSum, buffer); stream.Position += 4L; checkSum = CalculatePECheckSum(stream, length - checkSumOffset - 4, checkSum, buffer); ulong num = (ulong)(checkSum + length); return (uint)((int)num + (int)(num >> 32)); } private static uint CalculatePECheckSum(Stream stream, long length, uint checkSum, byte[] buffer) { int num3; for (long num = 0L; num < length; num += num3) { int num2 = (int)Math.Min(length - num, buffer.Length); num3 = stream.Read(buffer, 0, num2); if (num3 != num2) { ThrowInvalidOperationException("Couldn't read all bytes"); } int num4 = 0; while (num4 < num3) { checkSum += (uint)(buffer[num4++] | (buffer[num4++] << 8)); checkSum = (ushort)(checkSum + (checkSum >> 16)); } } return checkSum; } private static void ThrowInvalidOperationException(string message) { throw new InvalidOperationException(message); } public static RVA AlignUp(this RVA rva, uint alignment) { return (RVA)((uint)(rva + alignment - 1) & ~(alignment - 1)); } public static RVA AlignUp(this RVA rva, int alignment) { return (RVA)(((long)rva + (long)alignment - 1) & ~(alignment - 1)); } } internal interface IPEType { RVA ToRVA(PEInfo peInfo, FileOffset offset); FileOffset ToFileOffset(PEInfo peInfo, RVA rva); } public enum Machine : ushort { Unknown = 0, I386 = 332, R3000 = 354, R4000 = 358, R10000 = 360, WCEMIPSV2 = 361, ALPHA = 388, SH3 = 418, SH3DSP = 419, SH3E = 420, SH4 = 422, SH5 = 424, ARM = 448, THUMB = 450, ARMNT = 452, AM33 = 467, POWERPC = 496, POWERPCFP = 497, IA64 = 512, MIPS16 = 614, ALPHA64 = 644, MIPSFPU = 870, MIPSFPU16 = 1126, TRICORE = 1312, CEF = 3311, EBC = 3772, AMD64 = 34404, M32R = 36929, ARM64 = 43620, CEE = 49390, I386_Native_Apple = 18184, AMD64_Native_Apple = 49184, ARMNT_Native_Apple = 18304, ARM64_Native_Apple = 60448, S390X_Native_Apple = 17988, I386_Native_FreeBSD = 44168, AMD64_Native_FreeBSD = 11168, ARMNT_Native_FreeBSD = 44032, ARM64_Native_FreeBSD = 1952, S390X_Native_FreeBSD = 44484, I386_Native_Linux = 31285, AMD64_Native_Linux = 64797, ARMNT_Native_Linux = 31421, ARM64_Native_Linux = 53533, S390X_Native_Linux = 31609, I386_Native_NetBSD = 6367, AMD64_Native_NetBSD = 40951, ARMNT_Native_NetBSD = 6231, ARM64_Native_NetBSD = 46071, S390X_Native_NetBSD = 6547, I386_Native_Sun = 6366, AMD64_Native_Sun = 40950, ARMNT_Native_Sun = 6230, ARM64_Native_Sun = 46070, S390X_Native_Sun = 6546 } public static class MachineExtensions { public static bool Is64Bit(this Machine machine) { switch (machine) { case Machine.IA64: case Machine.ARM64_Native_FreeBSD: case Machine.AMD64_Native_FreeBSD: case Machine.AMD64: case Machine.AMD64_Native_Sun: case Machine.AMD64_Native_NetBSD: case Machine.ARM64: case Machine.ARM64_Native_Sun: case Machine.ARM64_Native_NetBSD: case Machine.AMD64_Native_Apple: case Machine.ARM64_Native_Linux: case Machine.ARM64_Native_Apple: case Machine.AMD64_Native_Linux: return true; case Machine.S390X_Native_Sun: case Machine.S390X_Native_NetBSD: case Machine.S390X_Native_Apple: case Machine.S390X_Native_Linux: case Machine.S390X_Native_FreeBSD: return true; default: return false; } } public static bool IsI386(this Machine machine) { switch (machine) { case Machine.I386: case Machine.I386_Native_Sun: case Machine.I386_Native_NetBSD: case Machine.I386_Native_Apple: case Machine.I386_Native_Linux: case Machine.I386_Native_FreeBSD: return true; default: return false; } } public static bool IsAMD64(this Machine machine) { switch (machine) { case Machine.AMD64_Native_FreeBSD: case Machine.AMD64: case Machine.AMD64_Native_Sun: case Machine.AMD64_Native_NetBSD: case Machine.AMD64_Native_Apple: case Machine.AMD64_Native_Linux: return true; default: return false; } } public static bool IsARMNT(this Machine machine) { switch (machine) { case Machine.ARMNT: case Machine.ARMNT_Native_Sun: case Machine.ARMNT_Native_NetBSD: case Machine.ARMNT_Native_Apple: case Machine.ARMNT_Native_Linux: case Machine.ARMNT_Native_FreeBSD: return true; default: return false; } } public static bool IsARM64(this Machine machine) { switch (machine) { case Machine.ARM64_Native_FreeBSD: case Machine.ARM64: case Machine.ARM64_Native_Sun: case Machine.ARM64_Native_NetBSD: case Machine.ARM64_Native_Linux: case Machine.ARM64_Native_Apple: return true; default: return false; } } public static bool IsS390x(this Machine machine) { switch (machine) { case Machine.S390X_Native_Sun: case Machine.S390X_Native_NetBSD: case Machine.S390X_Native_Apple: case Machine.S390X_Native_Linux: case Machine.S390X_Native_FreeBSD: return true; default: return false; } } } public enum ImageLayout { File, Memory } public sealed class PEImage : IInternalPEImage, IPEImage, IRvaFileOffsetConverter, IDisposable { private sealed class FilePEType : IPEType { public RVA ToRVA(PEInfo peInfo, FileOffset offset) { return peInfo.ToRVA(offset); } public FileOffset ToFileOffset(PEInfo peInfo, RVA rva) { return peInfo.ToFileOffset(rva); } } private sealed class MemoryPEType : IPEType { public RVA ToRVA(PEInfo peInfo, FileOffset offset) { return (RVA)offset; } public FileOffset ToFileOffset(PEInfo peInfo, RVA rva) { return (FileOffset)rva; } } private const bool USE_MEMORY_LAYOUT_WITH_MAPPED_FILES = false; private static readonly IPEType MemoryLayout = new MemoryPEType(); private static readonly IPEType FileLayout = new FilePEType(); private DataReaderFactory dataReaderFactory; private IPEType peType; private PEInfo peInfo; private UserValue<Win32Resources> win32Resources; private readonly Lock theLock = Lock.Create(); private ImageDebugDirectory[] imageDebugDirectories; public bool IsFileImageLayout => peType is FilePEType; public bool MayHaveInvalidAddresses => !IsFileImageLayout; public string Filename => dataReaderFactory.Filename; public ImageDosHeader ImageDosHeader => peInfo.ImageDosHeader; public ImageNTHeaders ImageNTHeaders => peInfo.ImageNTHeaders; public IList<ImageSectionHeader> ImageSectionHeaders => peInfo.ImageSectionHeaders; public IList<ImageDebugDirectory> ImageDebugDirectories { get { if (imageDebugDirectories == null) { imageDebugDirectories = ReadImageDebugDirectories(); } return imageDebugDirectories; } } public DataReaderFactory DataReaderFactory => dataReaderFactory; public Win32Resources Win32Resources { get { return win32Resources.Value; } set { IDisposable disposable = null; if (win32Resources.IsValueInitialized) { disposable = win32Resources.Value; if (disposable == value) { return; } } win32Resources.Value = value; disposable?.Dispose(); } } bool IInternalPEImage.IsMemoryMappedIO { get { if (dataReaderFactory is MemoryMappedDataReaderFactory memoryMappedDataReaderFactory) { return memoryMappedDataReaderFactory.IsMemoryMappedIO; } return false; } } public PEImage(DataReaderFactory dataReaderFactory, ImageLayout imageLayout, bool verify) { try { this.dataReaderFactory = dataReaderFactory; peType = ConvertImageLayout(imageLayout); DataReader reader = dataReaderFactory.CreateReader(); peInfo = new PEInfo(ref reader, verify); Initialize(); } catch { Dispose(); throw; } } private void Initialize() { win32Resources.ReadOriginalValue = delegate { ImageDataDirectory imageDataDirectory = peInfo.ImageNTHeaders.OptionalHeader.DataDirectories[2]; return (imageDataDirectory.VirtualAddress == (RVA)0u || imageDataDirectory.Size == 0) ? null : new Win32ResourcesPE(this); }; win32Resources.Lock = theLock; } private static IPEType ConvertImageLayout(ImageLayout imageLayout) { return imageLayout switch { ImageLayout.File => FileLayout, ImageLayout.Memory => MemoryLayout, _ => throw new ArgumentException("imageLayout"), }; } internal PEImage(string filename, bool mapAsImage, bool verify) : this(DataReaderFactoryFactory.Create(filename, mapAsImage), mapAsImage ? ImageLayout.Memory : ImageLayout.File, verify) { try { if (mapAsImage && dataReaderFactory is MemoryMappedDataReaderFactory) { ((MemoryMappedDataReaderFactory)dataReaderFactory).SetLength(peInfo.GetImageSize()); } } catch { Dispose(); throw; } } public PEImage(string filename, bool verify) : this(filename, mapAsImage: false, verify) { } public PEImage(string filename) : this(filename, verify: true) { } public PEImage(byte[] data, string filename, ImageLayout imageLayout, bool verify) : this(ByteArrayDataReaderFactory.Create(data, filename), imageLayout, verify) { } public PEImage(byte[] data, ImageLayout imageLayout, bool verify) : this(data, null, imageLayout, verify) { } public PEImage(byte[] data, bool verify) : this(data, null, ImageLayout.File, verify) { } public PEImage(byte[] data, string filename, bool verify) : this(data, filename, ImageLayout.File, verify) { } public PEImage(byte[] data) : this(data, null, verify: true) { } public PEImage(byte[] data, string filename) : this(data, filename, verify: true) { } public unsafe PEImage(IntPtr baseAddr, uint length, ImageLayout imageLayout, bool verify) : this(NativeMemoryDataReaderFactory.Create((byte*)(void*)baseAddr, length, null), imageLayout, verify) { } public PEImage(IntPtr baseAddr, uint length, bool verify) : this(baseAddr, length, ImageLayout.Memory, verify) { } public PEImage(IntPtr baseAddr, uint length) : this(baseAddr, length, verify: true) { } public unsafe PEImage(IntPtr baseAddr, ImageLayout imageLayout, bool verify) : this(NativeMemoryDataReaderFactory.Create((byte*)(void*)baseAddr, 65536u, null), imageLayout, verify) { try { ((NativeMemoryDataReaderFactory)dataReaderFactory).SetLength(peInfo.GetImageSize()); } catch { Dispose(); throw; } } public PEImage(IntPtr baseAddr, bool verify) : this(baseAddr, ImageLayout.Memory, verify) { } public PEImage(IntPtr baseAddr) : this(baseAddr, verify: true) { } public RVA ToRVA(FileOffset offset) { return peType.ToRVA(peInfo, offset); } public FileOffset ToFileOffset(RVA rva) { return peType.ToFileOffset(peInfo, rva); } public void Dispose() { IDisposable value; if (win32Resources.IsValueInitialized && (value = win32Resources.Value) != null) { value.Dispose(); } dataReaderFactory?.Dispose(); win32Resources.Value = null; dataReaderFactory = null; peType = null; peInfo = null; } public DataReader CreateReader(FileOffset offset) { return DataReaderFactory.CreateReader((uint)offset, (uint)(DataReaderFactory.Length - offset)); } public DataReader CreateReader(FileOffset offset, uint length) { return DataReaderFactory.CreateReader((uint)offset, length); } public DataReader CreateReader(RVA rva) { return CreateReader(ToFileOffset(rva)); } public DataReader CreateReader(RVA rva, uint length) { return CreateReader(ToFileOffset(rva), length); } public DataReader CreateReader() { return DataReaderFactory.CreateReader(); } void IInternalPEImage.UnsafeDisableMemoryMappedIO() { if (dataReaderFactory is MemoryMappedDataReaderFactory memoryMappedDataReaderFactory) { memoryMappedDataReaderFactory.UnsafeDisableMemoryMappedIO(); } } private ImageDebugDirectory[] ReadImageDebugDirectories() { try { ImageDataDirectory imageDataDirectory = ImageNTHeaders.OptionalHeader.DataDirectories[6]; if (imageDataDirectory.VirtualAddress == (RVA)0u) { return Array2.Empty<ImageDebugDirectory>(); } DataReader reader = DataReaderFactory.CreateReader(); if (imageDataDirectory.Size > reader.Length) { return Array2.Empty<ImageDebugDirectory>(); } int num = (int)(imageDataDirectory.Size / 28); if (num == 0) { return Array2.Empty<ImageDebugDirectory>(); } reader.CurrentOffset = (uint)ToFileOffset(imageDataDirectory.VirtualAddress); if ((ulong)((long)reader.CurrentOffset + (long)imageDataDirectory.Size) > (ulong)reader.Length) { return Array2.Empty<ImageDebugDirectory>(); } ImageDebugDirectory[] array = new ImageDebugDirectory[num]; for (int i = 0; i < array.Length; i++) { array[i] = new ImageDebugDirectory(ref reader, verify: true); } return array; } catch (IOException) { } return Array2.Empty<ImageDebugDirectory>(); } } internal sealed class PEInfo { private readonly ImageDosHeader imageDosHeader; private readonly ImageNTHeaders imageNTHeaders; private readonly ImageSectionHeader[] imageSectionHeaders; public ImageDosHeader ImageDosHeader => imageDosHeader; public ImageNTHeaders ImageNTHeaders => imageNTHeaders; public ImageSectionHeader[] ImageSectionHeaders => imageSectionHeaders; public PEInfo(ref DataReader reader, bool verify) { reader.Position = 0u; imageDosHeader = new ImageDosHeader(ref reader, verify); if (verify && imageDosHeader.NTHeadersOffset == 0) { throw new BadImageFormatException("Invalid NT headers offset"); } reader.Position = imageDosHeader.NTHeadersOffset; imageNTHeaders = new ImageNTHeaders(ref reader, verify); reader.Position = (uint)(imageNTHeaders.OptionalHeader.StartOffset + imageNTHeaders.FileHeader.SizeOfOptionalHeader); int num = imageNTHeaders.FileHeader.NumberOfSections; if (num > 0) { DataReader dataReader = reader; dataReader.Position += 20u; uint num2 = dataReader.ReadUInt32(); num = Math.Min(num, (int)((num2 - reader.Position) / 40)); } imageSectionHeaders = new ImageSectionHeader[num]; for (int i = 0; i < imageSectionHeaders.Length; i++) { imageSectionHeaders[i] = new ImageSectionHeader(ref reader, verify); } } public ImageSectionHeader ToImageSectionHeader(FileOffset offset) { ImageSectionHeader[] array = imageSectionHeaders; foreach (ImageSectionHeader imageSectionHeader in array) { if ((uint)offset >= imageSectionHeader.PointerToRawData && (uint)offset < imageSectionHeader.PointerToRawData + imageSectionHeader.SizeOfRawData) { return imageSectionHeader; } } return null; } public ImageSectionHeader ToImageSectionHeader(RVA rva) { uint sectionAlignment = imageNTHeaders.OptionalHeader.SectionAlignment; ImageSectionHeader[] array = imageSectionHeaders; foreach (ImageSectionHeader imageSectionHeader in array) { if (rva >= imageSectionHeader.VirtualAddress && rva < imageSectionHeader.VirtualAddress + dnlib.DotNet.Utils.AlignUp(imageSectionHeader.VirtualSize, sectionAlignment)) { return imageSectionHeader; } } return null; } public RVA ToRVA(FileOffset offset) { if (imageSectionHeaders.Length == 0) { return (RVA)offset; } ImageSectionHeader imageSectionHeader = imageSectionHeaders[imageSectionHeaders.Length - 1]; if ((uint)offset > imageSectionHeader.PointerToRawData + imageSectionHeader.SizeOfRawData) { return (RVA)0u; } ImageSectionHeader imageSectionHeader2 = ToImageSectionHeader(offset); if (imageSectionHeader2 != null) { return (RVA)((uint)(offset - imageSectionHeader2.PointerToRawData) + (uint)imageSectionHeader2.VirtualAddress); } return (RVA)offset; } public FileOffset ToFileOffset(RVA rva) { if ((uint)rva >= imageNTHeaders.OptionalHeader.SizeOfImage) { return (FileOffset)0u; } ImageSectionHeader imageSectionHeader = ToImageSectionHeader(rva); if (imageSectionHeader != null) { uint num = rva - imageSectionHeader.VirtualAddress; if (num < imageSectionHeader.SizeOfRawData) { return (FileOffset)(num + imageSectionHeader.PointerToRawData); } return (FileOffset)0u; } return (FileOffset)rva; } private static ulong AlignUp(ulong val, uint alignment) { return (val + alignment - 1) & ~(ulong)(alignment - 1); } public uint GetImageSize() { IImageOptionalHeader optionalHeader = ImageNTHeaders.OptionalHeader; uint sectionAlignment = optionalHeader.SectionAlignment; if (imageSectionHeaders.Length == 0) { return (uint)AlignUp(optionalHeader.SizeOfHeaders, sectionAlignment); } ImageSectionHeader imageSectionHeader = imageSectionHeaders[imageSectionHeaders.Length - 1]; return (uint)Math.Min(AlignUp((ulong)imageSectionHeader.VirtualAddress + (ulong)imageSectionHeader.VirtualSize, sectionAlignment), 4294967295uL); } } internal static class ProcessorArchUtils { private static class RuntimeInformationUtils { public static bool TryGet_RuntimeInformation_Architecture(out Machine machine) { return TryGetArchitecture((int)RuntimeInformation.ProcessArchitecture, out machine); } private static bool TryGetArchitecture(int architecture, out Machine machine) { switch (architecture) { case 0: machine = Machine.I386; return true; case 1: machine = Machine.AMD64; return true; case 2: machine = Machine.ARMNT; return true; case 3: machine = Machine.ARM64; return true; default: machine = Machine.Unknown; return false; } } } private static class WindowsUtils { private struct SYSTEM_INFO { public ushort wProcessorArchitecture; public ushort wReserved; public uint dwPageSize; public IntPtr lpMinimumApplicationAddress; public IntPtr lpMaximumApplicationAddress; public IntPtr dwActiveProcessorMask; public uint dwNumberOfProcessors; public uint dwProcessorType; public uint dwAllocationGranularity; public ushort wProcessorLevel; public ushort wProcessorRevision; } private enum ProcessorArchitecture : ushort { INTEL = 0, ARM = 5, IA64 = 6, AMD64 = 9, ARM64 = 12, UNKNOWN = ushort.MaxValue } private static bool canTryGetSystemInfo = true; [DllImport("kernel32")] private static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); public static bool TryGetProcessCpuArchitecture(out Machine machine) { if (canTryGetSystemInfo) { try { GetSystemInfo(out var lpSystemInfo); switch ((ProcessorArchitecture)lpSystemInfo.wProcessorArchitecture) { case ProcessorArchitecture.INTEL: machine = Machine.I386; return true; case ProcessorArchitecture.ARM: machine = Machine.ARMNT; return true; case ProcessorArchitecture.IA64: machine = Machine.IA64; return true; case ProcessorArchitecture.AMD64: machine = Machine.AMD64; return true; case ProcessorArchitecture.ARM64: machine = Machine.ARM64; return true; } } catch (EntryPointNotFoundException) { canTryGetSystemInfo = false; } catch (DllNotFoundException) { canTryGetSystemInfo = false; } } machine = Machine.Unknown; return false; } } private static Machine cachedMachine; public static Machine GetProcessCpuArchitecture() { if (cachedMachine == Machine.Unknown) { cachedMachine = GetProcessCpuArchitectureCore(); } return cachedMachine; } private static Machine GetProcessCpuArchitectureCore() { if (WindowsUtils.TryGetProcessCpuArchitecture(out var machine)) { return machine; } try { if (RuntimeInformationUtils.TryGet_RuntimeInformation_Architecture(out machine)) { return machine; } } catch (PlatformNotSupportedException) { } if (IntPtr.Size != 4) { return Machine.AMD64; } return Machine.I386; } } public enum RVA : uint { } public enum Subsystem : ushort { Unknown = 0, Native = 1, WindowsGui = 2, WindowsCui = 3, Os2Cui = 5, PosixCui = 7, NativeWindows = 8, WindowsCeGui = 9, EfiApplication = 10, EfiBootServiceDriver = 11, EfiRuntimeDriver = 12, EfiRom = 13, Xbox = 14, WindowsBootApplication = 16 } } namespace dnlib.IO { internal sealed class AlignedByteArrayDataStream : DataStream { private readonly byte[] data; public AlignedByteArrayDataStream(byte[] data) { this.data = data; } public unsafe override void ReadBytes(uint offset, void* destination, int length) { Marshal.Copy(data, (int)offset, (IntPtr)destination, length); } public override void ReadBytes(uint offset, byte[] destination, int destinationIndex, int length) { Array.Copy(data, (int)offset, destination, destinationIndex, length); } public override byte ReadByte(uint offset) { return data[offset]; } public override ushort ReadUInt16(uint offset) { int num = (int)offset; byte[] array = data; return (ushort)(array[num++] | (array[num] << 8)); } public override uint ReadUInt32(uint offset) { int num = (int)offset; byte[] array = data; return (uint)(array[num++] | (array[num++] << 8) | (array[num++] << 16) | (array[num] << 24)); } public override ulong ReadUInt64(uint offset) { int num = (int)offset; byte[] array = data; return array[num++] | ((ulong)array[num++] << 8) | ((ulong)array[num++] << 16) | ((ulong)array[num++] << 24) | ((ulong)array[num++] << 32) | ((ulong)array[num++] << 40) | ((ulong)array[num++] << 48) | ((ulong)array[num] << 56); } public unsafe override float ReadSingle(uint offset) { int num = (int)offset; byte[] array = data; uint num2 = (uint)(array[num++] | (array[num++] << 8) | (array[num++] << 16) | (array[num] << 24)); return *(float*)(&num2); } public unsafe override double ReadDouble(uint offset) { int num = (int)offset; byte[] array = data; ulong num2 = array[num++] | ((ulong)array[num++] << 8) | ((ulong)array[num++] << 16) | ((ulong)array[num++] << 24) | ((ulong)array[num++] << 32) | ((ulong)array[num++] << 40) | ((ulong)array[num++] << 48) | ((ulong)array[num] << 56); return *(double*)(&num2); } public unsafe override string ReadUtf16String(uint offset, int chars) { fixed (byte* ptr = data) { return new string((char*)(ptr + offset), 0, chars); } } public unsafe override string ReadString(uint offset, int length, Encoding encoding) { fixed (byte* ptr = data) { return new string((sbyte*)(ptr + offset), 0, length, encoding); } } public unsafe override bool TryGetOffsetOf(uint offset, uint endOffset, byte value, out uint valueOffset) { fixed (byte* ptr = data) { byte* ptr2 = ptr + offset; uint num = (endOffset - offset) / 4; for (uint num2 = 0u; num2 < num; num2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; } for (byte* ptr3 = ptr + endOffset; ptr2 != ptr3; ptr2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } } valueOffset = 0u; return false; } } } internal sealed class AlignedNativeMemoryDataStream : DataStream { private unsafe readonly byte* data; public unsafe AlignedNativeMemoryDataStream(byte* data) { this.data = data; } public unsafe override void ReadBytes(uint offset, void* destination, int length) { byte* ptr = data + offset; byte* ptr2 = (byte*)destination; int num = length / 4; length %= 4; for (int i = 0; i < num; i++) { *ptr2 = *ptr; ptr2++; ptr++; *ptr2 = *ptr; ptr2++; ptr++; *ptr2 = *ptr; ptr2++; ptr++; *ptr2 = *ptr; ptr2++; ptr++; } int num2 = 0; while (num2 < length) { *ptr2 = *ptr; num2++; ptr++; ptr2++; } } public unsafe override void ReadBytes(uint offset, byte[] destination, int destinationIndex, int length) { Marshal.Copy((IntPtr)(data + offset), destination, destinationIndex, length); } public unsafe override byte ReadByte(uint offset) { return data[offset]; } public unsafe override ushort ReadUInt16(uint offset) { byte* ptr = data + offset; return (ushort)(*(ptr++) | (*ptr << 8)); } public unsafe override uint ReadUInt32(uint offset) { byte* ptr = data + offset; return (uint)(*(ptr++) | (*(ptr++) << 8) | (*(ptr++) << 16) | (*ptr << 24)); } public unsafe override ulong ReadUInt64(uint offset) { byte* ptr = data + offset; return *(ptr++) | ((ulong)(*(ptr++)) << 8) | ((ulong)(*(ptr++)) << 16) | ((ulong)(*(ptr++)) << 24) | ((ulong)(*(ptr++)) << 32) | ((ulong)(*(ptr++)) << 40) | ((ulong)(*(ptr++)) << 48) | ((ulong)(*ptr) << 56); } public unsafe override float ReadSingle(uint offset) { byte* ptr = data + offset; uint num = (uint)(*(ptr++) | (*(ptr++) << 8) | (*(ptr++) << 16) | (*ptr << 24)); return *(float*)(&num); } public unsafe override double ReadDouble(uint offset) { byte* ptr = data + offset; ulong num = *(ptr++) | ((ulong)(*(ptr++)) << 8) | ((ulong)(*(ptr++)) << 16) | ((ulong)(*(ptr++)) << 24) | ((ulong)(*(ptr++)) << 32) | ((ulong)(*(ptr++)) << 40) | ((ulong)(*(ptr++)) << 48) | ((ulong)(*ptr) << 56); return *(double*)(&num); } public unsafe override string ReadUtf16String(uint offset, int chars) { return new string((char*)(data + offset), 0, chars); } public unsafe override string ReadString(uint offset, int length, Encoding encoding) { return new string((sbyte*)(data + offset), 0, length, encoding); } public unsafe override bool TryGetOffsetOf(uint offset, uint endOffset, byte value, out uint valueOffset) { byte* ptr = data; byte* ptr2 = ptr + offset; uint num = (endOffset - offset) / 4; for (uint num2 = 0u; num2 < num; num2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } ptr2++; } for (byte* ptr3 = ptr + endOffset; ptr2 != ptr3; ptr2++) { if (*ptr2 == value) { valueOffset = (uint)(ptr2 - ptr); return true; } } valueOffset = 0u; return false; } } public sealed class ByteArrayDataReaderFactory : DataReaderFactory { private DataStream stream; private string filename; private uint length; private byte[] data; public override string Filename => filename; public override uint Length => length; internal byte[] DataArray => data; internal uint DataOffset => 0u; private ByteArrayDataReaderFactory(byte[] data, string filename) { this.filename = filename; length = (uint)data.Length; stream = DataStreamFactory.Create(data); this.data = data; } public static ByteArrayDataReaderFactory Create(byte[] data, string filename) { if (data == null) { throw new ArgumentNullException("data"); } return new ByteArrayDataReaderFactory(data, filename); } public static DataReader CreateReader(byte[] data) { return Create(data, null).CreateReader(); } public override DataReader CreateReader(uint offset, uint length) { return CreateReader(stream, offset, length); } public override void Dispose() { stream = EmptyDataStream.Instance; length = 0u; filename = null; data = null; } } [Serializable] public sealed class DataReaderException : IOException { internal DataReaderException(string message) : base(message) { } internal DataReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } } [DebuggerDisplay("{StartOffset,h}-{EndOffset,h} Length={Length} BytesLeft={BytesLeft}")] public struct DataReader { private readonly DataStream stream; private readonly uint startOffset; private readonly uint endOffset; private uint currentOffset; public readonly uint StartOffset => startOffset; public readonly uint EndOffset => endOffset; public readonly uint Length => endOffset - startOffset; public uint CurrentOffset { readonly get { return currentOffset; } set { if (value < startOffset || value > endOffset) { ThrowDataReaderException("Invalid new CurrentOffset"); } currentOffset = value; } } public uint Position { readonly get { return currentOffset - startOffset; } set { if (value > Length) { ThrowDataReaderException("Invalid new Position"); } currentOffset = startOffset + value; } } public readonly uint BytesLeft => endOffset - currentOffset; public DataReader(DataStream stream, uint offset, uint length) { this.stream = stream; startOffset = offset; endOffset = offset + length; currentOffset = offset; } [Conditional("DEBUG")] private readonly void VerifyState() { } private static void ThrowNoMoreBytesLeft() { throw new DataReaderException("There's not enough bytes left to read"); } private static void ThrowDataReaderException(string message) { throw new DataReaderException(message); } private static void ThrowInvalidOperationException() { throw new InvalidOperationException(); } private static void ThrowArgumentNullException(string paramName) { throw new ArgumentNullException(paramName); } private static void ThrowInvalidArgument(string paramName) { throw new DataReaderException("Invalid argument value"); } public void Reset() { currentOffset = startOffset; } public readonly DataReader Slice(uint start, uint length) { if ((ulong)((long)start + (long)length) > (ulong)Length) { ThrowInvalidArgument("length"); } return new DataReader(stream, startOffset + start, length); } public readonly DataReader Slice(uint start) { if (start > Length) { ThrowInvalidArgument("start"); } return Slice(start, Length - start); } public readonly DataReader Slice(int start, int length) { if (start < 0) { ThrowInvalidArgument("start"); } if (length < 0) { ThrowInvalidArgument("length"); } return Slice((uint)start, (uint)length); } public readonly DataReader Slice(int start) { if (start < 0) { ThrowInvalidArgument("start"); } if ((uint)start > Length) { ThrowInvalidArgument("start"); } return Slice((uint)start, Length - (uint)start); } public readonly bool CanRead(int length) { if (length >= 0) { return (uint)length <= BytesLeft; } return false; } public readonly bool CanRead(uint length) { return length <= BytesLeft; } public bool ReadBoolean() { uint num = currentOffset; if (num == endOffset) { ThrowNoMoreBytesLeft(); } bool result = stream.ReadBoolean(num); currentOffset = num + 1; return result; } public char ReadChar() { uint num = currentOffset; if (endOffset - num < 2) { ThrowNoMoreBytesLeft(); } char result = stream.ReadChar(num); currentOffset = num + 2; return result; } public sbyte ReadSByte() { uint num = currentOffset; if (num == endOffset) { ThrowNoMoreBytesLeft(); } sbyte result = stream.ReadSByte(num); currentOffset = num + 1; return result; } public byte ReadByte() { uint num = currentOffset; if (num == endOffset) { ThrowNoMoreBytesLeft(); } byte result = stream.ReadByte(num); currentOffset = num + 1; return result; } public short ReadInt16() { uint num = currentOffset; if (endOffset - num < 2) { ThrowNoMoreBytesLeft(); } short result = stream.ReadInt16(num); currentOffset = num + 2; return result; } public ushort ReadUInt16() { uint num = currentOffset; if (endOffset - num < 2) { ThrowNoMoreBytesLeft(); } ushort result = stream.ReadUInt16(num); currentOffset = num + 2; return result; } public int ReadInt32() { uint num = currentOffset; if (endOffset - num < 4) { ThrowNoMoreBytesLeft(); } int result = stream.ReadInt32(num); currentOffset = num + 4; return result; } public uint ReadUInt32() { uint num = currentOffset; if (endOffset - num < 4) { ThrowNoMoreBytesLeft(); } uint result = stream.ReadUInt32(num); currentOffset = num + 4; return result; } internal byte Unsafe_ReadByte() { uint num = currentOffset; byte result = stream.ReadByte(num); currentOffset = num + 1; return result; } internal ushort Unsafe_ReadUInt16() { uint num = currentOffset; ushort result = stream.ReadUInt16(num); currentOffset = num + 2; return result; } internal uint Unsafe_ReadUInt32() { uint num = currentOffset; uint result = stream.ReadUInt32(num); currentOffset = num + 4; return result; } public long ReadInt64() { uint num = currentOffset; if (endOffset - num < 8) { ThrowNoMoreBytesLeft(); } long result = stream.ReadInt64(num); currentOffset = num + 8; return result; } public ulong ReadUInt64() { uint num = currentOffset; if (endOffset - num < 8) { ThrowNoMoreBytesLeft(); } ulong result = stream.ReadUInt64(num); currentOffset = num + 8; return result; } public float ReadSingle() { uint num = currentOffset; if (endOffset - num < 4) { ThrowNoMoreBytesLeft(); } float result = stream.ReadSingle(num); currentOffset = num + 4; return result; } public double ReadDouble() { uint num = currentOffset; if (endOffset - num < 8) { ThrowNoMoreBytesLeft(); } double result = stream.ReadDouble(num); currentOffset = num + 8; return result; } public Guid ReadGuid() { uint num = currentOffset; if (endOffset - num < 16) { ThrowNoMoreBytesLeft(); } Guid result = stream.ReadGuid(num); currentOffset = num + 16; return result; } public decimal ReadDecimal() { uint num = currentOffset; if (endOffset - num < 16) { ThrowNoMoreBytesLeft(); } decimal result = stream.ReadDecimal(num); currentOffset = num + 16; return result; } public string ReadUtf16String(int chars) { if (chars < 0) { ThrowInvalidArgument("chars"); } if (chars == 0) { return string.Empty; } uint num = (uint)(chars * 2); uint num2 = currentOffset; if (endOffset - num2 < num) { ThrowNoMoreBytesLeft(); } string result = ((num == 0) ? string.Empty : stream.ReadUtf16String(num2, chars)); currentOffset = num2 + num; return result; } public unsafe void ReadBytes(void* destination, int length) { if (destination == null && length != 0) { ThrowArgumentNullException("destination"); } if (length < 0) { ThrowInvalidArgument("length"); } if (length != 0) { uint num = currentOffset; if (endOffset - num < (uint)length) { ThrowNoMoreBytesLeft(); } stream.ReadBytes(num, destination, length); currentOffset = num + (uint)length; } } public void ReadBytes(byte[] destination, int destinationIndex, int length) { if (destination == null) { ThrowArgumentNullException("destination"); } if (destinationIndex < 0) { ThrowInvalidArgument("destinationIndex"); } if (length < 0) { ThrowInvalidArgument("length"); } if (length != 0) { uint num = currentOffset; if (endOffset - num < (uint)length) { ThrowNoMoreBytesLeft(); } stream.ReadBytes(num, destination, destinationIndex, length); currentOffset = num + (uint)length; } } public byte[] ReadBytes(int length) { if (length < 0) { ThrowInvalidArgument("length"); } if (length == 0) { return Array2.Empty<byte>(); } byte[] array = new byte[length]; ReadBytes(array, 0, length); return array; } public bool TryReadCompressedUInt32(out uint value) { uint num = currentOffset; uint num2 = endOffset - num; if (num2 == 0) { value = 0u; return false; } DataStream dataStream = stream; byte b = dataStream.ReadByte(num++); if ((b & 0x80) == 0) { value = b; currentOffset = num; return true; } if ((b & 0xC0) == 128) { if (num2 < 2) { value = 0u; return false; } value = (uint)(((b & 0x3F) << 8) | dataStream.ReadByte(num++)); currentOffset = num; return true; } if (num2 < 4) { value = 0u; return false; } value = (uint)(((b & 0x1F) << 24) | (dataStream.ReadByte(num++) << 16) | (dataStream.ReadByte(num++) << 8) | dataStream.ReadByte(num++)); currentOffset = num; return true; } public uint ReadCompressedUInt32() { if (!TryReadCompressedUInt32(out var value)) { ThrowNoMoreBytesLeft(); } return value; } public bool TryReadCompressedInt32(out int value) { uint num = currentOffset; uint num2 = endOffset - num; if (num2 == 0) { value = 0; return false; } DataStream dataStream = stream; byte b = dataStream.ReadByte(num++); if ((b & 0x80) == 0) { if ((b & 1) != 0) { value = -64 | (b >> 1); } else { value = b >> 1; } currentOffset = num; return true; } if ((b & 0xC0) == 128) { if (num2 < 2) { value = 0; return false; } uint num3 = (uint)(((b & 0x3F) << 8) | dataStream.ReadByte(num++)); if ((num3 & 1) != 0) { value = -8192 | (int)(num3 >> 1); } else { value = (int)(num3 >> 1); } currentOffset = num; return true; } if ((b & 0xE0) == 192) { if (num2 < 4) { value = 0; return false; } uint num4 = (uint)(((b & 0x1F) << 24) | (dataStream.ReadByte(num++) << 16) | (dataStream.ReadByte(num++) << 8) | dataStream.ReadByte(num++)); if ((num4 & 1) != 0) { value = -268435456 | (int)(num4 >> 1); } else { value = (int)(num4 >> 1); } currentOffset = num; return true; } value = 0; return false; } public int ReadCompressedInt32() { if (!TryReadCompressedInt32(out var value)) { ThrowNoMoreBytesLeft(); } return value; } public uint Read7BitEncodedUInt32() { uint num = 0u; int num2 = 0; for (int i = 0; i < 5; i++) { byte b = ReadByte(); num |= (uint)((b & 0x7F) << num2); if ((b & 0x80) == 0) { return num; } num2 += 7; } ThrowDataReaderException("Invalid encoded UInt32"); return 0u; } public int Read7BitEncodedInt32() { return (int)Read7BitEncodedUInt32(); } public string ReadSerializedString() { return ReadSerializedString(Encoding.UTF8); } public string ReadSerializedString(Encoding encoding) { if (encoding == null) { ThrowArgumentNullException("encoding"); } int num = Read7BitEncodedInt32(); if (num < 0) { ThrowNoMoreBytesLeft(); } if (num == 0) { return string.Empty; } return ReadString(num, encoding); } public readonly byte[] ToArray() { int length = (int)Length; if (length < 0) { ThrowInvalidOperationException(); } if (length == 0) { return Array2.Empty<byte>(); } byte[] array = new byte[length]; stream.ReadBytes(startOffset, array, 0, array.Length); return array; } public byte[] ReadRemainingBytes() { int bytesLeft = (int)BytesLeft; if (bytesLeft < 0) { ThrowInvalidOperationException(); } return ReadBytes(bytesLeft); } public byte[] TryReadBytesUntil(byte value) { uint num = currentOffset; uint num2 = endOffset; if (num == num2) { return null; } if (!stream.TryGetOffsetOf(num, num2, value, out var valueOffset)) { return null; } int num3 = (int)(valueOffset - num); if (num3 < 0) { return null; } return ReadBytes(num3); } public string TryReadZeroTerminatedUtf8String() { return TryReadZeroTerminatedString(Encoding.UTF8); } public string TryReadZeroTerminatedString(Encoding encoding) { if (encoding == null) { ThrowArgumentNullException("encoding"); } uint num = currentOffset; uint num2 = endOffset; if (num == num2) { return null; } if (!stream.TryGetOffsetOf(num, num2, 0, out var valueOffset)) { return null; } int num3 = (int)(valueOffset - num); if (num3 < 0) { return null; } string result = ((num3 == 0) ? string.Empty : stream.ReadString(num, num3, encoding)); currentOffset = valueOffset + 1; return result; } public string ReadUtf8String(int byteCount) { return ReadString(byteCount, Encoding.UTF8); } public string ReadString(int byteCount, Encoding encoding) { if (byteCount < 0) { ThrowInvalidArgument("byteCount"); } if (encoding == null) { ThrowArgumentNullException("encoding"); } if (byteCount == 0) { return string.Empty; } if ((uint)byteCount > Length) { ThrowInvalidArgument("byteCount"); } uint num = currentOffset; string result = stream.ReadString(num, byteCount, encoding); currentOffset = num + (uint)byteCount; return result; } public readonly Stream AsStream() { return new DataReaderStream(in this); } private readonly byte[] AllocTempBuffer() { return new byte[Math.Min(8192u, BytesLeft)]; } public void CopyTo(DataWriter destination) { if (destination == null) { ThrowArgumentNullException("destination"); } if (Position < Length) { CopyTo(destination.InternalStream, AllocTempBuffer()); } } public void CopyTo(DataWriter destination, byte[] dataBuffer) { if (destination == null) { ThrowArgumentNullException("destination"); } CopyTo(destination.InternalStream, dataBuffer); } public void CopyTo(BinaryWriter destination) { if (destination == null) { ThrowArgumentNullException("destination"); } if (Position < Length) { CopyTo(destination.BaseStream, AllocTempBuffer()); } } public void CopyTo(BinaryWriter destination, byte[] dataBuffer) { if (destination == null) { ThrowArgumentNullException("destination"); } CopyTo(destination.BaseStream, dataBuffer); } public void CopyTo(Stream destination) { if (destination == null) { ThrowArgumentNullException("destination"); } if (Position < Length) { CopyTo(destination, AllocTempBuffer()); } } public void CopyTo(Stream destination, byte[] dataBuffer) { if (destination == null) { ThrowArgumentNullException("destination"); } if (dataBuffer == null) { ThrowArgumentNullException("dataBuffer"); } if (Position < Length) { if (dataBuffer.Length == 0) { ThrowInvalidArgument("dataBuffer"); } uint num = BytesLeft; while (num != 0) { int num2 = (int)Math.Min((uint)dataBuffer.Length, num); num -= (uint)num2; ReadBytes(dataBuffer, 0, num2); destination.Write(dataBuffer, 0, num2); } } } } public abstract class DataReaderFactory : IDisposable { public abstract string Filename { get; } public abstract uint Length { get; } public virtual event EventHandler DataReaderInvalidated { add { } remove { } } public DataReader CreateReader() { return CreateReader(0u, Length); } public abstract DataReader CreateReader(uint offset, uint length); private static void ThrowArgumentOutOfRangeException(string paramName) { throw new ArgumentOutOfRangeException(paramName); } private static void Throw_CreateReader_2(int offset, int length) { if (offset < 0) { throw new ArgumentOutOfRangeException("offset"); } throw new ArgumentOutOfRangeException("length"); } public DataReader CreateReader(uint offset, int length) { if (length < 0) { ThrowArgumentOutOfRangeException("length"); } return CreateReader(offset, (uint)length); } public DataReader CreateReader(int offset, uint length) { if (offset < 0) { ThrowArgumentOutOfRangeException("offset"); } return CreateReader((uint)offset, length); } public DataReader CreateReader(int offset, int length) { if (offset < 0 || length < 0) { Throw_CreateReader_2(offset, length); } return CreateReader((uint)offset, (uint)length); } protected DataReader CreateReader(DataStream stream, uint offset, uint length) { uint length2 = Length; if (offset > length2) { offset = length2; } if ((ulong)((long)offset + (long)length) > (ulong)length2) { length = length2 - offset; } return new DataReader(stream, offset, length); } public abstract void Dispose(); } internal static class DataReaderFactoryFactory { private static readonly bool isUnix; static DataReaderFactoryFactory() { int platform = (int)Environment.OSVersion.Platform; if (platform == 4 || platform == 6 || platform == 128) { isUnix = true; } if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { isUnix = true; } } public static DataReaderFactory Create(string fileName, bool mapAsImage) { DataReaderFactory dataReaderFactory = CreateDataReaderFactory(fileName, mapAsImage); if (dataReaderFactory != null) { return dataReaderFactory; } return ByteArrayDataReaderFactory.Create(File.ReadAllBytes(fileName), fileName); } private static DataReaderFactory CreateDataReaderFactory(string fileName, bool mapAsImage) { if (!isUnix) { return MemoryMappedDataReaderFactory.CreateWindows(fileName, mapAsImage); } return MemoryMappedDataReaderFactory.CreateUnix(fileName, mapAsImage); } } internal sealed class DataReaderStream : Stream { private DataReader reader; private long position; public override bool CanRead => true; public override bool CanSeek => true; public override bool CanWrite => false; public override long Length => reader.Length; public override long Position { get { return position; } set { position = value; } } public DataReaderStream(in DataReader reader) { this.reader = reader; position = reader.Position; } public override void Flush() { } private bool CheckAndSetPosition() { if ((ulong)position > (ulong)reader.Length) { return false; } reader.Position = (uint)position; return true; } public override long Seek(long offset, SeekOrigin origin) { switch (origin) { case SeekOrigin.Begin: Position = offset; break; case SeekOrigin.Current: Position += offset; break; case SeekOrigin.End: Position = Length + offset; break; } retu
BepInEx\patchers\InfernoProtocolInteropFix\InfernoProtocol.InteropFix.dll
Decompiled 5 days 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.Versioning; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Preloader.Core.Patching; using Microsoft.CodeAnalysis; using dnlib.DotNet; using dnlib.DotNet.Writer; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("InfernoProtocol.InteropFix")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+477d00f8c6e6102e4d9ad948d3169f90685e9781")] [assembly: AssemblyProduct("InfernoProtocol.InteropFix")] [assembly: AssemblyTitle("InfernoProtocol.InteropFix")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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 InfernoProtocol.InteropFix { [PatcherPluginInfo("com.holden.infernoprotocol.interopfix", "Inferno Protocol Unity 6 Interop Fix", "1.0.0")] public sealed class Unity6InteropPatcher : BasePatcher { private static readonly string[] AffectedAssemblies = new string[2] { "UnityEngine.CoreModule.dll", "Unity.Collections.dll" }; public override void Initialize() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown string[] affectedAssemblies = AffectedAssemblies; bool flag = default(bool); foreach (string text in affectedAssemblies) { if (!((BasePatcher)this).Context.AvailableAssembliesPaths.TryGetValue(text, out var value)) { ManualLogSource log = ((BasePatcher)this).Log; BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(17, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Skipped missing "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } log.LogDebug(val); continue; } if (((BasePatcher)this).Context.AvailableAssemblies.TryGetValue(text, out var value2)) { value2.Dispose(); } int num = RepairAssembly(value); if (num == 0) { ManualLogSource log2 = ((BasePatcher)this).Log; BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(29, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("No duplicate types found in "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } log2.LogDebug(val); continue; } ManualLogSource log3 = ((BasePatcher)this).Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(40, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Removed "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" duplicate helper type(s) from "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log3.LogInfo(val2); } } private static int RepairAssembly(string assemblyPath) { //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_0017: Expected O, but got Unknown //IL_008f: 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_00a1: Expected O, but got Unknown ModuleDefMD val = ModuleDefMD.Load(File.ReadAllBytes(assemblyPath), new ModuleCreationOptions { TryToLoadPdbFromDisk = false }); try { int num = RemoveDuplicateTopLevelTypes(val); foreach (TypeDef item in ((ModuleDef)val).GetTypes().ToList()) { num += RemoveDuplicateNestedTypes(item); } if (num == 0) { return 0; } string text = assemblyPath + ".infernoprotocol-backup"; if (!File.Exists(text)) { File.Copy(assemblyPath, text); } string text2 = assemblyPath + ".infernoprotocol-tmp"; ModuleWriterOptions val2 = new ModuleWriterOptions((ModuleDef)(object)val) { Logger = (ILogger)(object)DummyLogger.NoThrowInstance }; ((ModuleDef)val).Write(text2, val2); File.Move(text2, assemblyPath, overwrite: true); return num; } finally { ((IDisposable)val)?.Dispose(); } } private static int RemoveDuplicateTopLevelTypes(ModuleDefMD module) { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); List<TypeDef> list = new List<TypeDef>(); foreach (TypeDef type in ((ModuleDef)module).Types) { if (!hashSet.Add(type.FullName)) { list.Add(type); } } foreach (TypeDef item in list) { ((ModuleDef)module).Types.Remove(item); } return list.Count; } private static int RemoveDuplicateNestedTypes(TypeDef type) { if (type.NestedTypes.Count < 2) { return 0; } HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); List<TypeDef> list = new List<TypeDef>(); foreach (TypeDef nestedType in type.NestedTypes) { if (!hashSet.Add(nestedType.Name.String)) { list.Add(nestedType); } } foreach (TypeDef item in list) { type.NestedTypes.Remove(item); } return list.Count; } } }