diff --git a/BurnOutSharp/ExecutableType/Microsoft/Entries/ResidentNameTableEntry.cs b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResidentNameTableEntry.cs new file mode 100644 index 00000000..b81a2ef9 --- /dev/null +++ b/BurnOutSharp/ExecutableType/Microsoft/Entries/ResidentNameTableEntry.cs @@ -0,0 +1,79 @@ +using System.IO; +using System.Text; +using BurnOutSharp.Tools; + +namespace BurnOutSharp.ExecutableType.Microsoft.Entries +{ + /// + /// These name strings are case-sensitive and are not null-terminated + /// + public class ResidentNameTableEntry + { + /// + /// Length of the name string that follows. + /// A zero value indicates the end of the name table. + /// + public byte Length; + + /// + /// ASCII text of the name string. + /// + public byte[] Data; + + /// + /// Ordinal number (index into entry table). + /// This value is ignored for the module name. + /// + public ushort OrdinalNumber; + + /// + /// ASCII text of the name string + /// + public string DataAsString + { + get + { + if (Data == null) + return string.Empty; + + // Try to read direct as ASCII + try + { + return Encoding.ASCII.GetString(Data); + } + catch { } + + // If ASCII encoding fails, then just return an empty string + return string.Empty; + } + } + + public static ResidentNameTableEntry Deserialize(Stream stream) + { + var rnte = new ResidentNameTableEntry(); + + rnte.Length = stream.ReadByteValue(); + if (rnte.Length == 0) + return rnte; + + rnte.Data = stream.ReadBytes(rnte.Length); + rnte.OrdinalNumber = stream.ReadUInt16(); + + return rnte; + } + + public static ResidentNameTableEntry Deserialize(byte[] content, ref int offset) + { + var rnte = new ResidentNameTableEntry(); + + rnte.Length = content.ReadByte(ref offset); + if (rnte.Length == 0) + return rnte; + + rnte.Data = content.ReadBytes(ref offset, rnte.Length); + rnte.OrdinalNumber = content.ReadUInt16(ref offset); + + return rnte; + } + } +} \ No newline at end of file diff --git a/BurnOutSharp/ExecutableType/Microsoft/Tables/ResidentNameTable.cs b/BurnOutSharp/ExecutableType/Microsoft/Tables/ResidentNameTable.cs new file mode 100644 index 00000000..24d6ba36 --- /dev/null +++ b/BurnOutSharp/ExecutableType/Microsoft/Tables/ResidentNameTable.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using System.IO; +using BurnOutSharp.ExecutableType.Microsoft.Entries; + +namespace BurnOutSharp.ExecutableType.Microsoft.Tables +{ + /// + /// The resident-name table follows the resource table, and contains this + /// module's name string and resident exported procedure name strings. The + /// first string in this table is this module's name. These name strings + /// are case-sensitive and are not null-terminated. + /// + public class ResidentNameTable + { + /// + /// The first string in this table is this module's name. + /// These name strings are case-sensitive and are not null-terminated. + /// + public ResidentNameTableEntry[] NameTableEntries; + + public static ResidentNameTable Deserialize(Stream stream) + { + var rnt = new ResidentNameTable(); + + var nameTableEntries = new List(); + while (true) + { + var rnte = ResidentNameTableEntry.Deserialize(stream); + if (rnte == null || rnte.Length == 0) + break; + + nameTableEntries.Add(rnte); + } + + rnt.NameTableEntries = nameTableEntries.ToArray(); + + return rnt; + } + + public static ResidentNameTable Deserialize(byte[] content, ref int offset) + { + var rnt = new ResidentNameTable(); + + var nameTableEntries = new List(); + while (true) + { + var rnte = ResidentNameTableEntry.Deserialize(content, ref offset); + if (rnte == null || rnte.Length == 0) + break; + + nameTableEntries.Add(rnte); + } + + rnt.NameTableEntries = nameTableEntries.ToArray(); + + return rnt; + } + } +} \ No newline at end of file