diff --git a/BurnOutSharp/ExecutableType/Microsoft/Entries/NEResourceNameString.cs b/BurnOutSharp/ExecutableType/Microsoft/Entries/NEResourceNameString.cs new file mode 100644 index 00000000..f0d3a047 --- /dev/null +++ b/BurnOutSharp/ExecutableType/Microsoft/Entries/NEResourceNameString.cs @@ -0,0 +1,46 @@ +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using BurnOutSharp.Tools; + +namespace BurnOutSharp.ExecutableType.Microsoft.Entries +{ + /// + /// Resource type and name strings + /// + [StructLayout(LayoutKind.Sequential)] + internal class NEResourceNameString + { + /// + /// Length of the type or name string that follows. A zero value + /// indicates the end of the resource type and name string, also + /// the end of the resource table. + /// + public byte Length; + + /// + /// ASCII text of the type or name string. + /// + public char[] Value; + + public static NEResourceNameString Deserialize(Stream stream) + { + var rds = new NEResourceNameString(); + + rds.Length = stream.ReadByteValue(); + rds.Value = stream.ReadChars(rds.Length, Encoding.ASCII); + + return rds; + } + + public static NEResourceNameString Deserialize(byte[] contents, int offset) + { + var rds = new NEResourceNameString(); + + rds.Length = contents[offset++]; + rds.Value = Encoding.ASCII.GetChars(contents, offset, rds.Length); + + return rds; + } + } +} diff --git a/BurnOutSharp/ExecutableType/Microsoft/Entries/NEResourceTableEntry.cs b/BurnOutSharp/ExecutableType/Microsoft/Entries/NEResourceTableEntry.cs new file mode 100644 index 00000000..aa903042 --- /dev/null +++ b/BurnOutSharp/ExecutableType/Microsoft/Entries/NEResourceTableEntry.cs @@ -0,0 +1,78 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using BurnOutSharp.Tools; + +namespace BurnOutSharp.ExecutableType.Microsoft.Entries +{ + /// + /// A table of resources for this type + /// + [StructLayout(LayoutKind.Sequential)] + internal class NEResourceTableEntry + { + /// + /// File offset to the contents of the resource data, + /// relative to beginning of file. The offset is in terms + /// of the alignment shift count value specified at + /// beginning of the resource table. + /// + public ushort Offset; + + /// + /// Length of the resource in the file (in bytes). + /// + public ushort Length; + + /// + /// Resource flags + /// + public ResourceTableEntryFlags Flags; + + /// + /// This is an integer type if the high-order + /// bit is set (8000h), otherwise it is the offset to the + /// resource string, the offset is relative to the + /// beginning of the resource table. + /// + public ushort ResourceID; + + /// + /// Reserved. + /// + public ushort Handle; + + /// + /// Reserved. + /// + public ushort Usage; + + public static NEResourceTableEntry Deserialize(Stream stream) + { + var ni = new NEResourceTableEntry(); + + ni.Offset = stream.ReadUInt16(); + ni.Length = stream.ReadUInt16(); + ni.Flags = (ResourceTableEntryFlags)stream.ReadUInt16(); + ni.ResourceID = stream.ReadUInt16(); + ni.Handle = stream.ReadUInt16(); + ni.Usage = stream.ReadUInt16(); + + return ni; + } + + public static NEResourceTableEntry Deserialize(byte[] contents, int offset) + { + var ni = new NEResourceTableEntry(); + + ni.Offset = BitConverter.ToUInt16(contents, offset); offset += 2; + ni.Length = BitConverter.ToUInt16(contents, offset); offset += 2; + ni.Flags = (ResourceTableEntryFlags)BitConverter.ToUInt16(contents, offset); offset += 2; + ni.ResourceID = BitConverter.ToUInt16(contents, offset); offset += 2; + ni.Handle = BitConverter.ToUInt16(contents, offset); offset += 2; + ni.Usage = BitConverter.ToUInt16(contents, offset); offset += 2; + + return ni; + } + } +} \ No newline at end of file diff --git a/BurnOutSharp/ExecutableType/Microsoft/Entries/NESegmentTableEntry.cs b/BurnOutSharp/ExecutableType/Microsoft/Entries/NESegmentTableEntry.cs new file mode 100644 index 00000000..60659630 --- /dev/null +++ b/BurnOutSharp/ExecutableType/Microsoft/Entries/NESegmentTableEntry.cs @@ -0,0 +1,64 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using BurnOutSharp.Tools; + +namespace BurnOutSharp.ExecutableType.Microsoft.Entries +{ + /// + /// The segment table contains an entry for each segment in the executable + /// file. The number of segment table entries are defined in the segmented + /// EXE header. The first entry in the segment table is segment number 1. + /// The following is the structure of a segment table entry. + /// + [StructLayout(LayoutKind.Sequential)] + internal class NESegmentTableEntry + { + /// + /// Logical-sector offset (n byte) to the contents of the segment + /// data, relative to the beginning of the file. Zero means no + /// file data. + /// + public ushort StartFileSector; + + /// + /// Length of the segment in the file, in bytes. Zero means 64K. + /// + public ushort BytesInFile; + + /// + /// Attribute flags + /// + public SegmentTableEntryFlags Flags; + + /// + /// Minimum allocation size of the segment, in bytes. + /// Total size of the segment. Zero means 64K + /// + public ushort MinimumAllocation; + + public static NESegmentTableEntry Deserialize(Stream stream) + { + var nste = new NESegmentTableEntry(); + + nste.StartFileSector = stream.ReadUInt16(); + nste.BytesInFile = stream.ReadUInt16(); + nste.Flags = (SegmentTableEntryFlags)stream.ReadUInt16(); + nste.MinimumAllocation = stream.ReadUInt16(); + + return nste; + } + + public static NESegmentTableEntry Deserialize(byte[] content, int offset) + { + var nste = new NESegmentTableEntry(); + + nste.StartFileSector = BitConverter.ToUInt16(content, offset); offset += 2; + nste.BytesInFile = BitConverter.ToUInt16(content, offset); offset += 2; + nste.Flags = (SegmentTableEntryFlags)BitConverter.ToUInt16(content, offset); offset += 2; + nste.MinimumAllocation = BitConverter.ToUInt16(content, offset); offset += 2; + + return nste; + } + } +} diff --git a/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceTypeInformationBlock.cs b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceTypeInformationBlock.cs new file mode 100644 index 00000000..3a078632 --- /dev/null +++ b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResourceTypeInformationBlock.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using BurnOutSharp.Tools; + +namespace BurnOutSharp.ExecutableType.Microsoft.Entries +{ + /// + /// Resource type information block + /// + [StructLayout(LayoutKind.Sequential)] + internal class ResourceTypeInformationBlock + { + /// + /// Type ID. This is an integer type if the high-order bit is + /// set (8000h); otherwise, it is an offset to the type string, + /// the offset is relative to the beginning of the resource + /// table. A zero type ID marks the end of the resource type + /// information blocks. + /// + public ushort TypeID; + + /// + /// Number of resources for this type. + /// + public ushort ResourceCount; + + /// + /// Reserved. + /// + public uint Reserved; + + /// + /// Reserved. + /// + public NEResourceTableEntry[] ResourceTable; + + public static ResourceTypeInformationBlock Deserialize(Stream stream) + { + var rtib = new ResourceTypeInformationBlock(); + + rtib.TypeID = stream.ReadUInt16(); + rtib.ResourceCount = stream.ReadUInt16(); + rtib.Reserved = stream.ReadUInt32(); + + rtib.ResourceTable = new NEResourceTableEntry[rtib.ResourceCount]; + for (int i = 0; i < rtib.ResourceCount; i++) + { + rtib.ResourceTable[i] = NEResourceTableEntry.Deserialize(stream); + } + + return rtib; + } + + public static ResourceTypeInformationBlock Deserialize(byte[] contents, int offset) + { + var rtib = new ResourceTypeInformationBlock(); + + rtib.TypeID = BitConverter.ToUInt16(contents, offset); offset += 2; + rtib.ResourceCount = BitConverter.ToUInt16(contents, offset); offset += 2; + rtib.Reserved = BitConverter.ToUInt32(contents, offset); offset += 4; + + rtib.ResourceTable = new NEResourceTableEntry[rtib.ResourceCount]; + for (int i = 0; i < rtib.ResourceCount; i++) + { + rtib.ResourceTable[i] = NEResourceTableEntry.Deserialize(contents, offset); offset += 12; + } + + return rtib; + } + } +} \ No newline at end of file diff --git a/BurnOutSharp/ExecutableType/Microsoft/Enums.cs b/BurnOutSharp/ExecutableType/Microsoft/Enums.cs index b1697d0e..d7a4476b 100644 --- a/BurnOutSharp/ExecutableType/Microsoft/Enums.cs +++ b/BurnOutSharp/ExecutableType/Microsoft/Enums.cs @@ -588,107 +588,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft NRSOFF32 = 0x0D, } - /// - /// Format of NS_FLAGS(x) - /// - /// x Unused - /// h Huge segment - /// c 32-bit code segment - /// d Discardable segment - /// DD I/O privilege level (286 DPL bits) - /// c Conforming segment - /// r Segment has relocations - /// e Execute/read only - /// p Preload segment - /// P Pure segment - /// m Movable segment - /// i Iterated segment - /// ttt Segment type - /// - [Flags] - internal enum NsFlags : ushort - { - /// - /// Segment type mask - /// - NSTYPE = 0x0007, - - /// - /// Code segment - /// - NSCODE = 0x0000, - - /// - /// Data segment - /// - NSDATA = 0x0001, - - /// - /// Iterated segment flag - /// - NSITER = 0x0008, - - /// - /// Movable segment flag - /// - NSMOVE = 0x0010, - - /// - /// Shared segment flag - /// - NSSHARED = 0x0020, - - /// - /// For compatibility - /// - NSPURE = 0x0020, - - /// - /// Preload segment flag - /// - NSPRELOAD = 0x0040, - - /// - /// Execute-only (code segment), or read-only (data segment) - /// - NSEXRD = 0x0080, - - /// - /// Segment has relocations - /// - NSRELOC = 0x0100, - - /// - /// Conforming segment - /// - NSCONFORM = 0x0200, - - /// - /// I/O privilege level (286 DPL bits) - /// - NSDPL = 0x0C00, - - /// - /// Left shift count for SEGDPL field - /// - SHIFTDPL = 10, - - /// - /// Segment is discardable - /// - NSDISCARD = 0x1000, - - /// - /// 32-bit code segment - /// - NS32BIT = 0x2000, - - /// - /// Huge memory segment, length of segment and minimum allocation size are in segment sector units - /// - NSHUGE = 0x4000, - } - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-image-only internal enum OptionalHeaderType : ushort { @@ -708,6 +607,26 @@ namespace BurnOutSharp.ExecutableType.Microsoft PE32Plus = 0x20b, } + /// http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm + [Flags] + internal enum ResourceTableEntryFlags : ushort + { + /// + /// Resource is not fixed. + /// + MOVEABLE = 0x0010, + + /// + /// Resource can be shared. + /// + PURE = 0x0020, + + /// + /// Resource is preloaded. + /// + PRELOAD = 0x0040, + } + /// /// Predefined Resource Types /// @@ -956,6 +875,91 @@ namespace BurnOutSharp.ExecutableType.Microsoft /// IMAGE_SCN_MEM_WRITE = 0x80000000, } + + /// http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm + [Flags] + internal enum SegmentTableEntryFlags : ushort + { + /// + /// Segment-type field. + /// + TYPE = 0x0007, + + /// + /// Code-segment type. + /// + CODE = 0x0000, + + /// + /// Data-segment type. + /// + DATA = 0x0001, + + /// + /// Iterated segment flag + /// + ITER = 0x0008, + + /// + /// Segment is not fixed. + /// + MOVEABLE = 0x0010, + + /// + /// Shared segment flag + /// + SHARED = 0x0020, + + /// + /// For compatibility + /// + PURE = 0x0020, + + /// + /// Segment will be preloaded; read-only if this is a data segment. + /// + PRELOAD = 0x0040, + + /// + /// Execute-only (code segment), or read-only (data segment) + /// + EXRD = 0x0080, + + /// + /// Set if segment has relocation records. + /// + RELOCINFO = 0x0100, + + /// + /// Conforming segment + /// + CONFORM = 0x0200, + + /// + /// I/O privilege level (286 DPL bits) + /// + DPL = 0x0C00, + + /// + /// Left shift count for SEGDPL field + /// + SHIFTDPL = 10, + + /// + /// Discard priority. + /// + DISCARD = 0x1000, + + /// + /// 32-bit code segment + /// + NS32BIT = 0x2000, + + /// + /// Huge memory segment, length of segment and minimum allocation size are in segment sector units + /// + HUGE = 0x4000, + } [Flags] internal enum TargetOperatingSystems : byte diff --git a/BurnOutSharp/ExecutableType/Microsoft/Headers/NewExecutableHeader.cs b/BurnOutSharp/ExecutableType/Microsoft/Headers/NewExecutableHeader.cs index 4964a9e9..a619a479 100644 --- a/BurnOutSharp/ExecutableType/Microsoft/Headers/NewExecutableHeader.cs +++ b/BurnOutSharp/ExecutableType/Microsoft/Headers/NewExecutableHeader.cs @@ -9,36 +9,40 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers /// The NE header is a relatively large structure with multiple characteristics. /// Because of the age of the format some items are unclear in meaning. /// + /// http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm [StructLayout(LayoutKind.Sequential)] internal class NewExecutableHeader { /// - /// "NE" [00] + /// Signature word. [00] + /// "N" is low-order byte. + /// "E" is high-order byte. /// public ushort Magic; /// - /// The major linker version [02] + /// Version number of the linker. [02] /// public byte LinkerVersion; /// - /// The minor linker version [03] + /// Revision number of the linker. [03] /// public byte LinkerRevision; /// - /// Offset of Entry Table [04] + /// Entry Table file offset, relative to the beginning of the segmented EXE header. [04] /// public ushort EntryTableOffset; /// - /// Length of entry table in bytes [06] + /// Number of bytes in the entry table. [06] /// public ushort EntryTableSize; /// - /// 32-bit CRC of entire contents of file [08] + /// 32-bit CRC of entire contents of file. [08] + /// These words are taken as 00 during the calculation. /// public uint CrcChecksum; diff --git a/BurnOutSharp/ExecutableType/Microsoft/NAMEINFO.cs b/BurnOutSharp/ExecutableType/Microsoft/NAMEINFO.cs deleted file mode 100644 index 9e974141..00000000 --- a/BurnOutSharp/ExecutableType/Microsoft/NAMEINFO.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * NEWEXE.H (C) Copyright Microsoft Corp 1984-1987 - * - * Data structure definitions for the OS/2 & Windows - * executable file format. - * - * Modified by IVS on 24-Jan-1991 for Resource DeCompiler - * (C) Copyright IVS 1991 - * - * http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h - */ - -using System.IO; -using System.Runtime.InteropServices; -using BurnOutSharp.Tools; - -namespace BurnOutSharp.ExecutableType.Microsoft -{ - [StructLayout(LayoutKind.Sequential)] - internal class NAMEINFO - { - public ushort Offset; - public ushort Length; - public ushort Flags; - public ushort ID; - public ushort Handle; - public ushort Usage; - - public static NAMEINFO Deserialize(Stream stream) - { - var ni = new NAMEINFO(); - - ni.Offset = stream.ReadUInt16(); - ni.Length = stream.ReadUInt16(); - ni.Flags = stream.ReadUInt16(); - ni.ID = stream.ReadUInt16(); - ni.Handle = stream.ReadUInt16(); - ni.Usage = stream.ReadUInt16(); - - return ni; - } - } -} \ No newline at end of file diff --git a/BurnOutSharp/ExecutableType/Microsoft/NewExecutable.cs b/BurnOutSharp/ExecutableType/Microsoft/NewExecutable.cs index c5e04499..95d78865 100644 --- a/BurnOutSharp/ExecutableType/Microsoft/NewExecutable.cs +++ b/BurnOutSharp/ExecutableType/Microsoft/NewExecutable.cs @@ -30,6 +30,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft #endregion // TODO: Add more and more parts of a standard NE executable, not just the header + // TODO: Tables? What about the tables? + // TODO: Implement the rest of the structures found at http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm + // (Left off at RESIDENT-NAME TABLE) public static NewExecutable Deserialize(Stream stream) { diff --git a/BurnOutSharp/ExecutableType/Microsoft/NewRsrc.cs b/BurnOutSharp/ExecutableType/Microsoft/NewRsrc.cs deleted file mode 100644 index 2ead5ff8..00000000 --- a/BurnOutSharp/ExecutableType/Microsoft/NewRsrc.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * NEWEXE.H (C) Copyright Microsoft Corp 1984-1987 - * - * Data structure definitions for the OS/2 & Windows - * executable file format. - * - * Modified by IVS on 24-Jan-1991 for Resource DeCompiler - * (C) Copyright IVS 1991 - * - * http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h - */ - -using System.IO; -using System.Runtime.InteropServices; -using BurnOutSharp.Tools; - -namespace BurnOutSharp.ExecutableType.Microsoft -{ - /// - /// Resource table - /// - [StructLayout(LayoutKind.Sequential)] - internal class NewRsrc - { - /// - /// Alignment shift count for resources - /// - public ushort AlignmentShiftCount; - public RsrcTypeInfo TypeInfo; - - public static NewRsrc Deserialize(Stream stream) - { - var nr = new NewRsrc(); - - nr.AlignmentShiftCount = stream.ReadUInt16(); - nr.TypeInfo = RsrcTypeInfo.Deserialize(stream); - - return nr; - } - } -} \ No newline at end of file diff --git a/BurnOutSharp/ExecutableType/Microsoft/NewSeg.cs b/BurnOutSharp/ExecutableType/Microsoft/NewSeg.cs deleted file mode 100644 index 98b1c9f5..00000000 --- a/BurnOutSharp/ExecutableType/Microsoft/NewSeg.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * NEWEXE.H (C) Copyright Microsoft Corp 1984-1987 - * - * Data structure definitions for the OS/2 & Windows - * executable file format. - * - * Modified by IVS on 24-Jan-1991 for Resource DeCompiler - * (C) Copyright IVS 1991 - * - * http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h - */ - -using System.IO; -using System.Runtime.InteropServices; -using BurnOutSharp.Tools; - -namespace BurnOutSharp.ExecutableType.Microsoft -{ - /// - /// New .EXE segment table entry - /// - [StructLayout(LayoutKind.Sequential)] - internal class NewSeg - { - /// - /// File sector of start of segment - /// - public ushort StartFileSector; - - /// - /// Number of bytes in file - /// - public ushort BytesInFile; - - /// - /// Attribute flags - /// - public ushort Flags; - - /// - /// Minimum allocation in bytes - /// - public ushort MinimumAllocation; - - public static NewSeg Deserialize(Stream stream) - { - var ns = new NewSeg(); - - ns.StartFileSector = stream.ReadUInt16(); - ns.BytesInFile = stream.ReadUInt16(); - ns.Flags = stream.ReadUInt16(); - ns.MinimumAllocation = stream.ReadUInt16(); - - return ns; - } - } -} diff --git a/BurnOutSharp/ExecutableType/Microsoft/ResourceTable.cs b/BurnOutSharp/ExecutableType/Microsoft/ResourceTable.cs deleted file mode 100644 index f3243bf8..00000000 --- a/BurnOutSharp/ExecutableType/Microsoft/ResourceTable.cs +++ /dev/null @@ -1,42 +0,0 @@ -/* - * NEWEXE.H (C) Copyright Microsoft Corp 1984-1987 - * - * Data structure definitions for the OS/2 & Windows - * executable file format. - * - * Modified by IVS on 24-Jan-1991 for Resource DeCompiler - * (C) Copyright IVS 1991 - * - * http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h - */ - -using System.IO; -using System.Runtime.InteropServices; -using BurnOutSharp.Tools; - -namespace BurnOutSharp.ExecutableType.Microsoft -{ - [StructLayout(LayoutKind.Sequential)] - internal class ResourceTable - { - public ushort rscAlignShift; - public TYPEINFO TypeInfo; - public ushort rscEndTypes; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] - public sbyte[][] rscResourceNames; - public byte rscEndNames; - - public static ResourceTable Deserialize(Stream stream) - { - var rt = new ResourceTable(); - - rt.rscAlignShift = stream.ReadUInt16(); - rt.TypeInfo = TYPEINFO.Deserialize(stream); - rt.rscEndTypes = stream.ReadUInt16(); - rt.rscResourceNames = null; // TODO: Figure out size - rt.rscEndNames = stream.ReadByteValue(); - - return rt; - } - } -} \ No newline at end of file diff --git a/BurnOutSharp/ExecutableType/Microsoft/RsrcTypeInfo.cs b/BurnOutSharp/ExecutableType/Microsoft/RsrcTypeInfo.cs deleted file mode 100644 index 7acee96c..00000000 --- a/BurnOutSharp/ExecutableType/Microsoft/RsrcTypeInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* - * NEWEXE.H (C) Copyright Microsoft Corp 1984-1987 - * - * Data structure definitions for the OS/2 & Windows - * executable file format. - * - * Modified by IVS on 24-Jan-1991 for Resource DeCompiler - * (C) Copyright IVS 1991 - * - * http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h - */ - -using System.IO; -using System.Runtime.InteropServices; -using BurnOutSharp.Tools; - -namespace BurnOutSharp.ExecutableType.Microsoft -{ - /// - /// Resource type information block - /// - [StructLayout(LayoutKind.Sequential)] - internal class RsrcTypeInfo - { - public ushort ID; - public ushort rt_nres; - public uint rt_proc; - - public static RsrcTypeInfo Deserialize(Stream stream) - { - var rti = new RsrcTypeInfo(); - - rti.ID = stream.ReadUInt16(); - rti.rt_nres = stream.ReadUInt16(); - rti.rt_proc = stream.ReadUInt32(); - - return rti; - } - } -} \ No newline at end of file diff --git a/BurnOutSharp/ExecutableType/Microsoft/TYPEINFO.cs b/BurnOutSharp/ExecutableType/Microsoft/TYPEINFO.cs deleted file mode 100644 index a28dee4d..00000000 --- a/BurnOutSharp/ExecutableType/Microsoft/TYPEINFO.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* - * NEWEXE.H (C) Copyright Microsoft Corp 1984-1987 - * - * Data structure definitions for the OS/2 & Windows - * executable file format. - * - * Modified by IVS on 24-Jan-1991 for Resource DeCompiler - * (C) Copyright IVS 1991 - * - * http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h - */ - -using System.IO; -using System.Runtime.InteropServices; -using BurnOutSharp.Tools; - -namespace BurnOutSharp.ExecutableType.Microsoft -{ - [StructLayout(LayoutKind.Sequential)] - internal class TYPEINFO - { - public ushort TypeID; - public ushort ResourceCount; - public uint Reserved; - public NAMEINFO NameInfo; - - public static TYPEINFO Deserialize(Stream stream) - { - var ti = new TYPEINFO(); - - ti.TypeID = stream.ReadUInt16(); - ti.ResourceCount = stream.ReadUInt16(); - ti.Reserved = stream.ReadUInt32(); - ti.NameInfo = NAMEINFO.Deserialize(stream); - - return ti; - } - } -} \ No newline at end of file diff --git a/BurnOutSharp/ExecutableType/Microsoft/Tables/NEResourceTable.cs b/BurnOutSharp/ExecutableType/Microsoft/Tables/NEResourceTable.cs new file mode 100644 index 00000000..d515794b --- /dev/null +++ b/BurnOutSharp/ExecutableType/Microsoft/Tables/NEResourceTable.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using BurnOutSharp.ExecutableType.Microsoft.Entries; +using BurnOutSharp.Tools; + +namespace BurnOutSharp.ExecutableType.Microsoft.Tables +{ + /// + /// The resource table follows the segment table and contains entries for + /// each resource in the executable file. The resource table consists of + /// an alignment shift count, followed by a table of resource records. The + /// resource records define the type ID for a set of resources. Each + /// resource record contains a table of resource entries of the defined + /// type. The resource entry defines the resource ID or name ID for the + /// resource. It also defines the location and size of the resource. + /// + /// http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm + [StructLayout(LayoutKind.Sequential)] + internal class NEResourceTable + { + /// + /// Alignment shift count for resource data. + /// + public ushort AlignmentShiftCount; + + /// + /// A table of resource type information blocks. + /// + public ResourceTypeInformationBlock[] TypeInformationBlocks; + + /// + /// Resource type and name strings are stored at the end of the + /// resource table. Note that these strings are NOT null terminated and + /// are case sensitive. + /// + public NEResourceNameString[] TypeAndNameStrings; + + public static NEResourceTable Deserialize(Stream stream) + { + var nrt = new NEResourceTable(); + + nrt.AlignmentShiftCount = stream.ReadUInt16(); + var typeInformationBlocks = new List(); + while (true) + { + var block = ResourceTypeInformationBlock.Deserialize(stream); + if (block.TypeID == 0) + break; + + typeInformationBlocks.Add(block); + } + + nrt.TypeInformationBlocks = typeInformationBlocks.ToArray(); + + var typeAndNameStrings = new List(); + while (true) + { + var str = NEResourceNameString.Deserialize(stream); + if (str.Length == 0) + break; + + typeAndNameStrings.Add(str); + } + + nrt.TypeAndNameStrings = typeAndNameStrings.ToArray(); + + return nrt; + } + + public static NEResourceTable Deserialize(byte[] contents, int offset) + { + var nrt = new NEResourceTable(); + + nrt.AlignmentShiftCount = BitConverter.ToUInt16(contents, offset); offset += 2; + var typeInformationBlocks = new List(); + while (true) + { + unsafe + { + var block = ResourceTypeInformationBlock.Deserialize(contents, offset); offset += Marshal.SizeOf(block); + if (block.TypeID == 0) + break; + + typeInformationBlocks.Add(block); + } + } + + nrt.TypeInformationBlocks = typeInformationBlocks.ToArray(); + + var typeAndNameStrings = new List(); + while (true) + { + unsafe + { + var str = NEResourceNameString.Deserialize(contents, offset); offset += Marshal.SizeOf(str); + if (str.Length == 0) + break; + + typeAndNameStrings.Add(str); + } + } + + nrt.TypeAndNameStrings = typeAndNameStrings.ToArray(); + + return nrt; + } + } +} \ No newline at end of file