context: using Editor_Mono.Cecil.Cil;
  using Editor_Mono.Cecil.Metadata;
  using System;
  using System.IO;
  namespace Editor_Mono.Cecil.PE
  {
  	internal sealed class ImageWriter : BinaryStreamWriter
  	{
  		private const uint pe_header_size = 152u;
  		private const uint section_header_size = 40u;
  		private const uint file_alignment = 512u;
  		private const uint section_alignment = 8192u;
  		private const ulong image_base = 4194304uL;
  		internal const uint text_rva = 8192u;
  		private readonly ModuleDefinition module;
  		private readonly MetadataBuilder metadata;
  		private readonly TextMap text_map;
  		private ImageDebugDirectory debug_directory;
  		private byte[] debug_data;
  		private ByteBuffer win32_resources;
  		private readonly bool pe64;
  		private readonly bool has_reloc;
  		private readonly uint time_stamp;
  		internal Section text;
  		internal Section rsrc;
  		internal Section reloc;
  		private ushort sections;
  		private ImageWriter(ModuleDefinition module, MetadataBuilder metadata, Stream stream) : base(stream)
  		{
  			this.module = module;
  			this.metadata = metadata;
  			this.pe64 = (module.Architecture == TargetArchitecture.AMD64 || module.Architecture == TargetArchitecture.IA64);
  			this.has_reloc = (module.Architecture == TargetArchitecture.I386);
  			this.GetDebugHeader();
  			this.GetWin32Resources();
  			this.text_map = this.BuildTextMap();
              this.sections = (ushort)(has_reloc ? 2 : 1); // text + reloc?
              this.time_stamp = (uint)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
  		}
  		private void GetDebugHeader()
  		{
  			ISymbolWriter symbol_writer = this.metadata.symbol_writer;
  			if (symbol_writer == null)
  			{
  				return;
  			}
  			if (!symbol_writer.GetDebugHeader(out this.debug_directory, out this.debug_data))
  			{
  				this.debug_data = Empty<byte>.Array;
  			}
  		}
  		private void GetWin32Resources()
  		{
  			Section imageResourceSection = this.GetImageResourceSection();
  			if (imageResourceSection == null)
  			{
  				return;
  			}
  			byte[] array = new byte[imageResourceSection.Data.Length];
  			Buffer.BlockCopy(imageResourceSection.Data, 0, array, 0, imageResourceSection.Data.Length);
  			this.win32_resources = new ByteBuffer(array);
  		}
  		private Section GetImageResourceSection()
  		{
  			if (!this.module.HasImage)
  			{
  				return null;
  			}
  			return this.module.Image.GetSection(".rsrc");
  		}
  		public static ImageWriter CreateWriter(ModuleDefinition module, MetadataBuilder metadata, Stream stream)
  		{
  			ImageWriter imageWriter = new ImageWriter(module, metadata, stream);
  			imageWriter.BuildSections();
  			return imageWriter;
  		}
  		private void BuildSections()
  		{
  			bool flag = this.win32_resources != null;
  			if (flag)
  			{
  				this.sections += 1;
  			}
  			this.text = this.CreateSection(".text", this.text_map.GetLength(), null);
  			Section previous = this.text;
  			if (flag)
  			{
  				this.rsrc = this.CreateSection(".rsrc", (uint)this.win32_resources.length, previous);
  				this.PatchWin32Resources(this.win32_resources);
  				previous = this.rsrc;
  			}
  			if (this.has_reloc)
  			{
  				this.reloc = this.CreateSection(".reloc", 12u, previous);
  			}
  		}
  		private Section CreateSection(string name, uint size, Section previous)
  		{
  			return new Section
  			{
  				Name = name,
  				VirtualAddress = (previous != null) ? (previous.VirtualAddress + ImageWriter.Align(previous.VirtualSize, 8192u)) : 8192u,
  				VirtualSize = size,
  				PointerToRawData = (previous != null) ? (previous.PointerToRawData + previous.SizeOfRawData) : ImageWriter.Align(this.GetHeaderSize(), 512u),
  				SizeOfRawData = ImageWriter.Align(size, 512u)
  			};
  		}
  		private static uint Align(uint value, uint align)
  		{
  			align -= 1u;
  			return value + align & ~align;
  		}
  		private void WriteDOSHeader()
  		{
  			this.Write(new byte[]
  			{
  				77,
  				90,
  				144,
  				0,
  				3,
  				0,
  				0,
  				0,
  				4,
  				0,
  				0,
  				0,
  				255,
  				255,
  				0,
  				0,
  				184,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				64,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				128,
  				0,
  				0,
  				0,
  				14,
  				31,
  				186,
  				14,
  				0,
  				180,
  				9,
  				205,
  				33,
  				184,
  				1,
  				76,
  				205,
  				33,
  				84,
  				104,
  				105,
  				115,
  				32,
  				112,
  				114,
  				111,
  				103,
  				114,
  				97,
  				109,
  				32,
  				99,
  				97,
  				110,
  				110,
  				111,
  				116,
  				32,
  				98,
  				101,
  				32,
  				114,
  				117,
  				110,
  				32,
  				105,
  				110,
  				32,
  				68,
  				79,
  				83,
  				32,
  				109,
  				111,
  				100,
  				101,
  				46,
  				13,
  				13,
  				10,
  				36,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0,
  				0
  			});
  		}
  		private ushort SizeOfOptionalHeader()
  		{
              return (ushort)(!pe64 ? 0xe0 : 0xf0);
          }
  		private void WritePEFileHeader()
  		{
  			base.WriteUInt32(17744u);
  			base.WriteUInt16(this.GetMachine());
  			base.WriteUInt16(this.sections);
  			base.WriteUInt32(this.time_stamp);
  			base.WriteUInt32(0u);
  			base.WriteUInt32(0u);
  			base.WriteUInt16(this.SizeOfOptionalHeader());
  			ushort num = (ushort)(2 | ((!this.pe64) ? 256 : 32));
  			if (this.module.Kind == ModuleKind.Dll || this.module.Kind == ModuleKind.NetModule)
  			{
  				num |= 8192;
  			}
  			base.WriteUInt16(num);
  		}
  		private ushort GetMachine()
  		{
  			switch (this.module.Architecture)
  			{
  			case TargetArchitecture.I386:
  				return 332;
  			case TargetArchitecture.AMD64:
  				return 34404;
  			case TargetArchitecture.IA64:
  				return 512;
  			case TargetArchitecture.ARMv7:
  				return 452;
  			default:
  				throw new NotSupportedException();
  			}
  		}
  		private Section LastSection()
  		{
  			if (this.reloc != null)
  			{
  				return this.reloc;
  			}
  			if (this.rsrc != null)
  			{
  				return this.rsrc;
  			}
  			return this.text;
  		}
  		private void WriteOptionalHeaders()
  		{
              WriteUInt16((ushort)(!pe64 ? 0x10b : 0x20b)); // Magic
              base.WriteByte(8);
  			base.WriteByte(0);
  			base.WriteUInt32(this.text.SizeOfRawData);
  			base.WriteUInt32(((this.reloc != null) ? this.reloc.SizeOfRawData : 0u) + ((this.rsrc != null) ? this.rsrc.SizeOfRawData : 0u));
  			base.WriteUInt32(0u);
  			Range range = this.text_map.GetRange(TextSegment.StartupStub);
  			base.WriteUInt32((range.Length > 0u) ? range.Start : 0u);
  			base.WriteUInt32(8192u);
  			if (!this.pe64)
  			{
  				base.WriteUInt32(0u);
  				base.WriteUInt32(4194304u);
  			}
  			else
  			{
  				base.WriteUInt64(4194304uL);
  			}
  			base.WriteUInt32(8192u);
  			base.WriteUInt32(512u);
  			base.WriteUInt16(4);
  			base.WriteUInt16(0);
  			base.WriteUInt16(0);
  			base.WriteUInt16(0);
  			base.WriteUInt16(4);
  			base.WriteUInt16(0);
  			base.WriteUInt32(0u);
  			Section section = this.LastSection();
  			base.WriteUInt32(section.VirtualAddress + ImageWriter.Align(section.VirtualSize, 8192u));
  			base.WriteUInt32(this.text.PointerToRawData);
  			base.WriteUInt32(0u);
  			base.WriteUInt16(this.GetSubSystem());
  			base.WriteUInt16((ushort)this.module.Characteristics);
  			if (!this.pe64)
  			{
  				base.WriteUInt32(1048576u);
  				base.WriteUInt32(4096u);
  				base.WriteUInt32(1048576u);
  				base.WriteUInt32(4096u);
  			}
  			else
  			{
  				base.WriteUInt64(1048576uL);
  				base.WriteUInt64(4096uL);
  				base.WriteUInt64(1048576uL);
  				base.WriteUInt64(4096uL);
  			}
  			base.WriteUInt32(0u);
  			base.WriteUInt32(16u);
  			this.WriteZeroDataDirectory();
  			base.WriteDataDirectory(this.text_map.GetDataDirectory(TextSegment.ImportDirectory));
  			if (this.rsrc != null)
  			{
  				base.WriteUInt32(this.rsrc.VirtualAddress);
  				base.WriteUInt32(this.rsrc.VirtualSize);
  			}
  			else
  			{
  				this.WriteZeroDataDirectory();
  			}
  			this.WriteZeroDataDirectory();
  			this.WriteZeroDataDirectory();
  			base.WriteUInt32((this.reloc != null) ? this.reloc.VirtualAddress : 0u);
  			base.WriteUInt32((this.reloc != null) ? this.reloc.VirtualSize : 0u);
  			if (this.text_map.GetLength(TextSegment.DebugDirectory) > 0)
  			{
  				base.WriteUInt32(this.text_map.GetRVA(TextSegment.DebugDirectory));
  				base.WriteUInt32(28u);
  			}
  			else
  			{
  				this.WriteZeroDataDirectory();
  			}
  			this.WriteZeroDataDirectory();
  			this.WriteZeroDataDirectory();
  			this.WriteZeroDataDirectory();
  			this.WriteZeroDataDirectory();
  			this.WriteZeroDataDirectory();
  			base.WriteDataDirectory(this.text_map.GetDataDirectory(TextSegment.ImportAddressTable));
  			this.WriteZeroDataDirectory();
  			base.WriteDataDirectory(this.text_map.GetDataDirectory(TextSegment.CLIHeader));
  			this.WriteZeroDataDirectory();
  		}
  		private void WriteZeroDataDirectory()
  		{
  			base.WriteUInt32(0u);
  			base.WriteUInt32(0u);
  		}
  		private ushort GetSubSystem()
  		{
  			switch (this.module.Kind)
  			{
  			case ModuleKind.Dll:
  			case ModuleKind.Console:
  			case ModuleKind.NetModule:
  				return 3;
  			case ModuleKind.Windows:
  				return 2;
  			default:
  				throw new ArgumentOutOfRangeException();
  			}
  		}
  		private void WriteSectionHeaders()
  		{
  			this.WriteSection(this.text, 1610612768u);
  
gt: 			if (this.rsrc != null)