using System; using System.IO; using System.Text; namespace BinaryObjectScanner.Wrappers { public class LinearExecutable : WrapperBase { #region Descriptive Properties /// public override string DescriptionString => "Linear Executable (LE/LX)"; #endregion #region Pass-Through Properties #region MS-DOS Stub #region Standard Fields /// #if NET48 public string Stub_Magic => _model.Stub.Header.Magic; #else public string? Stub_Magic => _model.Stub?.Header?.Magic; #endif /// #if NET48 public ushort Stub_LastPageBytes => _model.Stub.Header.LastPageBytes; #else public ushort? Stub_LastPageBytes => _model.Stub?.Header?.LastPageBytes; #endif /// #if NET48 public ushort Stub_Pages => _model.Stub.Header.Pages; #else public ushort? Stub_Pages => _model.Stub?.Header?.Pages; #endif /// #if NET48 public ushort Stub_RelocationItems => _model.Stub.Header.RelocationItems; #else public ushort? Stub_RelocationItems => _model.Stub?.Header?.RelocationItems; #endif /// #if NET48 public ushort Stub_HeaderParagraphSize => _model.Stub.Header.HeaderParagraphSize; #else public ushort? Stub_HeaderParagraphSize => _model.Stub?.Header?.HeaderParagraphSize; #endif /// #if NET48 public ushort Stub_MinimumExtraParagraphs => _model.Stub.Header.MinimumExtraParagraphs; #else public ushort? Stub_MinimumExtraParagraphs => _model.Stub?.Header?.MinimumExtraParagraphs; #endif /// #if NET48 public ushort Stub_MaximumExtraParagraphs => _model.Stub.Header.MaximumExtraParagraphs; #else public ushort? Stub_MaximumExtraParagraphs => _model.Stub?.Header?.MaximumExtraParagraphs; #endif /// #if NET48 public ushort Stub_InitialSSValue => _model.Stub.Header.InitialSSValue; #else public ushort? Stub_InitialSSValue => _model.Stub?.Header?.InitialSSValue; #endif /// #if NET48 public ushort Stub_InitialSPValue => _model.Stub.Header.InitialSPValue; #else public ushort? Stub_InitialSPValue => _model.Stub?.Header?.InitialSPValue; #endif /// #if NET48 public ushort Stub_Checksum => _model.Stub.Header.Checksum; #else public ushort? Stub_Checksum => _model.Stub?.Header?.Checksum; #endif /// #if NET48 public ushort Stub_InitialIPValue => _model.Stub.Header.InitialIPValue; #else public ushort? Stub_InitialIPValue => _model.Stub?.Header?.InitialIPValue; #endif /// #if NET48 public ushort Stub_InitialCSValue => _model.Stub.Header.InitialCSValue; #else public ushort? Stub_InitialCSValue => _model.Stub?.Header?.InitialCSValue; #endif /// #if NET48 public ushort Stub_RelocationTableAddr => _model.Stub.Header.RelocationTableAddr; #else public ushort? Stub_RelocationTableAddr => _model.Stub?.Header?.RelocationTableAddr; #endif /// #if NET48 public ushort Stub_OverlayNumber => _model.Stub.Header.OverlayNumber; #else public ushort? Stub_OverlayNumber => _model.Stub?.Header?.OverlayNumber; #endif #endregion #region PE Extensions /// #if NET48 public ushort[] Stub_Reserved1 => _model.Stub.Header.Reserved1; #else public ushort[]? Stub_Reserved1 => _model.Stub?.Header?.Reserved1; #endif /// #if NET48 public ushort Stub_OEMIdentifier => _model.Stub.Header.OEMIdentifier; #else public ushort? Stub_OEMIdentifier => _model.Stub?.Header?.OEMIdentifier; #endif /// #if NET48 public ushort Stub_OEMInformation => _model.Stub.Header.OEMInformation; #else public ushort? Stub_OEMInformation => _model.Stub?.Header?.OEMInformation; #endif /// #if NET48 public ushort[] Stub_Reserved2 => _model.Stub.Header.Reserved2; #else public ushort[]? Stub_Reserved2 => _model?.Stub?.Header?.Reserved2; #endif /// #if NET48 public uint Stub_NewExeHeaderAddr => _model.Stub.Header.NewExeHeaderAddr; #else public uint? Stub_NewExeHeaderAddr => _model.Stub?.Header?.NewExeHeaderAddr; #endif #endregion #endregion #region Information Block /// #if NET48 public string Signature => _model.InformationBlock.Signature; #else public string? Signature => _model.InformationBlock?.Signature; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.ByteOrder ByteOrder => _model.InformationBlock.ByteOrder; #else public SabreTools.Models.LinearExecutable.ByteOrder? ByteOrder => _model.InformationBlock?.ByteOrder; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.WordOrder WordOrder => _model.InformationBlock.WordOrder; #else public SabreTools.Models.LinearExecutable.WordOrder? WordOrder => _model.InformationBlock?.WordOrder; #endif /// #if NET48 public uint ExecutableFormatLevel => _model.InformationBlock.ExecutableFormatLevel; #else public uint? ExecutableFormatLevel => _model.InformationBlock?.ExecutableFormatLevel; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.CPUType CPUType => _model.InformationBlock.CPUType; #else public SabreTools.Models.LinearExecutable.CPUType? CPUType => _model.InformationBlock?.CPUType; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.OperatingSystem ModuleOS => _model.InformationBlock.ModuleOS; #else public SabreTools.Models.LinearExecutable.OperatingSystem? ModuleOS => _model.InformationBlock?.ModuleOS; #endif /// #if NET48 public uint ModuleVersion => _model.InformationBlock.ModuleVersion; #else public uint? ModuleVersion => _model.InformationBlock?.ModuleVersion; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.ModuleFlags ModuleTypeFlags => _model.InformationBlock.ModuleTypeFlags; #else public SabreTools.Models.LinearExecutable.ModuleFlags? ModuleTypeFlags => _model.InformationBlock?.ModuleTypeFlags; #endif /// #if NET48 public uint ModuleNumberPages => _model.InformationBlock.ModuleNumberPages; #else public uint? ModuleNumberPages => _model.InformationBlock?.ModuleNumberPages; #endif /// #if NET48 public uint InitialObjectCS => _model.InformationBlock.InitialObjectCS; #else public uint? InitialObjectCS => _model.InformationBlock?.InitialObjectCS; #endif /// #if NET48 public uint InitialEIP => _model.InformationBlock.InitialEIP; #else public uint? InitialEIP => _model.InformationBlock?.InitialEIP; #endif /// #if NET48 public uint InitialObjectSS => _model.InformationBlock.InitialObjectSS; #else public uint? InitialObjectSS => _model.InformationBlock?.InitialObjectSS; #endif /// #if NET48 public uint InitialESP => _model.InformationBlock.InitialESP; #else public uint? InitialESP => _model.InformationBlock?.InitialESP; #endif /// #if NET48 public uint MemoryPageSize => _model.InformationBlock.MemoryPageSize; #else public uint? MemoryPageSize => _model.InformationBlock?.MemoryPageSize; #endif /// #if NET48 public uint BytesOnLastPage => _model.InformationBlock.BytesOnLastPage; #else public uint? BytesOnLastPage => _model.InformationBlock?.BytesOnLastPage; #endif /// #if NET48 public uint FixupSectionSize => _model.InformationBlock.FixupSectionSize; #else public uint? FixupSectionSize => _model.InformationBlock?.FixupSectionSize; #endif /// #if NET48 public uint FixupSectionChecksum => _model.InformationBlock.FixupSectionChecksum; #else public uint? FixupSectionChecksum => _model.InformationBlock?.FixupSectionChecksum; #endif /// #if NET48 public uint LoaderSectionSize => _model.InformationBlock.LoaderSectionSize; #else public uint? LoaderSectionSize => _model.InformationBlock?.LoaderSectionSize; #endif /// #if NET48 public uint LoaderSectionChecksum => _model.InformationBlock.LoaderSectionChecksum; #else public uint? LoaderSectionChecksum => _model.InformationBlock?.LoaderSectionChecksum; #endif /// #if NET48 public uint ObjectTableOffset => _model.InformationBlock.ObjectTableOffset; #else public uint? ObjectTableOffset => _model.InformationBlock?.ObjectTableOffset; #endif /// #if NET48 public uint ObjectTableCount => _model.InformationBlock.ObjectTableCount; #else public uint? ObjectTableCount => _model.InformationBlock?.ObjectTableCount; #endif /// #if NET48 public uint ObjectPageMapOffset => _model.InformationBlock.ObjectPageMapOffset; #else public uint? ObjectPageMapOffset => _model.InformationBlock?.ObjectPageMapOffset; #endif /// #if NET48 public uint ObjectIterateDataMapOffset => _model.InformationBlock.ObjectIterateDataMapOffset; #else public uint? ObjectIterateDataMapOffset => _model.InformationBlock?.ObjectIterateDataMapOffset; #endif /// #if NET48 public uint ResourceTableOffset => _model.InformationBlock.ResourceTableOffset; #else public uint? ResourceTableOffset => _model.InformationBlock?.ResourceTableOffset; #endif /// #if NET48 public uint ResourceTableCount => _model.InformationBlock.ResourceTableCount; #else public uint? ResourceTableCount => _model.InformationBlock?.ResourceTableCount; #endif /// #if NET48 public uint ResidentNamesTableOffset => _model.InformationBlock.ResidentNamesTableOffset; #else public uint? ResidentNamesTableOffset => _model.InformationBlock?.ResidentNamesTableOffset; #endif /// #if NET48 public uint EntryTableOffset => _model.InformationBlock.EntryTableOffset; #else public uint? EntryTableOffset => _model.InformationBlock?.EntryTableOffset; #endif /// #if NET48 public uint ModuleDirectivesTableOffset => _model.InformationBlock.ModuleDirectivesTableOffset; #else public uint? ModuleDirectivesTableOffset => _model.InformationBlock?.ModuleDirectivesTableOffset; #endif /// #if NET48 public uint ModuleDirectivesCount => _model.InformationBlock.ModuleDirectivesCount; #else public uint? ModuleDirectivesCount => _model.InformationBlock?.ModuleDirectivesCount; #endif /// #if NET48 public uint FixupPageTableOffset => _model.InformationBlock.FixupPageTableOffset; #else public uint? FixupPageTableOffset => _model.InformationBlock?.FixupPageTableOffset; #endif /// #if NET48 public uint FixupRecordTableOffset => _model.InformationBlock.FixupRecordTableOffset; #else public uint? FixupRecordTableOffset => _model.InformationBlock?.FixupRecordTableOffset; #endif /// #if NET48 public uint ImportedModulesNameTableOffset => _model.InformationBlock.ImportedModulesNameTableOffset; #else public uint? ImportedModulesNameTableOffset => _model.InformationBlock?.ImportedModulesNameTableOffset; #endif /// #if NET48 public uint ImportedModulesCount => _model.InformationBlock.ImportedModulesCount; #else public uint? ImportedModulesCount => _model.InformationBlock?.ImportedModulesCount; #endif /// #if NET48 public uint ImportProcedureNameTableOffset => _model.InformationBlock.ImportProcedureNameTableOffset; #else public uint? ImportProcedureNameTableOffset => _model.InformationBlock?.ImportProcedureNameTableOffset; #endif /// #if NET48 public uint PerPageChecksumTableOffset => _model.InformationBlock.PerPageChecksumTableOffset; #else public uint? PerPageChecksumTableOffset => _model.InformationBlock?.PerPageChecksumTableOffset; #endif /// #if NET48 public uint DataPagesOffset => _model.InformationBlock.DataPagesOffset; #else public uint? DataPagesOffset => _model.InformationBlock?.DataPagesOffset; #endif /// #if NET48 public uint PreloadPageCount => _model.InformationBlock.PreloadPageCount; #else public uint? PreloadPageCount => _model.InformationBlock?.PreloadPageCount; #endif /// #if NET48 public uint NonResidentNamesTableOffset => _model.InformationBlock.NonResidentNamesTableOffset; #else public uint? NonResidentNamesTableOffset => _model.InformationBlock?.NonResidentNamesTableOffset; #endif /// #if NET48 public uint NonResidentNamesTableLength => _model.InformationBlock.NonResidentNamesTableLength; #else public uint? NonResidentNamesTableLength => _model.InformationBlock?.NonResidentNamesTableLength; #endif /// #if NET48 public uint NonResidentNamesTableChecksum => _model.InformationBlock.NonResidentNamesTableChecksum; #else public uint? NonResidentNamesTableChecksum => _model.InformationBlock?.NonResidentNamesTableChecksum; #endif /// #if NET48 public uint AutomaticDataObject => _model.InformationBlock.AutomaticDataObject; #else public uint? AutomaticDataObject => _model.InformationBlock?.AutomaticDataObject; #endif /// #if NET48 public uint DebugInformationOffset => _model.InformationBlock.DebugInformationOffset; #else public uint? DebugInformationOffset => _model.InformationBlock?.DebugInformationOffset; #endif /// #if NET48 public uint DebugInformationLength => _model.InformationBlock.DebugInformationLength; #else public uint? DebugInformationLength => _model.InformationBlock?.DebugInformationLength; #endif /// #if NET48 public uint PreloadInstancePagesNumber => _model.InformationBlock.PreloadInstancePagesNumber; #else public uint? PreloadInstancePagesNumber => _model.InformationBlock?.PreloadInstancePagesNumber; #endif /// #if NET48 public uint DemandInstancePagesNumber => _model.InformationBlock.DemandInstancePagesNumber; #else public uint? DemandInstancePagesNumber => _model.InformationBlock?.DemandInstancePagesNumber; #endif /// #if NET48 public uint ExtraHeapAllocation => _model.InformationBlock.ExtraHeapAllocation; #else public uint? ExtraHeapAllocation => _model.InformationBlock?.ExtraHeapAllocation; #endif #endregion #region Tables /// #if NET48 public SabreTools.Models.LinearExecutable.ObjectTableEntry[] ObjectTable => _model.ObjectTable; #else public SabreTools.Models.LinearExecutable.ObjectTableEntry?[]? ObjectTable => _model.ObjectTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.ObjectPageMapEntry[] ObjectPageMap => _model.ObjectPageMap; #else public SabreTools.Models.LinearExecutable.ObjectPageMapEntry?[]? ObjectPageMap => _model.ObjectPageMap; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.ResourceTableEntry[] ResourceTable => _model.ResourceTable; #else public SabreTools.Models.LinearExecutable.ResourceTableEntry?[]? ResourceTable => _model.ResourceTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.ResidentNamesTableEntry[] ResidentNamesTable => _model.ResidentNamesTable; #else public SabreTools.Models.LinearExecutable.ResidentNamesTableEntry?[]? ResidentNamesTable => _model.ResidentNamesTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.EntryTableBundle[] EntryTable => _model.EntryTable; #else public SabreTools.Models.LinearExecutable.EntryTableBundle?[]? EntryTable => _model.EntryTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.ModuleFormatDirectivesTableEntry[] ModuleFormatDirectivesTable => _model.ModuleFormatDirectivesTable; #else public SabreTools.Models.LinearExecutable.ModuleFormatDirectivesTableEntry?[]? ModuleFormatDirectivesTable => _model.ModuleFormatDirectivesTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.VerifyRecordDirectiveTableEntry[] VerifyRecordDirectiveTable => _model.VerifyRecordDirectiveTable; #else public SabreTools.Models.LinearExecutable.VerifyRecordDirectiveTableEntry?[]? VerifyRecordDirectiveTable => _model.VerifyRecordDirectiveTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.PerPageChecksumTableEntry[] PerPageChecksumTable => _model.PerPageChecksumTable; #else public SabreTools.Models.LinearExecutable.PerPageChecksumTableEntry?[]? PerPageChecksumTable => _model.PerPageChecksumTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.FixupPageTableEntry[] FixupPageTable => _model.FixupPageTable; #else public SabreTools.Models.LinearExecutable.FixupPageTableEntry?[]? FixupPageTable => _model.FixupPageTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.FixupRecordTableEntry[] FixupRecordTable => _model.FixupRecordTable; #else public SabreTools.Models.LinearExecutable.FixupRecordTableEntry?[]? FixupRecordTable => _model.FixupRecordTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.ImportModuleNameTableEntry[] ImportModuleNameTable => _model.ImportModuleNameTable; #else public SabreTools.Models.LinearExecutable.ImportModuleNameTableEntry?[]? ImportModuleNameTable => _model.ImportModuleNameTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.ImportModuleProcedureNameTableEntry[] ImportModuleProcedureNameTable => _model.ImportModuleProcedureNameTable; #else public SabreTools.Models.LinearExecutable.ImportModuleProcedureNameTableEntry?[]? ImportModuleProcedureNameTable => _model.ImportModuleProcedureNameTable; #endif /// #if NET48 public SabreTools.Models.LinearExecutable.NonResidentNamesTableEntry[] NonResidentNamesTable => _model.NonResidentNamesTable; #else public SabreTools.Models.LinearExecutable.NonResidentNamesTableEntry?[]? NonResidentNamesTable => _model.NonResidentNamesTable; #endif #endregion #region Debug Information /// #if NET48 public string DI_Signature => _model.DebugInformation?.Signature; #else public string? DI_Signature => _model.DebugInformation?.Signature; #endif /// public SabreTools.Models.LinearExecutable.DebugFormatType? DI_FormatType => _model.DebugInformation?.FormatType; /// #if NET48 public byte[] DebuggerData => _model.DebugInformation?.DebuggerData; #else public byte[]? DebuggerData => _model.DebugInformation?.DebuggerData; #endif #endregion #endregion #region Extension Properties // TODO: Determine what extension properties are needed #endregion #region Constructors /// #if NET48 public LinearExecutable(SabreTools.Models.LinearExecutable.Executable model, byte[] data, int offset) #else public LinearExecutable(SabreTools.Models.LinearExecutable.Executable? model, byte[]? data, int offset) #endif : base(model, data, offset) { // All logic is handled by the base class } /// #if NET48 public LinearExecutable(SabreTools.Models.LinearExecutable.Executable model, Stream data) #else public LinearExecutable(SabreTools.Models.LinearExecutable.Executable? model, Stream? data) #endif : base(model, data) { // All logic is handled by the base class }/// /// Create an LE/LX executable from a byte array and offset /// /// Byte array representing the executable /// Offset within the array to parse /// An LE/LX executable wrapper on success, null on failure #if NET48 public static LinearExecutable Create(byte[] data, int offset) #else public static LinearExecutable? Create(byte[]? data, int offset) #endif { // If the data is invalid if (data == null) return null; // If the offset is out of bounds if (offset < 0 || offset >= data.Length) return null; // Create a memory stream and use that MemoryStream dataStream = new MemoryStream(data, offset, data.Length - offset); return Create(dataStream); } /// /// Create an LE/LX executable from a Stream /// /// Stream representing the executable /// An LE/LX executable wrapper on success, null on failure #if NET48 public static LinearExecutable Create(Stream data) #else public static LinearExecutable? Create(Stream? data) #endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) return null; var executable = new SabreTools.Serialization.Streams.LinearExecutable().Deserialize(data); if (executable == null) return null; try { return new LinearExecutable(executable, data); } catch { return null; } } #endregion #region Printing /// public override StringBuilder PrettyPrint() { StringBuilder builder = new StringBuilder(); Printing.LinearExecutable.Print(builder, _model); return builder; } #if NET6_0_OR_GREATER /// public override string ExportJSON() => System.Text.Json.JsonSerializer.Serialize(_model, _jsonSerializerOptions); #endif #endregion #region REMOVE -- DO NOT USE /// /// Read an arbitrary range from the source /// /// The start of where to read data from, -1 means start of source /// How many bytes to read, -1 means read until end /// Byte array representing the range, null on error [Obsolete] #if NET48 public byte[] ReadArbitraryRange(int rangeStart = -1, int length = -1) #else public byte[]? ReadArbitraryRange(int rangeStart = -1, int length = -1) #endif { // If we have an unset range start, read from the start of the source if (rangeStart == -1) rangeStart = 0; // If we have an unset length, read the whole source if (length == -1) { switch (_dataSource) { case DataSource.ByteArray: #if NET48 length = _byteArrayData.Length - _byteArrayOffset; #else length = _byteArrayData!.Length - _byteArrayOffset; #endif break; case DataSource.Stream: #if NET48 length = (int)_streamData.Length; #else length = (int)_streamData!.Length; #endif break; } } return ReadFromDataSource(rangeStart, length); } #endregion } }