public NEFile(String fileName) { using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 0x400, FileOptions.None)) { BinaryReader rdr = new BinaryReader(fs); /////////////////////////////// // DOS Header DosHeader = new DosHeader(rdr); // The NE documentation states that if the UInt16 at 0x18 in the DOS header is 0x40, then the UInt16 at 0x3C contains the byte offset (from the beginning of the file) to the segmented header (i.e. 'NE') /////////////////////////////// // NE Offset if (DosHeader.RelocationTableOffset != 0x40) { throw new FormatException("The specified file does not contain an NE segment pointer."); } rdr.BaseStream.Seek(0x3C, SeekOrigin.Begin); NEOffset = rdr.ReadUInt16(); rdr.BaseStream.Seek(NEOffset, SeekOrigin.Begin); /////////////////////////////// // NE Header NEHeader = new NEHeader(rdr); /////////////////////////////// // NE Segment Table long bytesWasted1 = (NEOffset + NEHeader.SegmentTableOffset) - rdr.BaseStream.Position; rdr.BaseStream.Seek(NEOffset + NEHeader.SegmentTableOffset, SeekOrigin.Begin); SegmentTable = new NESegmentTableEntry[NEHeader.SegmentTableCount]; for (int i = 0; i < NEHeader.SegmentTableCount; i++) { SegmentTable[i].Offset = rdr.ReadUInt16(); SegmentTable[i].Size = rdr.ReadUInt16(); SegmentTable[i].Type = (NESegmentType)rdr.ReadUInt16(); SegmentTable[i].MinimumAllocation = rdr.ReadUInt16(); } /////////////////////////////// // Resource Table long bytesWasted2 = (NEOffset + NEHeader.ResourceTableOffset) - rdr.BaseStream.Position; rdr.BaseStream.Seek(NEOffset + NEHeader.ResourceTableOffset, SeekOrigin.Begin); ResourceTable = new NEResourceTable(rdr); /////////////////////////////// // Resident Name Table /////////////////////////////// // Module-Reference Table /////////////////////////////// // Imported-Name Table /////////////////////////////// // Entry Table /////////////////////////////// // Non-Resident Name Table /////////////////////////////// // Per-Segment Data } }
private void Load(Stream stream) { var rdr = new BinaryReader(stream); //////////////////////////////////// // The DOS Stub and PE Offset marker DosHeader = new DosHeader(rdr); PEOffset = DosHeader.NewExeHeaderAddress; // this is at 0x3C rdr.BaseStream.Seek(PEOffset, SeekOrigin.Begin); //////////////////////////////////// // The COFF File Header PESignature = rdr.ReadBytes(4); if (!IsPESignature(PESignature)) { throw new FormatException("The specified file does not contain a PE signature."); } CoffFileHeader = new CoffFileHeader(rdr); var offsetEndOfCoffFileHeader = rdr.BaseStream.Position; //////////////////////////////////// // The Optional Header var magic = (PE32Magic)rdr.ReadUInt16(); switch (magic) { case PE32Magic.PE32: // Ensure the Optional Header is big enough for the minimum amount of data // Standard fields: 28 bytes // Windows fields: 68 bytes // Total: 92 bytes if (CoffFileHeader.SizeOfOptionalHeader < 96) { var msg = string.Format( "The specified file's declared Optional Header size of {0} bytes is smaller than the minimum of 96 required bytes.", CoffFileHeader.SizeOfOptionalHeader ); throw new FormatException(msg); } OptionalHeader32 = new CoffOptionalHeader32(magic, rdr); break; case PE32Magic.PE32Plus: // Standard fields: 24 bytes // Windows fields: 88 bytes // Total: 112 bytes if (CoffFileHeader.SizeOfOptionalHeader < 112) { var msg = string.Format( "The specified file's declared Optional Header size of {0} bytes is smaller than the minimum of 112 required bytes.", CoffFileHeader.SizeOfOptionalHeader ); throw new FormatException(msg); } OptionalHeader32Plus = new CoffOptionalHeader32Plus(magic, rdr); break; case PE32Magic.RomImage: default: OptionalHeader = rdr.ReadBytes(CoffFileHeader.SizeOfOptionalHeader); break; } var offsetEndOfOptionalHeader = rdr.BaseStream.Position; // by now we're at the end of the Optional Header, but let's make sure if (offsetEndOfOptionalHeader != offsetEndOfCoffFileHeader + CoffFileHeader.SizeOfOptionalHeader) { // error condition } /////////////////////////////// // The Section Table SectionTable = new SectionTableEntry[CoffFileHeader.NofSections]; for (var i = 0; i < SectionTable.Length; i++) { SectionTable[i] = new SectionTableEntry(rdr); } }