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 @@
+