diff --git a/exeinfogui/MainForm.xeto b/exeinfogui/MainForm.xeto index 29b710f..fcf1f5b 100644 --- a/exeinfogui/MainForm.xeto +++ b/exeinfogui/MainForm.xeto @@ -28,6 +28,18 @@ + + + + + + + + + + + + diff --git a/exeinfogui/MainForm.xeto.cs b/exeinfogui/MainForm.xeto.cs index b51cfe0..296e411 100644 --- a/exeinfogui/MainForm.xeto.cs +++ b/exeinfogui/MainForm.xeto.cs @@ -36,8 +36,11 @@ namespace exeinfogui public class MainForm : Form { ComboBox cmbArch; + Label lblSubsystem; TextBox txtFile; TextArea txtInformation; + TextBox txtOs; + TextBox txtSubsystem; TextBox txtType; public MainForm() @@ -51,6 +54,8 @@ namespace exeinfogui txtType.Text = ""; txtInformation.Text = ""; cmbArch.Items.Clear(); + lblSubsystem.Visible = false; + txtSubsystem.Visible = false; OpenFileDialog dlgOpen = new OpenFileDialog {Title = "Choose executable file", MultiSelect = false}; @@ -82,8 +87,6 @@ namespace exeinfogui else txtType.Text = "Format not recognized"; - cmbArch.SelectedIndex = 0; - exeFs.Close(); if(recognizedExe == null) return; @@ -92,6 +95,20 @@ namespace exeinfogui txtInformation.Text = recognizedExe.Information; foreach(Architecture arch in recognizedExe.Architectures) cmbArch.Items.Add(Enums.ArchitectureName.FirstOrDefault(ar => ar.arch == arch).longName); + cmbArch.SelectedIndex = 0; + + if(recognizedExe.RequiredOperatingSystem.MajorVersion > 0) + txtOs.Text = $"{recognizedExe.RequiredOperatingSystem.Name}" + + $" {recognizedExe.RequiredOperatingSystem.MajorVersion}" + + $".{recognizedExe.RequiredOperatingSystem.MinorVersion}"; + else txtOs.Text = recognizedExe.RequiredOperatingSystem.Name; + + if(!string.IsNullOrEmpty(recognizedExe.RequiredOperatingSystem.Subsystem)) + { + lblSubsystem.Visible = true; + txtSubsystem.Visible = true; + txtSubsystem.Text = recognizedExe.RequiredOperatingSystem.Subsystem; + } } protected void OnMnuAboutClick(object sender, EventArgs e) diff --git a/libexeinfo/AtariST/AtariST.cs b/libexeinfo/AtariST/AtariST.cs index e858190..8b57988 100644 --- a/libexeinfo/AtariST/AtariST.cs +++ b/libexeinfo/AtariST/AtariST.cs @@ -24,6 +24,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; @@ -67,12 +68,13 @@ namespace libexeinfo /// /// Header for this executable /// - public AtariHeader Header { get; private set; } - public Stream BaseStream { get; } - public bool IsBigEndian => true; - public bool Recognized { get; private set; } - public string Type { get; private set; } - public Architecture[] Architectures => new[] {Architecture.M68K}; + public AtariHeader Header { get; private set; } + public Stream BaseStream { get; } + public bool IsBigEndian => true; + public bool Recognized { get; private set; } + public string Type { get; private set; } + public IEnumerable Architectures => new[] {Architecture.M68K}; + public OperatingSystem RequiredOperatingSystem => new OperatingSystem {Name = "Atari TOS"}; void Initialize() { diff --git a/libexeinfo/COFF/COFF.cs b/libexeinfo/COFF/COFF.cs index b256ec7..c9b32e5 100644 --- a/libexeinfo/COFF/COFF.cs +++ b/libexeinfo/COFF/COFF.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; +using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; @@ -68,12 +69,14 @@ namespace libexeinfo /// /// Header for this executable /// - public COFFHeader Header { get; private set; } - public Stream BaseStream { get; } - public bool IsBigEndian { get; private set; } - public bool Recognized { get; private set; } - public string Type { get; private set; } - public Architecture[] Architectures => new[] {MachineTypeToArchitecture(Header.machine)}; + public COFFHeader Header { get; private set; } + public Stream BaseStream { get; } + public bool IsBigEndian { get; private set; } + public bool Recognized { get; private set; } + public string Type { get; private set; } + public IEnumerable Architectures => new[] {MachineTypeToArchitecture(Header.machine)}; + public OperatingSystem RequiredOperatingSystem => + new OperatingSystem {Name = "Unknown"}; // TODO: Know void Initialize() { diff --git a/libexeinfo/IExecutable.cs b/libexeinfo/IExecutable.cs index baa67c2..5a4244e 100644 --- a/libexeinfo/IExecutable.cs +++ b/libexeinfo/IExecutable.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; namespace libexeinfo { @@ -27,6 +28,10 @@ namespace libexeinfo /// /// Architectures that the executable can run on /// - Architecture[] Architectures { get; } + IEnumerable Architectures { get; } + /// + /// Operating system the executable requires to run on + /// + OperatingSystem RequiredOperatingSystem { get; } } } \ No newline at end of file diff --git a/libexeinfo/LX/LX.cs b/libexeinfo/LX/LX.cs index 4bd08a1..ae14e0b 100644 --- a/libexeinfo/LX/LX.cs +++ b/libexeinfo/LX/LX.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; +using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; @@ -75,11 +76,12 @@ namespace libexeinfo /// /// The that contains the executable represented by this instance /// - public Stream BaseStream { get; } - public bool IsBigEndian => false; - public bool Recognized { get; private set; } - public string Type { get; private set; } - public Architecture[] Architectures => new[] {CpuToArchitecture(header.cpu_type)}; + public Stream BaseStream { get; } + public bool IsBigEndian { get; private set; } + public bool Recognized { get; private set; } + public string Type { get; private set; } + public IEnumerable Architectures => new[] {CpuToArchitecture(header.cpu_type)}; + public OperatingSystem RequiredOperatingSystem { get; private set; } void Initialize() { @@ -102,7 +104,36 @@ namespace libexeinfo if(!Recognized) return; - Type = header.signature == SIGNATURE16 ? "Linear Executable (LE)" : "Linear eXecutable (LX)"; + Type = header.signature == SIGNATURE16 ? "Linear Executable (LE)" : "Linear eXecutable (LX)"; + IsBigEndian = header.byte_order == 1 || header.word_order == 1; + + OperatingSystem reqOs = new OperatingSystem(); + switch(header.os_type) + { + case TargetOS.OS2: + reqOs.Name = "OS/2"; + if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && + !header.module_flags.HasFlag(ModuleFlags.PMCompatible) || + !header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && + header.module_flags.HasFlag(ModuleFlags.PMCompatible)) reqOs.Subsystem = "Console"; + else if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && + header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + reqOs.Subsystem = "Presentation Manager"; + break; + case TargetOS.Windows: + case TargetOS.Win32: + case TargetOS.Unknown: + reqOs.Name = "Windows"; + break; + case TargetOS.DOS: + reqOs.Name = "Windows"; + break; + default: + reqOs.Name = $"Unknown code {(ushort)header.os_type}"; + break; + } + + RequiredOperatingSystem = reqOs; } /// diff --git a/libexeinfo/MZ/MZ.cs b/libexeinfo/MZ/MZ.cs index 52adffb..7df67aa 100644 --- a/libexeinfo/MZ/MZ.cs +++ b/libexeinfo/MZ/MZ.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; +using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; @@ -78,9 +79,10 @@ namespace libexeinfo /// /// If true this instance correctly represents a DOS relocatable executable /// - public bool Recognized { get; private set; } - public string Type { get; private set; } - public Architecture[] Architectures => new[] {Architecture.I86}; + public bool Recognized { get; private set; } + public string Type { get; private set; } + public IEnumerable Architectures => new[] {Architecture.I86}; + public OperatingSystem RequiredOperatingSystem => new OperatingSystem {Name = "DOS"}; void Initialize() { diff --git a/libexeinfo/NE/Info.cs b/libexeinfo/NE/Info.cs index 3ef6fab..31cbb24 100644 --- a/libexeinfo/NE/Info.cs +++ b/libexeinfo/NE/Info.cs @@ -64,105 +64,123 @@ namespace libexeinfo if(header.program_flags.HasFlag(ProgramFlags.i87)) sb.AppendLine("\tApplication uses floating point instructions"); - if(header.target_os == TargetOS.OS2) + switch(header.target_os) { - sb.AppendLine("\tOS/2 application"); - if(header.os_major > 0) - sb.AppendFormat("\tApplication requires OS/2 {0}.{1} to run", header.os_major, header.os_minor) - .AppendLine(); - else sb.AppendLine("\tApplication requires OS/2 1.0 to run"); - if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication is full screen, unaware of Presentation Manager"); - else if(!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication is aware of Presentation Manager, but doesn't use it"); - else if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication uses Presentation Manager"); - if(header.os2_flags.HasFlag(OS2Flags.LongFilename)) - sb.AppendLine("\tApplication supports long filenames"); - if(header.os2_flags.HasFlag(OS2Flags.ProtectedMode2)) - sb.AppendLine("\tApplication uses OS/2 2.x protected mode"); - if(header.os2_flags.HasFlag(OS2Flags.ProportionalFonts)) - sb.AppendLine("\tApplication uses OS/2 2.x proportional fonts"); - if(header.os2_flags.HasFlag(OS2Flags.GangloadArea)) - sb.AppendFormat("\tGangload area starts at {0} an runs for {1} bytes", header.return_thunks_offset, - header.segment_reference_thunks).AppendLine(); - else - { + case TargetOS.OS2: + sb.AppendLine("\tOS/2 application"); + if(header.os_major > 0) + sb.AppendFormat("\tApplication requires OS/2 {0}.{1} to run", header.os_major, header.os_minor) + .AppendLine(); + else sb.AppendLine("\tApplication requires OS/2 1.0 to run"); + if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication is full screen, unaware of Presentation Manager"); + else if(!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication is aware of Presentation Manager, but doesn't use it"); + else if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication uses Presentation Manager"); + if(header.os2_flags.HasFlag(OS2Flags.LongFilename)) + sb.AppendLine("\tApplication supports long filenames"); + if(header.os2_flags.HasFlag(OS2Flags.ProtectedMode2)) + sb.AppendLine("\tApplication uses OS/2 2.x protected mode"); + if(header.os2_flags.HasFlag(OS2Flags.ProportionalFonts)) + sb.AppendLine("\tApplication uses OS/2 2.x proportional fonts"); + if(header.os2_flags.HasFlag(OS2Flags.GangloadArea)) + sb.AppendFormat("\tGangload area starts at {0} an runs for {1} bytes", + header.return_thunks_offset, header.segment_reference_thunks).AppendLine(); + else + { + sb.AppendFormat("\tReturn thunks are at: {0}", header.return_thunks_offset) + .AppendLine(); + sb.AppendFormat("\tSegment reference thunks are at: {0}", header.segment_reference_thunks) + .AppendLine(); + } + + break; + case TargetOS.Windows: + case TargetOS.Win32: + case TargetOS.Unknown: + switch(header.target_os) + { + case TargetOS.Windows: + case TargetOS.Unknown: + sb.AppendLine("\t16-bit Windows application"); + break; + case TargetOS.Win32: + sb.AppendLine("\t32-bit Windows application"); + break; + } + + if(header.os_major > 0) + sb.AppendFormat("\tApplication requires Windows {0}.{1} to run", header.os_major, + header.os_minor).AppendLine(); + else + switch(header.target_os) + { + case TargetOS.Windows: + sb.AppendLine("\tApplication requires Windows 2.0 to run"); + break; + case TargetOS.Unknown: + sb.AppendLine("\tApplication requires Windows 1.0 to run"); + break; + } + if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication is full screen, unaware of Windows"); + else if(!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication is aware of Windows, but doesn't use it"); + else if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication uses Windows"); sb.AppendFormat("\tReturn thunks are at: {0}", header.return_thunks_offset).AppendLine(); sb.AppendFormat("\tSegment reference thunks are at: {0}", header.segment_reference_thunks) .AppendLine(); - } - } - else if(header.target_os == TargetOS.Windows || header.target_os == TargetOS.Win32 || - header.target_os == TargetOS.Unknown) - { - if(header.target_os == TargetOS.Windows || header.target_os == TargetOS.Unknown) - sb.AppendLine("\t16-bit Windows application"); - else if(header.target_os == TargetOS.Win32) - sb.AppendLine("\t32-bit Windows application"); - if(header.os_major > 0) - sb.AppendFormat("\tApplication requires Windows {0}.{1} to run", header.os_major, header.os_minor) + break; + case TargetOS.DOS: + sb.AppendLine("\tDOS application"); + sb.AppendFormat("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor) .AppendLine(); - else if(header.target_os == TargetOS.Windows) - sb.AppendLine("\tApplication requires Windows 2.0 to run"); - else if(header.target_os == TargetOS.Unknown) - sb.AppendLine("\tApplication requires Windows 1.0 to run"); - if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication is full screen, unaware of Windows"); - else if(!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication is aware of Windows, but doesn't use it"); - else if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication uses Windows"); - sb.AppendFormat("\tReturn thunks are at: {0}", header.return_thunks_offset).AppendLine(); - sb.AppendFormat("\tSegment reference thunks are at: {0}", header.segment_reference_thunks).AppendLine(); - } - else if(header.target_os == TargetOS.DOS) - { - sb.AppendLine("\tDOS application"); - sb.AppendFormat("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor) - .AppendLine(); - if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication is full screen, unaware of Windows"); - else if(!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication is aware of Windows, but doesn't use it"); - else if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication uses Windows"); - sb.AppendFormat("\tReturn thunks are at: {0}", header.return_thunks_offset).AppendLine(); - sb.AppendFormat("\tSegment reference thunks are at: {0}", header.segment_reference_thunks).AppendLine(); - } - else if(header.target_os == TargetOS.Borland) - { - sb.AppendLine("\tBorland Operating System Services application"); - sb.AppendFormat("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor) - .AppendLine(); - if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication is full screen, unaware of Windows"); - else if(!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication is aware of Windows, but doesn't use it"); - else if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && - header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) - sb.AppendLine("\tApplication uses Windows"); - sb.AppendFormat("\tReturn thunks are at: {0}", header.return_thunks_offset).AppendLine(); - sb.AppendFormat("\tSegment reference thunks are at: {0}", header.segment_reference_thunks).AppendLine(); - } - else - { - sb.AppendFormat("\tApplication for unknown OS {0}", (byte)header.target_os).AppendLine(); - sb.AppendFormat("\tApplication requires OS {0}.{1} to run", header.os_major, header.os_minor) - .AppendLine(); - sb.AppendFormat("\tReturn thunks are at: {0}", header.return_thunks_offset).AppendLine(); - sb.AppendFormat("\tSegment reference thunks are at: {0}", header.segment_reference_thunks).AppendLine(); + if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication is full screen, unaware of Windows"); + else if(!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication is aware of Windows, but doesn't use it"); + else if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication uses Windows"); + sb.AppendFormat("\tReturn thunks are at: {0}", header.return_thunks_offset).AppendLine(); + sb.AppendFormat("\tSegment reference thunks are at: {0}", header.segment_reference_thunks) + .AppendLine(); + break; + case TargetOS.Borland: + sb.AppendLine("\tBorland Operating System Services application"); + sb.AppendFormat("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor) + .AppendLine(); + if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication is full screen, unaware of Windows"); + else if(!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication is aware of Windows, but doesn't use it"); + else if(header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + sb.AppendLine("\tApplication uses Windows"); + sb.AppendFormat("\tReturn thunks are at: {0}", header.return_thunks_offset).AppendLine(); + sb.AppendFormat("\tSegment reference thunks are at: {0}", header.segment_reference_thunks) + .AppendLine(); + break; + default: + sb.AppendFormat("\tApplication for unknown OS {0}", (byte)header.target_os).AppendLine(); + sb.AppendFormat("\tApplication requires OS {0}.{1} to run", header.os_major, header.os_minor) + .AppendLine(); + sb.AppendFormat("\tReturn thunks are at: {0}", header.return_thunks_offset).AppendLine(); + sb.AppendFormat("\tSegment reference thunks are at: {0}", header.segment_reference_thunks) + .AppendLine(); + break; } if(header.application_flags.HasFlag(ApplicationFlags.Errors)) sb.AppendLine("\tExecutable has errors"); diff --git a/libexeinfo/NE/NE.cs b/libexeinfo/NE/NE.cs index 7225cd2..80906dd 100644 --- a/libexeinfo/NE/NE.cs +++ b/libexeinfo/NE/NE.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; +using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; @@ -73,11 +74,11 @@ namespace libexeinfo Initialize(); } - public Stream BaseStream { get; } - public bool IsBigEndian => false; - public bool Recognized { get; private set; } - public string Type { get; private set; } - public Architecture[] Architectures => + public Stream BaseStream { get; } + public bool IsBigEndian => false; + public bool Recognized { get; private set; } + public string Type { get; private set; } + public IEnumerable Architectures => new[] { Header.target_os == TargetOS.Win32 || Header.program_flags.HasFlag(ProgramFlags.i386) @@ -86,6 +87,7 @@ namespace libexeinfo ? Architecture.I286 : Architecture.I86 }; + public OperatingSystem RequiredOperatingSystem { get; private set; } void Initialize() { @@ -109,6 +111,71 @@ namespace libexeinfo Recognized = true; Type = "New Executable (NE)"; + + OperatingSystem reqOs = new OperatingSystem(); + + switch(Header.target_os) + { + case TargetOS.OS2: + reqOs.Name = "OS/2"; + if(Header.os_major > 0) + { + reqOs.MajorVersion = Header.os_major; + reqOs.MinorVersion = Header.os_minor; + } + else + { + reqOs.MajorVersion = 1; + reqOs.MinorVersion = 0; + } + + if(Header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + !Header.application_flags.HasFlag(ApplicationFlags.GUICompatible) || + !Header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + Header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) reqOs.Subsystem = "Console"; + else if(Header.application_flags.HasFlag(ApplicationFlags.FullScreen) && + Header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + reqOs.Subsystem = "Presentation Manager"; + break; + case TargetOS.Windows: + case TargetOS.Win32: + case TargetOS.Unknown: + reqOs.Name = "Windows"; + if(Header.os_major > 0) + { + reqOs.MajorVersion = Header.os_major; + reqOs.MinorVersion = Header.os_minor; + } + else + switch(Header.target_os) + { + case TargetOS.Windows: + reqOs.MajorVersion = 2; + reqOs.MinorVersion = 0; + break; + case TargetOS.Unknown: + reqOs.MajorVersion = 1; + reqOs.MinorVersion = 0; + break; + } + + break; + case TargetOS.DOS: + case TargetOS.Borland: + reqOs.Name = "DOS"; + reqOs.MajorVersion = Header.os_major; + reqOs.MinorVersion = Header.os_minor; + if(Header.target_os == TargetOS.Borland) reqOs.Subsystem = "Borland Operating System Services"; + break; + default: + reqOs.Name = $"Unknown code {(byte)Header.target_os}"; + reqOs.MajorVersion = Header.os_major; + reqOs.MinorVersion = Header.os_minor; + break; + } + + RequiredOperatingSystem = reqOs; + if(Header.resource_entries <= 0) return; Resources = GetResources(BaseStream, BaseExecutable.Header.new_offset, Header.resource_table_offset); diff --git a/libexeinfo/PE/PE.cs b/libexeinfo/PE/PE.cs index 5014293..56b6980 100644 --- a/libexeinfo/PE/PE.cs +++ b/libexeinfo/PE/PE.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; +using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; @@ -72,11 +73,13 @@ namespace libexeinfo Initialize(); } - public Stream BaseStream { get; } - public bool IsBigEndian => false; - public bool Recognized { get; private set; } - public string Type { get; private set; } - public Architecture[] Architectures => new[] {COFF.MachineTypeToArchitecture(Header.coff.machine)}; + public Stream BaseStream { get; } + public bool IsBigEndian => false; + public bool Recognized { get; private set; } + public string Type { get; private set; } + public IEnumerable Architectures => + new[] {COFF.MachineTypeToArchitecture(Header.coff.machine)}; + public OperatingSystem RequiredOperatingSystem { get; private set; } void Initialize() { @@ -121,6 +124,62 @@ namespace libexeinfo Marshal.FreeHGlobal(hdrPtr); WinHeader = ToPlus(hdr32); } + + OperatingSystem reqOs = new OperatingSystem(); + + switch(WinHeader.subsystem) + { + case Subsystems.IMAGE_SUBSYSTEM_UNKNOWN: + reqOs.Name = "Unknown"; + break; + case Subsystems.IMAGE_SUBSYSTEM_NATIVE: + reqOs.Name = "Windows NT"; + reqOs.Subsystem = "Native"; + break; + case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_GUI: + reqOs.Name = WinHeader.majorOperatingSystemVersion < 3 ? "Windows NT" : "Windows"; + reqOs.Subsystem = "GUI"; + break; + case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_CUI: + reqOs.Name = WinHeader.majorOperatingSystemVersion < 3 ? "Windows NT" : "Windows"; + reqOs.Subsystem = "Console"; + break; + case Subsystems.IMAGE_SUBSYSTEM_OS2_CUI: + reqOs.Name = "Windows NT"; + reqOs.Subsystem = "OS/2"; + break; + case Subsystems.IMAGE_SUBSYSTEM_POSIX_CUI: + reqOs.Name = "Windows NT"; + reqOs.Subsystem = "POSIX"; + break; + case Subsystems.IMAGE_SUBSYSTEM_NATIVE_WINDOWS: + reqOs.Name = "Windows"; + reqOs.Subsystem = "Native"; + break; + case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: + reqOs.Name = "Windows CE"; + break; + case Subsystems.IMAGE_SUBSYSTEM_EFI_APPLICATION: + case Subsystems.IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + case Subsystems.IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + case Subsystems.IMAGE_SUBSYSTEM_EFI_ROM: + reqOs.Name = "EFI"; + break; + case Subsystems.IMAGE_SUBSYSTEM_XBOX: + reqOs.Name = "Xbox OS"; + break; + case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION: + reqOs.Name = "Windows NT"; + reqOs.Subsystem = "Boot environment"; + break; + default: + reqOs.Name = $"Unknown code ${(ushort)WinHeader.subsystem}"; + break; + } + + reqOs.MajorVersion = WinHeader.majorOperatingSystemVersion; + reqOs.MinorVersion = WinHeader.minorOperatingSystemVersion; + RequiredOperatingSystem = reqOs; } /// diff --git a/libexeinfo/Structs.cs b/libexeinfo/Structs.cs new file mode 100644 index 0000000..ffc619d --- /dev/null +++ b/libexeinfo/Structs.cs @@ -0,0 +1,10 @@ +namespace libexeinfo +{ + public struct OperatingSystem + { + public string Name; + public int MajorVersion; + public int MinorVersion; + public string Subsystem; + } +} \ No newline at end of file diff --git a/libexeinfo/libexeinfo.csproj b/libexeinfo/libexeinfo.csproj index ebc4154..8895836 100644 --- a/libexeinfo/libexeinfo.csproj +++ b/libexeinfo/libexeinfo.csproj @@ -80,6 +80,7 @@ +