Decompiled source of InfernoProtocolInteropFix v1.0.0

BepInEx\patchers\InfernoProtocolInteropFix\dnlib.dll

Decompiled 5 days ago
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 ago
using 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;
		}
	}
}