Refactor.

This commit is contained in:
2018-02-25 22:44:26 +00:00
parent 7bfb6744f2
commit c3cd0b5831
15 changed files with 224 additions and 245 deletions

View File

@@ -68,17 +68,11 @@ namespace libexeinfo
/// <summary> /// <summary>
/// Header for this executable /// Header for this executable
/// </summary> /// </summary>
public COFFHeader Header { get; private set; } public COFFHeader Header { get; private set; }
/// <summary> public Stream BaseStream { get; }
/// The <see cref="FileStream" /> that contains the executable represented by this instance public bool IsBigEndian { get; private set; }
/// </summary> public bool Recognized { get; private set; }
public Stream BaseStream { get; } public string Type { get; private set; }
public bool IsBigEndian { get; private set; }
/// <summary>
/// If true this instance correctly represents a Common Object File Format
/// </summary>
public bool Recognized { get; private set; }
public string Type { get; private set; }
void Initialize() void Initialize()
{ {

View File

@@ -31,10 +31,10 @@ namespace libexeinfo
/// <summary> /// <summary>
/// Linear Executable signature, "LE" /// Linear Executable signature, "LE"
/// </summary> /// </summary>
public const ushort Signature16 = 0x454C; const ushort SIGNATURE16 = 0x454C;
/// <summary> /// <summary>
/// Linear eXecutable signature, "LX" /// Linear eXecutable signature, "LX"
/// </summary> /// </summary>
public const ushort Signature = 0x584C; const ushort SIGNATURE = 0x584C;
} }
} }

View File

@@ -30,59 +30,67 @@ namespace libexeinfo
{ {
public partial class LX public partial class LX
{ {
public string Information => GetInfo(Header); public string Information => GetInfo(header);
public static string GetInfo(LXHeader header) static string GetInfo(LXHeader header)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if(header.signature == Signature16) sb.AppendLine("Linear Executable (LE):"); sb.AppendLine(header.signature == SIGNATURE16 ? "Linear Executable (LE):" : "Linear eXecutable (LX):");
else sb.AppendLine("Linear eXecutable (LX):");
if(header.os_type == TargetOS.OS2) switch(header.os_type)
{ {
sb.AppendLine("\tOS/2 application"); case TargetOS.OS2:
if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && sb.AppendLine("\tOS/2 application");
!header.module_flags.HasFlag(ModuleFlags.PMCompatible)) if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
sb.AppendLine("\tApplication is full screen, unaware of Presentation Manager"); !header.module_flags.HasFlag(ModuleFlags.PMCompatible))
else if(!header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && sb.AppendLine("\tApplication is full screen, unaware of Presentation Manager");
header.module_flags.HasFlag(ModuleFlags.PMCompatible)) else if(!header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
sb.AppendLine("\tApplication is aware of Presentation Manager, but doesn't use it"); header.module_flags.HasFlag(ModuleFlags.PMCompatible))
else if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && sb.AppendLine("\tApplication is aware of Presentation Manager, but doesn't use it");
header.module_flags.HasFlag(ModuleFlags.PMCompatible)) else if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
sb.AppendLine("\tApplication uses Presentation Manager"); header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication uses Presentation Manager");
break;
case TargetOS.Windows:
case TargetOS.Win32:
case TargetOS.Unknown:
switch(header.os_type)
{
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.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
!header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication is full screen, unaware of Windows");
else if(!header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication is aware of Windows, but doesn't use it");
else if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication uses Windows");
break;
case TargetOS.DOS:
sb.AppendLine("\tDOS application");
if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
!header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication is full screen, unaware of Windows");
else if(!header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication is aware of Windows, but doesn't use it");
else if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication uses Windows");
break;
default:
sb.AppendFormat("\tApplication for unknown OS {0}", (ushort)header.os_type).AppendLine();
break;
} }
else if(header.os_type == TargetOS.Windows || header.os_type == TargetOS.Win32 ||
header.os_type == TargetOS.Unknown)
{
if(header.os_type == TargetOS.Windows || header.os_type == TargetOS.Unknown)
sb.AppendLine("\t16-bit Windows application");
else if(header.os_type == TargetOS.Win32)
sb.AppendLine("\t32-bit Windows application");
if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
!header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication is full screen, unaware of Windows");
else if(!header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication is aware of Windows, but doesn't use it");
else if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication uses Windows");
}
else if(header.os_type == TargetOS.DOS)
{
sb.AppendLine("\tDOS application");
if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
!header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication is full screen, unaware of Windows");
else if(!header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication is aware of Windows, but doesn't use it");
else if(header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
header.module_flags.HasFlag(ModuleFlags.PMCompatible))
sb.AppendLine("\tApplication uses Windows");
}
else
sb.AppendFormat("\tApplication for unknown OS {0}", (ushort)header.os_type).AppendLine();
sb.AppendFormat("\tByte ordering: {0}", header.byte_order == 1 ? "Big-endian" : "Little-Endian") sb.AppendFormat("\tByte ordering: {0}", header.byte_order == 1 ? "Big-endian" : "Little-Endian")
.AppendLine(); .AppendLine();

View File

@@ -30,127 +30,124 @@ using System.Runtime.InteropServices;
namespace libexeinfo namespace libexeinfo
{ {
/// <summary> /// <summary>
/// Represents a Microsoft/IBM Linear EXecutable /// Represents a Microsoft/IBM Linear EXecutable
/// </summary> /// </summary>
// TODO: Big-endian (really needed?) // TODO: Big-endian (really needed?)
public partial class LX : IExecutable public partial class LX : IExecutable
{ {
MZ BaseExecutable; MZ baseExecutable;
/// <summary> /// <summary>
/// The <see cref="FileStream" /> that contains the executable represented by this instance /// Header for this executable
/// </summary> /// </summary>
public Stream BaseStream { get; } LXHeader header;
public bool IsBigEndian => false;
/// <summary>
/// Header for this executable
/// </summary>
LXHeader Header;
/// <summary>
/// If true this instance correctly represents a Microsoft/IBM Linear EXecutable
/// </summary>
public bool Recognized { get; private set;}
public string Type { get; private set;}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:libexeinfo.NE" /> class. /// Initializes a new instance of the <see cref="T:libexeinfo.NE" /> class.
/// </summary> /// </summary>
/// <param name="path">Executable path.</param> /// <param name="path">Executable path.</param>
public LX(string path) public LX(string path)
{ {
BaseStream = File.Open(path, FileMode.Open, FileAccess.Read); BaseStream = File.Open(path, FileMode.Open, FileAccess.Read);
Initialize(); Initialize();
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:libexeinfo.NE" /> class. /// Initializes a new instance of the <see cref="T:libexeinfo.NE" /> class.
/// </summary> /// </summary>
/// <param name="stream">Stream containing the executable.</param> /// <param name="stream">Stream containing the executable.</param>
public LX(Stream stream) public LX(Stream stream)
{ {
BaseStream = stream; BaseStream = stream;
Initialize(); Initialize();
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:libexeinfo.NE" /> class. /// Initializes a new instance of the <see cref="T:libexeinfo.NE" /> class.
/// </summary> /// </summary>
/// <param name="data">Byte array containing the executable.</param> /// <param name="data">Byte array containing the executable.</param>
public LX(byte[] data) public LX(byte[] data)
{
BaseStream = new MemoryStream(data);
Initialize();
}
void Initialize()
{
Recognized = false;
if(BaseStream == null) return;
BaseExecutable = new MZ(BaseStream);
if(!BaseExecutable.Recognized) return;
if(BaseExecutable.Header.new_offset >= BaseStream.Length) return;
BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
Header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader));
Marshal.FreeHGlobal(hdrPtr);
Recognized = Header.signature == Signature || Header.signature == Signature16;
if(!Recognized) return;
Type = Header.signature == Signature16 ? "Linear Executable (LE)" : "Linear eXecutable (LX)";
}
/// <summary>
/// Identifies if the specified executable is a Microsoft/IBM Linear EXecutable
/// </summary>
/// <returns><c>true</c> if the specified executable is a Microsoft/IBM Linear EXecutable, <c>false</c> otherwise.</returns>
/// <param name="path">Executable path.</param>
public static bool Identify(string path)
{ {
FileStream BaseStream = File.Open(path, FileMode.Open, FileAccess.Read); BaseStream = new MemoryStream(data);
MZ BaseExecutable = new MZ(BaseStream); Initialize();
if(!BaseExecutable.Recognized) return false;
if(BaseExecutable.Header.new_offset >= BaseStream.Length) return false;
BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
LXHeader Header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader));
Marshal.FreeHGlobal(hdrPtr);
return Header.signature == Signature || Header.signature == Signature16;
} }
/// <summary> /// <summary>
/// Identifies if the specified executable is a Microsoft/IBM Linear EXecutable /// The <see cref="FileStream" /> that contains the executable represented by this instance
/// </summary> /// </summary>
/// <returns><c>true</c> if the specified executable is a Microsoft/IBM Linear EXecutable, <c>false</c> otherwise.</returns> public Stream BaseStream { get; }
/// <param name="stream">Stream containing the executable.</param> public bool IsBigEndian => false;
public static bool Identify(FileStream stream) public bool Recognized { get; private set; }
public string Type { get; private set; }
void Initialize()
{ {
FileStream BaseStream = stream; Recognized = false;
MZ BaseExecutable = new MZ(BaseStream); if(BaseStream == null) return;
if(!BaseExecutable.Recognized) return false;
if(BaseExecutable.Header.new_offset >= BaseStream.Length) return false; baseExecutable = new MZ(BaseStream);
if(!baseExecutable.Recognized) return;
BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin); if(baseExecutable.Header.new_offset >= BaseStream.Length) return;
byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
LXHeader Header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader));
Marshal.FreeHGlobal(hdrPtr);
return Header.signature == Signature || Header.signature == Signature16;
BaseStream.Seek(baseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))];
BaseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader));
Marshal.FreeHGlobal(hdrPtr);
Recognized = header.signature == SIGNATURE || header.signature == SIGNATURE16;
if(!Recognized) return;
Type = header.signature == SIGNATURE16 ? "Linear Executable (LE)" : "Linear eXecutable (LX)";
}
/// <summary>
/// Identifies if the specified executable is a Microsoft/IBM Linear EXecutable
/// </summary>
/// <returns><c>true</c> if the specified executable is a Microsoft/IBM Linear EXecutable, <c>false</c> otherwise.</returns>
/// <param name="path">Executable path.</param>
public static bool Identify(string path)
{
FileStream baseStream = File.Open(path, FileMode.Open, FileAccess.Read);
MZ baseExecutable = new MZ(baseStream);
if(!baseExecutable.Recognized) return false;
if(baseExecutable.Header.new_offset >= baseStream.Length) return false;
baseStream.Seek(baseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))];
baseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
LXHeader header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader));
Marshal.FreeHGlobal(hdrPtr);
return header.signature == SIGNATURE || header.signature == SIGNATURE16;
}
/// <summary>
/// Identifies if the specified executable is a Microsoft/IBM Linear EXecutable
/// </summary>
/// <returns><c>true</c> if the specified executable is a Microsoft/IBM Linear EXecutable, <c>false</c> otherwise.</returns>
/// <param name="stream">Stream containing the executable.</param>
public static bool Identify(FileStream stream)
{
FileStream baseStream = stream;
MZ baseExecutable = new MZ(baseStream);
if(!baseExecutable.Recognized) return false;
if(baseExecutable.Header.new_offset >= baseStream.Length) return false;
baseStream.Seek(baseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))];
baseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
LXHeader header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader));
Marshal.FreeHGlobal(hdrPtr);
return header.signature == SIGNATURE || header.signature == SIGNATURE16;
} }
} }
} }

View File

@@ -31,6 +31,6 @@ namespace libexeinfo
/// <summary> /// <summary>
/// MZ executable signature, "MZ" /// MZ executable signature, "MZ"
/// </summary> /// </summary>
public const ushort Signature = 0x5A4D; const ushort SIGNATURE = 0x5A4D;
} }
} }

View File

@@ -41,7 +41,7 @@ namespace libexeinfo
/// </summary> /// </summary>
/// <returns>Human readable information for given MZ header.</returns> /// <returns>Human readable information for given MZ header.</returns>
/// <param name="header">MZ executable header.</param> /// <param name="header">MZ executable header.</param>
public static string GetInfo(MZHeader header) static string GetInfo(MZHeader header)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.AppendLine("DOS MZ executable:"); sb.AppendLine("DOS MZ executable:");

View File

@@ -94,7 +94,7 @@ namespace libexeinfo
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
Header = (MZHeader)Marshal.PtrToStructure(hdrPtr, typeof(MZHeader)); Header = (MZHeader)Marshal.PtrToStructure(hdrPtr, typeof(MZHeader));
Marshal.FreeHGlobal(hdrPtr); Marshal.FreeHGlobal(hdrPtr);
Recognized = Header.signature == Signature; Recognized = Header.signature == SIGNATURE;
if(!Recognized) return; if(!Recognized) return;
@@ -128,7 +128,7 @@ namespace libexeinfo
MZHeader mzHdr = (MZHeader)Marshal.PtrToStructure(hdrPtr, typeof(MZHeader)); MZHeader mzHdr = (MZHeader)Marshal.PtrToStructure(hdrPtr, typeof(MZHeader));
Marshal.FreeHGlobal(hdrPtr); Marshal.FreeHGlobal(hdrPtr);
return mzHdr.signature == Signature; return mzHdr.signature == SIGNATURE;
} }
} }
} }

View File

@@ -31,15 +31,15 @@ namespace libexeinfo
/// <summary> /// <summary>
/// New Executable signature, "NE" /// New Executable signature, "NE"
/// </summary> /// </summary>
public const ushort Signature = 0x454E; const ushort SIGNATURE = 0x454E;
/// <summary> /// <summary>
/// Signature for a <see cref="FixedFileInfo" /> /// Signature for a <see cref="FixedFileInfo" />
/// </summary> /// </summary>
public static readonly string FixedFileInfoSig = "VS_VERSION_INFO"; const string FIXED_FILE_INFO_SIG = "VS_VERSION_INFO";
/// <summary> /// <summary>
/// Signature for list of name=value strings inside a version resource /// Signature for list of name=value strings inside a version resource
/// </summary> /// </summary>
public static readonly string StringFileInfo = "StringFileInfo"; const string STRING_FILE_INFO = "StringFileInfo";
/// <summary> /// <summary>
/// Gets the name of a resource type according to its identifier /// Gets the name of a resource type according to its identifier
@@ -76,7 +76,7 @@ namespace libexeinfo
case (int)ResourceTypes.RT_TOOLBAR: return "RT_TOOLBAR"; case (int)ResourceTypes.RT_TOOLBAR: return "RT_TOOLBAR";
case (int)ResourceTypes.RT_VERSION: return "RT_VERSION"; case (int)ResourceTypes.RT_VERSION: return "RT_VERSION";
case (int)ResourceTypes.RT_VXD: return "RT_VXD"; case (int)ResourceTypes.RT_VXD: return "RT_VXD";
default: return string.Format("{0}", id & 0x7FFF); default: return $"{id & 0x7FFF}";
} }
} }
} }

View File

@@ -73,16 +73,10 @@ namespace libexeinfo
Initialize(); Initialize();
} }
/// <summary>
/// The <see cref="FileStream" /> that contains the executable represented by this instance
/// </summary>
public Stream BaseStream { get; } public Stream BaseStream { get; }
public bool IsBigEndian => false; public bool IsBigEndian => false;
/// <summary> public bool Recognized { get; private set; }
/// If true this instance correctly represents a Microsoft New Executable public string Type { get; private set; }
/// </summary>
public bool Recognized { get; private set; }
public string Type { get; }
void Initialize() void Initialize()
{ {
@@ -102,9 +96,10 @@ namespace libexeinfo
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
Header = (NEHeader)Marshal.PtrToStructure(hdrPtr, typeof(NEHeader)); Header = (NEHeader)Marshal.PtrToStructure(hdrPtr, typeof(NEHeader));
Marshal.FreeHGlobal(hdrPtr); Marshal.FreeHGlobal(hdrPtr);
if(Header.signature != Signature) return; if(Header.signature != SIGNATURE) return;
Recognized = true; Recognized = true;
Type = "New Executable (NE)";
if(Header.resource_entries <= 0) return; if(Header.resource_entries <= 0) return;
Resources = GetResources(BaseStream, BaseExecutable.Header.new_offset, Header.resource_table_offset); Resources = GetResources(BaseStream, BaseExecutable.Header.new_offset, Header.resource_table_offset);
@@ -131,7 +126,7 @@ namespace libexeinfo
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
NEHeader Header = (NEHeader)Marshal.PtrToStructure(hdrPtr, typeof(NEHeader)); NEHeader Header = (NEHeader)Marshal.PtrToStructure(hdrPtr, typeof(NEHeader));
Marshal.FreeHGlobal(hdrPtr); Marshal.FreeHGlobal(hdrPtr);
return Header.signature == Signature; return Header.signature == SIGNATURE;
} }
/// <summary> /// <summary>
@@ -154,7 +149,7 @@ namespace libexeinfo
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
NEHeader Header = (NEHeader)Marshal.PtrToStructure(hdrPtr, typeof(NEHeader)); NEHeader Header = (NEHeader)Marshal.PtrToStructure(hdrPtr, typeof(NEHeader));
Marshal.FreeHGlobal(hdrPtr); Marshal.FreeHGlobal(hdrPtr);
return Header.signature == Signature; return Header.signature == SIGNATURE;
} }
} }
} }

View File

@@ -27,6 +27,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@@ -40,17 +41,10 @@ namespace libexeinfo
/// <returns>The decoded version resources.</returns> /// <returns>The decoded version resources.</returns>
public List<Version> GetVersions() public List<Version> GetVersions()
{ {
List<Version> versions = new List<Version>(); return (from type in Resources.types
where (type.id & 0x7FFF) == (int)ResourceTypes.RT_VERSION
foreach(ResourceType type in Resources.types) from resource in type.resources
if((type.id & 0x7FFF) == (int)ResourceTypes.RT_VERSION) select new Version(resource.data, resource.name)).ToList();
foreach(Resource resource in type.resources)
{
Version vers = new Version(resource.data, resource.name);
versions.Add(vers);
}
return versions;
} }
/// <summary> /// <summary>
@@ -129,7 +123,7 @@ namespace libexeinfo
/// <value>The resource name.</value> /// <value>The resource name.</value>
public string Name { get; } public string Name { get; }
VersionNode GetNode(byte[] data, int startPosition, out int nodeLength) static VersionNode GetNode(byte[] data, int startPosition, out int nodeLength)
{ {
nodeLength = 0; nodeLength = 0;
@@ -172,21 +166,17 @@ namespace libexeinfo
void DecodeNode(VersionNode node, string parent, string grandparent) void DecodeNode(VersionNode node, string parent, string grandparent)
{ {
if(node.szName == FixedFileInfoSig) if(node.szName == FIXED_FILE_INFO_SIG)
{ {
IntPtr infoPtr = Marshal.AllocHGlobal(node.cbData); IntPtr infoPtr = Marshal.AllocHGlobal(node.cbData);
Marshal.Copy(node.rgbData, 0, infoPtr, node.cbData); Marshal.Copy(node.rgbData, 0, infoPtr, node.cbData);
FixedFileInfo info = (FixedFileInfo)Marshal.PtrToStructure(infoPtr, typeof(FixedFileInfo)); FixedFileInfo info = (FixedFileInfo)Marshal.PtrToStructure(infoPtr, typeof(FixedFileInfo));
Marshal.FreeHGlobal(infoPtr); Marshal.FreeHGlobal(infoPtr);
FileVersion = string.Format("{0}.{1:D2}.{2}.{3}", (info.dwFileVersionMS & 0xFFFF0000) >> 16, FileVersion =
info.dwFileVersionMS & 0xFFFF, $"{(info.dwFileVersionMS & 0xFFFF0000) >> 16}.{info.dwFileVersionMS & 0xFFFF:D2}.{(info.dwFileVersionLS & 0xFFFF0000) >> 16}.{info.dwFileVersionLS & 0xFFFF}";
(info.dwFileVersionLS & 0xFFFF0000) >> 16, ProductVersion =
info.dwFileVersionLS & 0xFFFF); $"{(info.dwProductVersionMS & 0xFFFF0000) >> 16}.{info.dwProductVersionMS & 0xFFFF:D2}.{(info.dwProductVersionLS & 0xFFFF0000) >> 16}.{info.dwProductVersionLS & 0xFFFF}";
ProductVersion = string.Format("{0}.{1:D2}.{2}.{3}", (info.dwProductVersionMS & 0xFFFF0000) >> 16,
info.dwProductVersionMS & 0xFFFF,
(info.dwProductVersionLS & 0xFFFF0000) >> 16,
info.dwProductVersionLS & 0xFFFF);
FileFlags = FileFlags =
(VersionFileFlags)(info.dwFileFlags & info.dwFileFlagsMask); (VersionFileFlags)(info.dwFileFlags & info.dwFileFlagsMask);
FileOS = (VersionFileOS)info.dwFileOS; FileOS = (VersionFileOS)info.dwFileOS;
@@ -195,13 +185,13 @@ namespace libexeinfo
FileDate = DateTime.FromFileTime(info.dwFileDateMS * 0x100000000 + info.dwFileDateLS); FileDate = DateTime.FromFileTime(info.dwFileDateMS * 0x100000000 + info.dwFileDateLS);
} }
if(parent == StringFileInfo) if(parent == STRING_FILE_INFO)
{ {
Dictionary<string, string> strings = new Dictionary<string, string>(); Dictionary<string, string> strings = new Dictionary<string, string>();
StringsByLanguage.Add(node.szName, strings); StringsByLanguage.Add(node.szName, strings);
} }
if(grandparent == StringFileInfo) if(grandparent == STRING_FILE_INFO)
if(StringsByLanguage.TryGetValue(parent, out Dictionary<string, string> strings)) if(StringsByLanguage.TryGetValue(parent, out Dictionary<string, string> strings))
{ {
Encoding encoding; Encoding encoding;
@@ -212,9 +202,9 @@ namespace libexeinfo
strings.Add(node.szName, encoding.GetString(node.rgbData)); strings.Add(node.szName, encoding.GetString(node.rgbData));
} }
if(node.children != null) if(node.children == null) return;
for(int i = 0; i < node.children.Length; i++)
DecodeNode(node.children[i], node.szName, parent); foreach(VersionNode n in node.children) DecodeNode(n, node.szName, parent);
} }
/// <summary> /// <summary>
@@ -235,7 +225,7 @@ namespace libexeinfo
case VersionFileType.VFT_STATIC_LIB: return "Static-link library"; case VersionFileType.VFT_STATIC_LIB: return "Static-link library";
case VersionFileType.VFT_UNKNOWN: return "Unknown"; case VersionFileType.VFT_UNKNOWN: return "Unknown";
case VersionFileType.VFT_VXD: return "Virtual device"; case VersionFileType.VFT_VXD: return "Virtual device";
default: return string.Format("Unknown type code {0}", (uint)type); default: return $"Unknown type code {(uint)type}";
} }
} }
@@ -263,7 +253,7 @@ namespace libexeinfo
case VersionFileSubtype.VFT2_DRV_VERSIONED_PRINTER: return "Versioned"; case VersionFileSubtype.VFT2_DRV_VERSIONED_PRINTER: return "Versioned";
case VersionFileSubtype.VFT2_UNKNOWN: return "Unknown"; case VersionFileSubtype.VFT2_UNKNOWN: return "Unknown";
default: default:
return string.Format("Unknown type code {0}", (uint)subtype); return $"Unknown type code {(uint)subtype}";
} }
} }
@@ -283,7 +273,7 @@ namespace libexeinfo
case VersionFileSubtype.VFT2_FONT_VECTOR: return "Vector"; case VersionFileSubtype.VFT2_FONT_VECTOR: return "Vector";
case VersionFileSubtype.VFT2_UNKNOWN: return "Unknown"; case VersionFileSubtype.VFT2_UNKNOWN: return "Unknown";
default: default:
return string.Format("Unknown type code {0}", (uint)subtype); return $"Unknown type code {(uint)subtype}";
} }
} }
@@ -330,7 +320,7 @@ namespace libexeinfo
return "16-bit Presentation Manager running under 32-bit OS/2"; return "16-bit Presentation Manager running under 32-bit OS/2";
case VersionFileOS.VOS_OS232_PM32: case VersionFileOS.VOS_OS232_PM32:
return "32-bit Presentation Manager running under 32-bit OS/2"; return "32-bit Presentation Manager running under 32-bit OS/2";
default: return string.Format("Unknown OS code {0}", (uint)os); default: return $"Unknown OS code {(uint)os}";
} }
} }
} }

View File

@@ -31,8 +31,8 @@ namespace libexeinfo
/// <summary> /// <summary>
/// Portable Executable signature, "PE\0\0" /// Portable Executable signature, "PE\0\0"
/// </summary> /// </summary>
public const ushort Signature = 0x00004550; const ushort SIGNATURE = 0x00004550;
public const ushort PE32 = COFF.ZMAGIC; const ushort PE32 = COFF.ZMAGIC;
public const ushort PE32Plus = 0x20b; internal const ushort PE32Plus = 0x20b;
} }
} }

View File

@@ -25,6 +25,7 @@
// THE SOFTWARE. // THE SOFTWARE.
using System; using System;
// ReSharper disable InconsistentNaming
namespace libexeinfo namespace libexeinfo
{ {

View File

@@ -32,7 +32,7 @@ namespace libexeinfo
{ {
public string Information => GetInfo(Header, WinHeader); public string Information => GetInfo(Header, WinHeader);
public static string GetInfo(PEHeader header, WindowsHeader64 winheader) static string GetInfo(PEHeader header, WindowsHeader64 winheader)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append(COFF.GetInfo(header.coff)); sb.Append(COFF.GetInfo(header.coff));

View File

@@ -72,16 +72,10 @@ namespace libexeinfo
Initialize(); Initialize();
} }
/// <summary>
/// The <see cref="FileStream" /> that contains the executable represented by this instance
/// </summary>
public Stream BaseStream { get; } public Stream BaseStream { get; }
public bool IsBigEndian => false; public bool IsBigEndian => false;
/// <summary> public bool Recognized { get; private set; }
/// If true this instance correctly represents a Microsoft Portable Executable public string Type { get; private set; }
/// </summary>
public bool Recognized { get; private set; }
public string Type { get; private set; }
void Initialize() void Initialize()
{ {
@@ -100,7 +94,7 @@ namespace libexeinfo
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
Header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader)); Header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));
Marshal.FreeHGlobal(hdrPtr); Marshal.FreeHGlobal(hdrPtr);
Recognized = Header.signature == Signature; Recognized = Header.signature == SIGNATURE;
if(!Recognized) return; if(!Recognized) return;
@@ -135,20 +129,20 @@ namespace libexeinfo
/// <param name="path">Executable path.</param> /// <param name="path">Executable path.</param>
public static bool Identify(string path) public static bool Identify(string path)
{ {
FileStream BaseStream = File.Open(path, FileMode.Open, FileAccess.Read); FileStream baseStream = File.Open(path, FileMode.Open, FileAccess.Read);
MZ BaseExecutable = new MZ(BaseStream); MZ baseExecutable = new MZ(baseStream);
if(!BaseExecutable.Recognized) return false; if(!baseExecutable.Recognized) return false;
if(BaseExecutable.Header.new_offset >= BaseStream.Length) return false; if(baseExecutable.Header.new_offset >= baseStream.Length) return false;
BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin); baseStream.Seek(baseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))]; byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
BaseStream.Read(buffer, 0, buffer.Length); baseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length); IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
PEHeader Header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader)); PEHeader header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));
Marshal.FreeHGlobal(hdrPtr); Marshal.FreeHGlobal(hdrPtr);
return Header.signature == Signature; return header.signature == SIGNATURE;
} }
/// <summary> /// <summary>
@@ -158,20 +152,20 @@ namespace libexeinfo
/// <param name="stream">Stream containing the executable.</param> /// <param name="stream">Stream containing the executable.</param>
public static bool Identify(FileStream stream) public static bool Identify(FileStream stream)
{ {
FileStream BaseStream = stream; FileStream baseStream = stream;
MZ BaseExecutable = new MZ(BaseStream); MZ baseExecutable = new MZ(baseStream);
if(!BaseExecutable.Recognized) return false; if(!baseExecutable.Recognized) return false;
if(BaseExecutable.Header.new_offset >= BaseStream.Length) return false; if(baseExecutable.Header.new_offset >= baseStream.Length) return false;
BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin); baseStream.Seek(baseExecutable.Header.new_offset, SeekOrigin.Begin);
byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))]; byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
BaseStream.Read(buffer, 0, buffer.Length); baseStream.Read(buffer, 0, buffer.Length);
IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length); IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
PEHeader Header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader)); PEHeader header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));
Marshal.FreeHGlobal(hdrPtr); Marshal.FreeHGlobal(hdrPtr);
return Header.signature == Signature; return header.signature == SIGNATURE;
} }
static WindowsHeader64 ToPlus(WindowsHeader header) static WindowsHeader64 ToPlus(WindowsHeader header)

View File

@@ -28,7 +28,7 @@ namespace libexeinfo
{ {
public partial class PE public partial class PE
{ {
public static string SubsystemToString(Subsystems subsystem) static string SubsystemToString(Subsystems subsystem)
{ {
switch(subsystem) switch(subsystem)
{ {