Added support for NE version resources.

This commit is contained in:
2017-10-03 20:36:07 +01:00
parent 1ab0c652b4
commit 0dafcd268e
8 changed files with 913 additions and 407 deletions

View File

@@ -1,403 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Collections.Generic;
using System.Text;
namespace exeinfo
{
public static class NE
{
public const ushort Signature = 0x454E;
//[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct Header
{
public ushort signature;
public byte linker_major;
public byte linker_minor;
public ushort entry_table_offset;
public ushort entry_table_length;
public uint crc;
public ProgramFlags program_flags;
public ApplicationFlags application_flags;
public byte auto_data_segment_index;
public ushort initial_heap;
public ushort initial_stack;
public uint entry_point;
public uint stack_pointer;
public ushort segment_count;
public ushort reference_count;
public ushort nonresident_table_size;
public ushort segment_table_offset;
public ushort resource_table_offset;
public ushort resident_names_offset;
public ushort module_reference_offset;
public ushort imported_names_offset;
public uint nonresident_names_offset;
public ushort movable_entries;
public ushort alignment_shift;
public ushort resource_entries;
public TargetOS target_os;
public OS2Flags os2_flags;
public ushort return_thunks_offset;
public ushort segment_reference_thunks;
public ushort minimum_swap_area;
public byte os_minor;
public byte os_major;
}
[Flags]
public enum ProgramFlags : byte
{
NoDGroup = 0,
SingleDGroup = 1,
MultipleDGroup = 2,
GlobalInit = 1 << 2,
ProtectedMode = 1 << 3,
i86 = 1 << 4,
i286 = 1 << 5,
i386 = 1 << 6,
i87 = 1 << 7
}
public enum TargetOS : byte
{
Unknown = 0,
OS2 = 1,
Windows = 2,
DOS = 3,
Win32 = 4,
Borland = 5
}
[Flags]
public enum ApplicationFlags : byte
{
FullScreen = 1,
GUICompatible = 2,
Errors = 1 << 5,
NonConforming = 1 << 6,
DLL = 1 << 7
}
[Flags]
public enum OS2Flags : byte
{
LongFilename = 1 << 0,
ProtectedMode2 = 1 << 1,
ProportionalFonts = 1 << 2,
GangloadArea = 1 << 3,
}
public struct ResourceTable
{
public ushort alignment_shift;
public ResourceType[] types;
}
public struct ResourceType
{
public ushort id;
public ushort count;
public uint reserved;
public Resource[] resources;
// Not sequentially stored
public string name;
}
public struct Resource
{
public ushort dataOffset;
public ushort length;
public ResourceFlags flags;
public ushort id;
public uint reserved;
// Not sequentially stored
public string name;
public byte[] data;
}
[Flags]
public enum ResourceFlags : ushort
{
Moveable = 0x10,
Pure = 0x20,
Preload = 0x40
}
public static void PrintInfo(Header header)
{
Console.WriteLine("New Executable (NE):");
Console.WriteLine("\tFile's CRC: 0x{0:X8}", header.crc);
Console.WriteLine("\tLinker version: {0}.{1}", header.linker_major, header.linker_minor);
if (header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && !header.program_flags.HasFlag(ProgramFlags.MultipleDGroup))
Console.WriteLine("\tApplication uses a single shared DGroup");
else if (!header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && header.program_flags.HasFlag(ProgramFlags.MultipleDGroup))
Console.WriteLine("\tApplication uses a multiple DGroup");
else if (header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && header.program_flags.HasFlag(ProgramFlags.MultipleDGroup))
Console.WriteLine("\tApplication indicates an incorrect DGroup value");
else if (!header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && !header.program_flags.HasFlag(ProgramFlags.MultipleDGroup))
Console.WriteLine("\tApplication does not use DGroup");
if (header.program_flags.HasFlag(ProgramFlags.GlobalInit))
Console.WriteLine("\tApplication uses global initialization");
if (header.program_flags.HasFlag(ProgramFlags.ProtectedMode))
Console.WriteLine("\tApplication uses protected mode");
if (header.program_flags.HasFlag(ProgramFlags.i86))
Console.WriteLine("\tApplication uses 8086 instructions");
if (header.program_flags.HasFlag(ProgramFlags.i286))
Console.WriteLine("\tApplication uses 80286 instructions");
if (header.program_flags.HasFlag(ProgramFlags.i386))
Console.WriteLine("\tApplication uses 80386 instructions");
if (header.program_flags.HasFlag(ProgramFlags.i87))
Console.WriteLine("\tApplication uses floating point instructions");
if(header.target_os == TargetOS.OS2)
{
Console.WriteLine("\tOS/2 application");
Console.WriteLine("\tApplication requires OS/2 {0}.{1} to run", header.os_major, header.os_minor);
if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is full screen, unaware of Presentation Manager");
else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\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))
Console.WriteLine("\tApplication uses Presentation Manager");
if (header.os2_flags.HasFlag(OS2Flags.LongFilename))
Console.WriteLine("\tApplication supports long filenames");
if (header.os2_flags.HasFlag(OS2Flags.ProtectedMode2))
Console.WriteLine("\tApplication uses OS/2 2.x protected mode");
if (header.os2_flags.HasFlag(OS2Flags.ProportionalFonts))
Console.WriteLine("\tApplication uses OS/2 2.x proportional fonts");
if (header.os2_flags.HasFlag(OS2Flags.GangloadArea))
Console.WriteLine("\tGangload area starts at {0} an runs for {1} bytes", header.return_thunks_offset, header.segment_reference_thunks);
else
{
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
}
else if (header.target_os == TargetOS.Windows || header.target_os == TargetOS.Win32)
{
if (header.target_os == TargetOS.Windows)
Console.WriteLine("\t16-bit Windows application");
else if (header.target_os == TargetOS.Win32)
Console.WriteLine("\t32-bit Windows application");
Console.WriteLine("\tApplication requires Windows {0}.{1} to run", header.os_major, header.os_minor);
if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is full screen, unaware of Windows");
else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is aware of Windows, but doesn't use it");
else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication uses Windows");
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
else if (header.target_os == TargetOS.DOS)
{
Console.WriteLine("\tDOS application");
Console.WriteLine("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor);
if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is full screen, unaware of Windows");
else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is aware of Windows, but doesn't use it");
else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication uses Windows");
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
else if (header.target_os == TargetOS.Borland)
{
Console.WriteLine("\tBorland Operating System Services application");
Console.WriteLine("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor);
if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is full screen, unaware of Windows");
else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is aware of Windows, but doesn't use it");
else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication uses Windows");
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
else
{
Console.WriteLine("\tApplication for unknown OS {0}", (byte)header.target_os);
Console.WriteLine("\tApplication requires OS {0}.{1} to run", header.os_major, header.os_minor);
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
if (header.application_flags.HasFlag(ApplicationFlags.Errors))
Console.WriteLine("\tExecutable has errors");
if (header.application_flags.HasFlag(ApplicationFlags.NonConforming))
Console.WriteLine("\tExecutable is non conforming");
if (header.application_flags.HasFlag(ApplicationFlags.DLL))
Console.WriteLine("\tExecutable is a dynamic library or a driver");
Console.WriteLine("\tMinimum code swap area: {0} bytes", header.minimum_swap_area);
Console.WriteLine("\tFile alignment shift: {0}", 512 << header.alignment_shift);
Console.WriteLine("\tInitial local heap should be {0} bytes", header.initial_heap);
Console.WriteLine("\tInitial stack size should be {0} bytes", header.initial_stack);
Console.WriteLine("\tCS:IP entry point: {0:X4}:{1:X4}", (header.entry_point & 0xFFFF0000) >> 16, header.entry_point & 0xFFFF);
if (!header.application_flags.HasFlag(ApplicationFlags.DLL))
Console.WriteLine("\tSS:SP initial stack pointer: {0:X4}:{1:X4}", (header.stack_pointer & 0xFFFF0000) >> 16, header.stack_pointer & 0xFFFF);
Console.WriteLine("\tEntry table starts at {0} and runs for {1} bytes", header.entry_table_offset, header.entry_table_length);
Console.WriteLine("\tSegment table starts at {0} and contain {1} segments", header.segment_table_offset, header.segment_count);
Console.WriteLine("\tModule reference table starts at {0} and contain {1} references", header.module_reference_offset, header.reference_count);
Console.WriteLine("\tNon-resident names table starts at {0} and runs for {1} bytes", header.nonresident_names_offset, header.nonresident_table_size);
Console.WriteLine("\tResources table starts at {0} and contains {1} entries", header.resource_table_offset, header.resource_entries);
Console.WriteLine("\tResident names table starts at {0}", header.resident_names_offset);
Console.WriteLine("\tImported names table starts at {0}", header.imported_names_offset);
}
public static ResourceTable GetResources(FileStream exeFs, uint neStart, ushort tableOff)
{
long oldPosition = exeFs.Position;
byte[] DW = new byte[2];
byte[] DD = new byte[4];
exeFs.Position = neStart + tableOff;
ResourceTable table = new ResourceTable();
exeFs.Read(DW, 0, 2);
table.alignment_shift = BitConverter.ToUInt16(DW, 0);
List<ResourceType> types = new List<ResourceType>();
while(true)
{
ResourceType type = new ResourceType();
exeFs.Read(DW, 0, 2);
type.id = BitConverter.ToUInt16(DW, 0);
if (type.id == 0)
break;
exeFs.Read(DW, 0, 2);
type.count = BitConverter.ToUInt16(DW, 0);
exeFs.Read(DD, 0, 4);
type.reserved = BitConverter.ToUInt32(DD, 0);
type.resources = new Resource[type.count];
for (int i = 0; i < type.count; i++)
{
type.resources[i] = new Resource();
exeFs.Read(DW, 0, 2);
type.resources[i].dataOffset = BitConverter.ToUInt16(DW, 0);
exeFs.Read(DW, 0, 2);
type.resources[i].length = BitConverter.ToUInt16(DW, 0);
exeFs.Read(DW, 0, 2);
type.resources[i].flags = (ResourceFlags)BitConverter.ToUInt16(DW, 0);
exeFs.Read(DW, 0, 2);
type.resources[i].id = BitConverter.ToUInt16(DW, 0);
exeFs.Read(DD, 0, 4);
type.resources[i].reserved = BitConverter.ToUInt32(DD, 0);
}
types.Add(type);
}
table.types = types.ToArray();
for (int t = 0; t < table.types.Length; t++)
{
if ((table.types[t].id & 0x8000) == 0)
{
byte len;
byte[] str;
exeFs.Position = neStart + tableOff + table.types[t].id;
len = (byte)exeFs.ReadByte();
str = new byte[len];
exeFs.Read(str, 0, len);
table.types[t].name = Encoding.ASCII.GetString(str);
}
else
table.types[t].name = IdToName(table.types[t].id);
for (int r = 0; r < table.types[t].resources.Length; r++)
{
if ((table.types[t].resources[r].id & 0x8000) == 0)
{
byte len;
byte[] str;
exeFs.Position = neStart + tableOff + table.types[t].resources[r].id;
len = (byte)exeFs.ReadByte();
str = new byte[len];
exeFs.Read(str, 0, len);
table.types[t].resources[r].name = Encoding.ASCII.GetString(str);
}
else
table.types[t].resources[r].name = string.Format("{0}", table.types[t].resources[r].id & 0x7FFF);
table.types[t].resources[r].data = new byte[table.types[t].resources[r].length * (1 << table.alignment_shift)];
exeFs.Position = table.types[t].resources[r].dataOffset * (1 <<table.alignment_shift);
exeFs.Read(table.types[t].resources[r].data, 0, table.types[t].resources[r].data.Length);
}
}
exeFs.Position = oldPosition;
return table;
}
public static string IdToName(ushort id)
{
switch(id & 0x7FFF)
{
case 9:
return "RT_ACCELERATOR";
case 21:
return "RT_ANICURSOR";
case 22:
return "RT_ANIICON";
case 2:
return "RT_BITMAP";
case 1:
return "RT_CURSOR";
case 5:
return "RT_DIALOG";
case 18:
return "RT_DIALOGEX";
case 17:
return "RT_DLGINCLUDE";
case 240:
return "RT_DLGINIT";
case 8:
return "RT_FONT";
case 7:
return "RT_FONTDIR";
case 12:
return "RT_GROUP_CURSOR";
case 14:
return "RT_GROUP_ICON";
case 23:
return "RT_HTML";
case 3:
return "RT_ICON";
case 24:
return "RT_MANIFEST";
case 4:
return "RT_MENU";
case 15:
return "RT_MENUEX";
case 11:
return "RT_MESSAGETABLE";
case 8194:
return "RT_NEWBITMAP";
case 19:
return "RT_PLUGPLAY";
case 10:
return "RT_RCDATA";
case 6:
return "RT_STRING";
case 241:
return "RT_TOOLBAR";
case 16:
return "RT_VERSION";
case 20:
return "RT_VXD";
default:
return string.Format("{0}", id & 0x7FFF);
}
}
}
}

72
exeinfo/NE/Consts.cs Normal file
View File

@@ -0,0 +1,72 @@
using System;
using System.ComponentModel;
namespace exeinfo.NE
{
public static class Consts
{
public const ushort Signature = 0x454E;
public static readonly string FixedFileInfo = "VS_VERSION_INFO";
public static readonly string StringFileInfo = "StringFileInfo";
public static string IdToName(ushort id)
{
switch (id & 0x7FFF)
{
case (int)ResourceTypes.RT_ACCELERATOR:
return "RT_ACCELERATOR";
case (int)ResourceTypes.RT_ANICURSOR:
return "RT_ANICURSOR";
case (int)ResourceTypes.RT_ANIICON:
return "RT_ANIICON";
case (int)ResourceTypes.RT_BITMAP:
return "RT_BITMAP";
case (int)ResourceTypes.RT_CURSOR:
return "RT_CURSOR";
case (int)ResourceTypes.RT_DIALOG:
return "RT_DIALOG";
case (int)ResourceTypes.RT_DIALOGEX:
return "RT_DIALOGEX";
case (int)ResourceTypes.RT_DLGINCLUDE:
return "RT_DLGINCLUDE";
case (int)ResourceTypes.RT_DLGINIT:
return "RT_DLGINIT";
case (int)ResourceTypes.RT_FONT:
return "RT_FONT";
case (int)ResourceTypes.RT_FONTDIR:
return "RT_FONTDIR";
case (int)ResourceTypes.RT_GROUP_CURSOR:
return "RT_GROUP_CURSOR";
case (int)ResourceTypes.RT_GROUP_ICON:
return "RT_GROUP_ICON";
case (int)ResourceTypes.RT_HTML:
return "RT_HTML";
case (int)ResourceTypes.RT_ICON:
return "RT_ICON";
case (int)ResourceTypes.RT_MANIFEST:
return "RT_MANIFEST";
case (int)ResourceTypes.RT_MENU:
return "RT_MENU";
case (int)ResourceTypes.RT_MENUEX:
return "RT_MENUEX";
case (int)ResourceTypes.RT_MESSAGETABLE:
return "RT_MESSAGETABLE";
case (int)ResourceTypes.RT_NEWBITMAP:
return "RT_NEWBITMAP";
case (int)ResourceTypes.RT_PLUGPLAY:
return "RT_PLUGPLAY";
case (int)ResourceTypes.RT_RCDATA:
return "RT_RCDATA";
case (int)ResourceTypes.RT_STRING:
return "RT_STRING";
case (int)ResourceTypes.RT_TOOLBAR:
return "RT_TOOLBAR";
case (int)ResourceTypes.RT_VERSION:
return "RT_VERSION";
case (int)ResourceTypes.RT_VXD:
return "RT_VXD";
default:
return string.Format("{0}", id & 0x7FFF);
}
}
}
}

160
exeinfo/NE/Enums.cs Normal file
View File

@@ -0,0 +1,160 @@
using System;
namespace exeinfo.NE
{
[Flags]
public enum ProgramFlags : byte
{
NoDGroup = 0,
SingleDGroup = 1,
MultipleDGroup = 2,
GlobalInit = 1 << 2,
ProtectedMode = 1 << 3,
i86 = 1 << 4,
i286 = 1 << 5,
i386 = 1 << 6,
i87 = 1 << 7
}
public enum TargetOS : byte
{
Unknown = 0,
OS2 = 1,
Windows = 2,
DOS = 3,
Win32 = 4,
Borland = 5
}
[Flags]
public enum ApplicationFlags : byte
{
FullScreen = 1,
GUICompatible = 2,
Errors = 1 << 5,
NonConforming = 1 << 6,
DLL = 1 << 7
}
[Flags]
public enum OS2Flags : byte
{
LongFilename = 1 << 0,
ProtectedMode2 = 1 << 1,
ProportionalFonts = 1 << 2,
GangloadArea = 1 << 3,
}
[Flags]
public enum ResourceFlags : ushort
{
Moveable = 0x10,
Pure = 0x20,
Preload = 0x40
}
public enum ResourceTypes : ushort
{
RT_ACCELERATOR = 9,
RT_ANICURSOR = 21,
RT_ANIICON = 22,
RT_BITMAP = 2,
RT_CURSOR = 1,
RT_DIALOG = 5,
RT_DIALOGEX = 18,
RT_DLGINCLUDE = 17,
RT_DLGINIT = 240,
RT_FONT = 8,
RT_FONTDIR = 7,
RT_GROUP_CURSOR = 12,
RT_GROUP_ICON = 13,
RT_HTML = 23,
RT_ICON = 3,
RT_MANIFEST = 24,
RT_MENU = 4,
RT_MENUEX = 15,
RT_MESSAGETABLE = 11,
RT_NEWBITMAP = RT_NEW | RT_BITMAP,
RT_PLUGPLAY = 19,
RT_RCDATA = 10,
RT_STRING = 6,
RT_TOOLBAR = 241,
RT_VERSION = 16,
RT_VXD = 20,
RT_NEW = 0x2000,
}
[Flags]
public enum VersionFileFlags : uint
{
VS_FF_DEBUG = 0x00000001,
VS_FF_INFOINFERRED = 0x00000010,
VS_FF_PATCHED = 0x00000004,
VS_FF_PRERELEASE = 0x00000002,
VS_FF_PRIVATEBUILD = 0x00000008,
VS_FF_SPECIALBUILD = 0x00000020,
}
public enum VersionFileOS : uint
{
VOS_DOS = 0x00010000,
VOS_NT = 0x00040000,
VOS_WINDOWS16 = 0x00000001,
VOS_WINDOWS32 = 0x00000004,
VOS_OS216 = 0x00020000,
VOS_OS232 = 0x00030000,
VOS_PM16 = 0x00000002,
VOS_PM32 = 0x00000003,
VOS_UNKNOWN = 0x00000000,
// Combinations, some have no sense
VOS_DOS_NT = 0x00050000,
VOS_DOS_WINDOWS16 = 0x00010001,
VOS_DOS_WINDOWS32 = 0x00010004,
VOS_DOS_PM16 = 0x00010002,
VOS_DOS_PM32 = 0x00010003,
VOS_NT_WINDOWS16 = 0x00040001,
VOS_NT_WINDOWS32 = 0x00040004,
VOS_NT_PM16 = 0x00040002,
VOS_NT_PM32 = 0x00040003,
VOS_OS216_WINDOWS16 = 0x00020001,
VOS_OS216_WINDOWS32 = 0x00020004,
VOS_OS216_PM16 = 0x00020002,
VOS_OS216_PM32 = 0x00020003,
VOS_OS232_WINDOWS16 = 0x00030001,
VOS_OS232_WINDOWS32 = 0x00030004,
VOS_OS232_PM16 = 0x00030002,
VOS_OS232_PM32 = 0x00030003,
}
public enum VersionFileType : uint
{
VFT_APP = 0x00000001,
VFT_DLL = 0x00000002,
VFT_DRV = 0x00000003,
VFT_FONT = 0x00000004,
VFT_STATIC_LIB = 0x00000007,
VFT_UNKNOWN = 0x00000000,
VFT_VXD = 0x00000005,
}
public enum VersionFileSubtype : uint
{
VFT2_UNKNOWN = 0x00000000,
// Drivers
VFT2_DRV_COMM = 0x0000000A,
VFT2_DRV_DISPLAY = 0x00000004,
VFT2_DRV_INSTALLABLE = 0x00000008,
VFT2_DRV_KEYBOARD = 0x00000002,
VFT2_DRV_LANGUAGE = 0x00000003,
VFT2_DRV_MOUSE = 0x00000005,
VFT2_DRV_NETWORK = 0x00000006,
VFT2_DRV_PRINTER = 0x00000001,
VFT2_DRV_SOUND = 0x00000009,
VFT2_DRV_SYSTEM = 0x00000007,
VFT2_DRV_VERSIONED_PRINTER = 0x0000000C,
// Fonts
VFT2_FONT_RASTER = 0x00000001,
VFT2_FONT_TRUETYPE = 0x00000003,
VFT2_FONT_VECTOR = 0x00000002,
}
}

221
exeinfo/NE/Info.cs Normal file
View File

@@ -0,0 +1,221 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace exeinfo.NE
{
public class Info
{
public static void PrintInfo(Header header)
{
Console.WriteLine("New Executable (NE):");
Console.WriteLine("\tFile's CRC: 0x{0:X8}", header.crc);
Console.WriteLine("\tLinker version: {0}.{1}", header.linker_major, header.linker_minor);
if (header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && !header.program_flags.HasFlag(ProgramFlags.MultipleDGroup))
Console.WriteLine("\tApplication uses a single shared DGroup");
else if (!header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && header.program_flags.HasFlag(ProgramFlags.MultipleDGroup))
Console.WriteLine("\tApplication uses a multiple DGroup");
else if (header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && header.program_flags.HasFlag(ProgramFlags.MultipleDGroup))
Console.WriteLine("\tApplication indicates an incorrect DGroup value");
else if (!header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && !header.program_flags.HasFlag(ProgramFlags.MultipleDGroup))
Console.WriteLine("\tApplication does not use DGroup");
if (header.program_flags.HasFlag(ProgramFlags.GlobalInit))
Console.WriteLine("\tApplication uses global initialization");
if (header.program_flags.HasFlag(ProgramFlags.ProtectedMode))
Console.WriteLine("\tApplication uses protected mode");
if (header.program_flags.HasFlag(ProgramFlags.i86))
Console.WriteLine("\tApplication uses 8086 instructions");
if (header.program_flags.HasFlag(ProgramFlags.i286))
Console.WriteLine("\tApplication uses 80286 instructions");
if (header.program_flags.HasFlag(ProgramFlags.i386))
Console.WriteLine("\tApplication uses 80386 instructions");
if (header.program_flags.HasFlag(ProgramFlags.i87))
Console.WriteLine("\tApplication uses floating point instructions");
if (header.target_os == TargetOS.OS2)
{
Console.WriteLine("\tOS/2 application");
Console.WriteLine("\tApplication requires OS/2 {0}.{1} to run", header.os_major, header.os_minor);
if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is full screen, unaware of Presentation Manager");
else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\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))
Console.WriteLine("\tApplication uses Presentation Manager");
if (header.os2_flags.HasFlag(OS2Flags.LongFilename))
Console.WriteLine("\tApplication supports long filenames");
if (header.os2_flags.HasFlag(OS2Flags.ProtectedMode2))
Console.WriteLine("\tApplication uses OS/2 2.x protected mode");
if (header.os2_flags.HasFlag(OS2Flags.ProportionalFonts))
Console.WriteLine("\tApplication uses OS/2 2.x proportional fonts");
if (header.os2_flags.HasFlag(OS2Flags.GangloadArea))
Console.WriteLine("\tGangload area starts at {0} an runs for {1} bytes", header.return_thunks_offset, header.segment_reference_thunks);
else
{
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
}
else if (header.target_os == TargetOS.Windows || header.target_os == TargetOS.Win32)
{
if (header.target_os == TargetOS.Windows)
Console.WriteLine("\t16-bit Windows application");
else if (header.target_os == TargetOS.Win32)
Console.WriteLine("\t32-bit Windows application");
Console.WriteLine("\tApplication requires Windows {0}.{1} to run", header.os_major, header.os_minor);
if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is full screen, unaware of Windows");
else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is aware of Windows, but doesn't use it");
else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication uses Windows");
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
else if (header.target_os == TargetOS.DOS)
{
Console.WriteLine("\tDOS application");
Console.WriteLine("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor);
if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is full screen, unaware of Windows");
else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is aware of Windows, but doesn't use it");
else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication uses Windows");
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
else if (header.target_os == TargetOS.Borland)
{
Console.WriteLine("\tBorland Operating System Services application");
Console.WriteLine("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor);
if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is full screen, unaware of Windows");
else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication is aware of Windows, but doesn't use it");
else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
Console.WriteLine("\tApplication uses Windows");
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
else
{
Console.WriteLine("\tApplication for unknown OS {0}", (byte)header.target_os);
Console.WriteLine("\tApplication requires OS {0}.{1} to run", header.os_major, header.os_minor);
Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset);
Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks);
}
if (header.application_flags.HasFlag(ApplicationFlags.Errors))
Console.WriteLine("\tExecutable has errors");
if (header.application_flags.HasFlag(ApplicationFlags.NonConforming))
Console.WriteLine("\tExecutable is non conforming");
if (header.application_flags.HasFlag(ApplicationFlags.DLL))
Console.WriteLine("\tExecutable is a dynamic library or a driver");
Console.WriteLine("\tMinimum code swap area: {0} bytes", header.minimum_swap_area);
Console.WriteLine("\tFile alignment shift: {0}", 512 << header.alignment_shift);
Console.WriteLine("\tInitial local heap should be {0} bytes", header.initial_heap);
Console.WriteLine("\tInitial stack size should be {0} bytes", header.initial_stack);
Console.WriteLine("\tCS:IP entry point: {0:X4}:{1:X4}", (header.entry_point & 0xFFFF0000) >> 16, header.entry_point & 0xFFFF);
if (!header.application_flags.HasFlag(ApplicationFlags.DLL))
Console.WriteLine("\tSS:SP initial stack pointer: {0:X4}:{1:X4}", (header.stack_pointer & 0xFFFF0000) >> 16, header.stack_pointer & 0xFFFF);
Console.WriteLine("\tEntry table starts at {0} and runs for {1} bytes", header.entry_table_offset, header.entry_table_length);
Console.WriteLine("\tSegment table starts at {0} and contain {1} segments", header.segment_table_offset, header.segment_count);
Console.WriteLine("\tModule reference table starts at {0} and contain {1} references", header.module_reference_offset, header.reference_count);
Console.WriteLine("\tNon-resident names table starts at {0} and runs for {1} bytes", header.nonresident_names_offset, header.nonresident_table_size);
Console.WriteLine("\tResources table starts at {0} and contains {1} entries", header.resource_table_offset, header.resource_entries);
Console.WriteLine("\tResident names table starts at {0}", header.resident_names_offset);
Console.WriteLine("\tImported names table starts at {0}", header.imported_names_offset);
}
public static ResourceTable GetResources(FileStream exeFs, uint neStart, ushort tableOff)
{
long oldPosition = exeFs.Position;
byte[] DW = new byte[2];
byte[] DD = new byte[4];
exeFs.Position = neStart + tableOff;
ResourceTable table = new ResourceTable();
exeFs.Read(DW, 0, 2);
table.alignment_shift = BitConverter.ToUInt16(DW, 0);
List<ResourceType> types = new List<ResourceType>();
while (true)
{
ResourceType type = new ResourceType();
exeFs.Read(DW, 0, 2);
type.id = BitConverter.ToUInt16(DW, 0);
if (type.id == 0)
break;
exeFs.Read(DW, 0, 2);
type.count = BitConverter.ToUInt16(DW, 0);
exeFs.Read(DD, 0, 4);
type.reserved = BitConverter.ToUInt32(DD, 0);
type.resources = new Resource[type.count];
for (int i = 0; i < type.count; i++)
{
type.resources[i] = new Resource();
exeFs.Read(DW, 0, 2);
type.resources[i].dataOffset = BitConverter.ToUInt16(DW, 0);
exeFs.Read(DW, 0, 2);
type.resources[i].length = BitConverter.ToUInt16(DW, 0);
exeFs.Read(DW, 0, 2);
type.resources[i].flags = (ResourceFlags)BitConverter.ToUInt16(DW, 0);
exeFs.Read(DW, 0, 2);
type.resources[i].id = BitConverter.ToUInt16(DW, 0);
exeFs.Read(DD, 0, 4);
type.resources[i].reserved = BitConverter.ToUInt32(DD, 0);
}
types.Add(type);
}
table.types = types.ToArray();
for (int t = 0; t < table.types.Length; t++)
{
if ((table.types[t].id & 0x8000) == 0)
{
byte len;
byte[] str;
exeFs.Position = neStart + tableOff + table.types[t].id;
len = (byte)exeFs.ReadByte();
str = new byte[len];
exeFs.Read(str, 0, len);
table.types[t].name = Encoding.ASCII.GetString(str);
}
else
table.types[t].name = Consts.IdToName(table.types[t].id);
for (int r = 0; r < table.types[t].resources.Length; r++)
{
if ((table.types[t].resources[r].id & 0x8000) == 0)
{
byte len;
byte[] str;
exeFs.Position = neStart + tableOff + table.types[t].resources[r].id;
len = (byte)exeFs.ReadByte();
str = new byte[len];
exeFs.Read(str, 0, len);
table.types[t].resources[r].name = Encoding.ASCII.GetString(str);
}
else
table.types[t].resources[r].name = string.Format("{0}", table.types[t].resources[r].id & 0x7FFF);
table.types[t].resources[r].data = new byte[table.types[t].resources[r].length * (1 << table.alignment_shift)];
exeFs.Position = table.types[t].resources[r].dataOffset * (1 << table.alignment_shift);
exeFs.Read(table.types[t].resources[r].data, 0, table.types[t].resources[r].data.Length);
}
}
exeFs.Position = oldPosition;
return table;
}
}
}

99
exeinfo/NE/Structs.cs Normal file
View File

@@ -0,0 +1,99 @@
using System;
using System.Runtime.InteropServices;
namespace exeinfo.NE
{
[StructLayout(LayoutKind.Sequential/*, Pack = 2*/)]
public struct Header
{
public ushort signature;
public byte linker_major;
public byte linker_minor;
public ushort entry_table_offset;
public ushort entry_table_length;
public uint crc;
public ProgramFlags program_flags;
public ApplicationFlags application_flags;
public byte auto_data_segment_index;
public ushort initial_heap;
public ushort initial_stack;
public uint entry_point;
public uint stack_pointer;
public ushort segment_count;
public ushort reference_count;
public ushort nonresident_table_size;
public ushort segment_table_offset;
public ushort resource_table_offset;
public ushort resident_names_offset;
public ushort module_reference_offset;
public ushort imported_names_offset;
public uint nonresident_names_offset;
public ushort movable_entries;
public ushort alignment_shift;
public ushort resource_entries;
public TargetOS target_os;
public OS2Flags os2_flags;
public ushort return_thunks_offset;
public ushort segment_reference_thunks;
public ushort minimum_swap_area;
public byte os_minor;
public byte os_major;
}
public struct ResourceTable
{
public ushort alignment_shift;
public ResourceType[] types;
}
public struct ResourceType
{
public ushort id;
public ushort count;
public uint reserved;
public Resource[] resources;
// Not sequentially stored
public string name;
}
public struct Resource
{
public ushort dataOffset;
public ushort length;
public ResourceFlags flags;
public ushort id;
public uint reserved;
// Not sequentially stored
public string name;
public byte[] data;
}
class VersionNode
{
public ushort cbNode;
public ushort cbData;
public string szName;
public byte[] rgbData;
public VersionNode[] children;
}
[StructLayout(LayoutKind.Sequential)]
public class FixedFileInfo
{
public uint dwSignature;
public uint dwStrucVersion;
public uint dwFileVersionMS;
public uint dwFileVersionLS;
public uint dwProductVersionMS;
public uint dwProductVersionLS;
public uint dwFileFlagsMask;
public uint dwFileFlags;
public uint dwFileOS;
public uint dwFileType;
public uint dwFileSubtype;
public uint dwFileDateMS;
public uint dwFileDateLS;
}
}

316
exeinfo/NE/Version.cs Normal file
View File

@@ -0,0 +1,316 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace exeinfo.NE
{
public class Version
{
public Dictionary<string, Dictionary<string, string>> StringsByLanguage { get; }
string fileVersion;
string productVersion;
VersionFileFlags fileFlags;
VersionFileOS fileOS;
VersionFileType fileType;
VersionFileSubtype fileSubtype;
DateTime fileDate;
public string FileVersion
{
get
{
return fileVersion;
}
}
public string ProductVersion
{
get
{
return productVersion;
}
}
public VersionFileFlags FileFlags
{
get
{
return fileFlags;
}
}
public VersionFileOS FileOS
{
get
{
return fileOS;
}
}
public VersionFileType FileType
{
get
{
return fileType;
}
}
public VersionFileSubtype FileSubtype
{
get
{
return fileSubtype;
}
}
public DateTime FileDate
{
get
{
return fileDate;
}
}
public Version(byte[] data)
{
if (data == null || data.Length < 5)
return;
StringsByLanguage = new Dictionary<string, Dictionary<string, string>>();
VersionNode root = GetNode(data, 0, out int rootLength);
DecodeNode(root, null, null);
}
VersionNode GetNode(byte[] data, int startPosition, out int nodeLength)
{
nodeLength = 0;
VersionNode node = new VersionNode
{
cbNode = BitConverter.ToUInt16(data, startPosition + nodeLength),
cbData = BitConverter.ToUInt16(data, startPosition + nodeLength + 2)
};
nodeLength += 4;
MemoryStream nameMs = new MemoryStream();
while (data[startPosition + nodeLength] > 0)
{
nameMs.WriteByte(data[startPosition + nodeLength]);
nodeLength++;
}
node.szName = Encoding.ASCII.GetString(nameMs.ToArray());
nodeLength++;
if (nodeLength % 4 > 0)
nodeLength += 4 - (nodeLength % 4);
node.rgbData = new byte[node.cbData];
Array.Copy(data, startPosition + nodeLength, node.rgbData, 0, node.cbData);
nodeLength += node.cbData;
if (nodeLength % 4 > 0)
nodeLength += 4 - (nodeLength % 4);
List<VersionNode> children = new List<VersionNode>();
while (nodeLength < node.cbNode)
{
children.Add(GetNode(data, startPosition + nodeLength, out int childLength));
nodeLength += childLength;
}
if (children.Count > 0)
node.children = children.ToArray();
return node;
}
void DecodeNode(VersionNode node, string parent, string grandparent)
{
if (node.szName == Consts.FixedFileInfo)
{
IntPtr infoPtr = Marshal.AllocHGlobal(node.cbData);
Marshal.Copy(node.rgbData, 0, infoPtr, node.cbData);
FixedFileInfo info = (FixedFileInfo)Marshal.PtrToStructure(infoPtr, typeof(FixedFileInfo));
Marshal.FreeHGlobal(infoPtr);
fileVersion = string.Format("{0}.{1:D2}.{2}.{3}", (info.dwFileVersionMS & 0xFFFF0000) >> 16, info.dwFileVersionMS & 0xFFFF,
(info.dwFileVersionLS & 0xFFFF0000) >> 16, info.dwFileVersionLS & 0xFFFF);
productVersion = string.Format("{0}.{1:D2}.{2}.{3}", (info.dwProductVersionMS & 0xFFFF0000) >> 16, info.dwProductVersionMS & 0xFFFF,
(info.dwProductVersionLS & 0xFFFF0000) >> 16, info.dwProductVersionLS & 0xFFFF);
fileFlags = (VersionFileFlags)(info.dwFileFlags & info.dwFileFlagsMask);
fileOS = (VersionFileOS)info.dwFileOS;
fileType = (VersionFileType)info.dwFileType;
fileSubtype = (VersionFileSubtype)info.dwFileSubtype;
fileDate = DateTime.FromFileTime(info.dwFileDateMS * 0x100000000 + info.dwFileDateLS);
}
if (parent == Consts.StringFileInfo)
{
Dictionary<string, string> strings = new Dictionary<string, string>();
StringsByLanguage.Add(node.szName, strings);
}
if (grandparent == Consts.StringFileInfo)
{
if (StringsByLanguage.TryGetValue(parent, out Dictionary<string, string> strings))
{
Encoding encoding;
try
{
encoding = Encoding.GetEncoding(Convert.ToInt32(parent.Substring(4), 16));
}
catch
{
encoding = Encoding.ASCII;
}
strings.Add(node.szName, encoding.GetString(node.rgbData));
}
}
if (node.children != null)
{
for (int i = 0; i < node.children.Length; i++)
DecodeNode(node.children[i], node.szName, parent);
}
}
public static string TypeToString(VersionFileType type)
{
switch (type)
{
case VersionFileType.VFT_APP:
return "Application";
case VersionFileType.VFT_DLL:
return "Dynamic-link library";
case VersionFileType.VFT_DRV:
return "Device driver";
case VersionFileType.VFT_FONT:
return "Font";
case VersionFileType.VFT_STATIC_LIB:
return "Static-link library";
case VersionFileType.VFT_UNKNOWN:
return "Unknown";
case VersionFileType.VFT_VXD:
return "Virtual device";
default:
return string.Format("Unknown type code {0}", (uint)type);
}
}
public static string DriverToString(VersionFileSubtype subtype)
{
switch (subtype)
{
case VersionFileSubtype.VFT2_DRV_COMM:
return "Communications";
case VersionFileSubtype.VFT2_DRV_DISPLAY:
return "Display";
case VersionFileSubtype.VFT2_DRV_INSTALLABLE:
return "Installable";
case VersionFileSubtype.VFT2_DRV_KEYBOARD:
return "Keyboard";
case VersionFileSubtype.VFT2_DRV_LANGUAGE:
return "Language";
case VersionFileSubtype.VFT2_DRV_MOUSE:
return "Mouse";
case VersionFileSubtype.VFT2_DRV_NETWORK:
return "Network";
case VersionFileSubtype.VFT2_DRV_PRINTER:
return "Printer";
case VersionFileSubtype.VFT2_DRV_SOUND:
return "Sound";
case VersionFileSubtype.VFT2_DRV_SYSTEM:
return "System";
case VersionFileSubtype.VFT2_DRV_VERSIONED_PRINTER:
return "Versioned";
case VersionFileSubtype.VFT2_UNKNOWN:
return "Unknown";
default:
return string.Format("Unknown type code {0}", (uint)subtype);
}
}
public static string FontToString(VersionFileSubtype subtype)
{
switch (subtype)
{
case VersionFileSubtype.VFT2_FONT_RASTER:
return "Raster";
case VersionFileSubtype.VFT2_FONT_TRUETYPE:
return "TrueType";
case VersionFileSubtype.VFT2_FONT_VECTOR:
return "Vector";
case VersionFileSubtype.VFT2_UNKNOWN:
return "Unknown";
default:
return string.Format("Unknown type code {0}", (uint)subtype);
}
}
public static string OsToString(VersionFileOS os)
{
switch (os)
{
case VersionFileOS.VOS_DOS:
return "DOS";
case VersionFileOS.VOS_NT:
return "Windows NT";
case VersionFileOS.VOS_WINDOWS16:
return "16-bit Windows";
case VersionFileOS.VOS_WINDOWS32:
return "32-bit Windows";
case VersionFileOS.VOS_OS216:
return "16-bit OS/2";
case VersionFileOS.VOS_OS232:
return "32-bit OS/2";
case VersionFileOS.VOS_PM16:
return "16-bit Presentation Manager";
case VersionFileOS.VOS_PM32:
return "32-bit Presentation Manager";
case VersionFileOS.VOS_UNKNOWN:
return "Unknown";
case VersionFileOS.VOS_DOS_NT:
return "DOS running under Windows NT";
case VersionFileOS.VOS_DOS_WINDOWS16:
return "16-bit Windows running under DOS";
case VersionFileOS.VOS_DOS_WINDOWS32:
return "32-bit Windows running under DOS";
case VersionFileOS.VOS_DOS_PM16:
return "16-bit Presentation Manager running under DOS";
case VersionFileOS.VOS_DOS_PM32:
return "32-bit Presentation Manager running under DOS";
case VersionFileOS.VOS_NT_WINDOWS16:
return "16-bit Windows running under Windows NT";
case VersionFileOS.VOS_NT_WINDOWS32:
return "32-bit Windows running under Windows NT";
case VersionFileOS.VOS_NT_PM16:
return "16-bit Presentation Manager running under Windows NT";
case VersionFileOS.VOS_NT_PM32:
return "32-bit Presentation Manager running under Windows NT";
case VersionFileOS.VOS_OS216_WINDOWS16:
return "16-bit Windows running under 16-bit OS/2";
case VersionFileOS.VOS_OS216_WINDOWS32:
return "32-bit Windows running under 16-bit OS/2";
case VersionFileOS.VOS_OS216_PM16:
return "16-bit Presentation Manager running under 16-bit OS/2";
case VersionFileOS.VOS_OS216_PM32:
return "32-bit Presentation Manager running under 16-bit OS/2";
case VersionFileOS.VOS_OS232_WINDOWS16:
return "16-bit Windows running under 32-bit OS/2";
case VersionFileOS.VOS_OS232_WINDOWS32:
return "32-bit Windows running under 32-bit OS/2";
case VersionFileOS.VOS_OS232_PM16:
return "16-bit Presentation Manager running under 32-bit OS/2";
case VersionFileOS.VOS_OS232_PM32:
return "32-bit Presentation Manager running under 32-bit OS/2";
default:
return string.Format("Unknown OS code {0}", (uint)os);
}
}
}
}

View File

@@ -1,6 +1,9 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace exeinfo
{
@@ -46,10 +49,41 @@ namespace exeinfo
neHdr = (NE.Header)Marshal.PtrToStructure(hdrPtr, typeof(NE.Header));
Marshal.FreeHGlobal(hdrPtr);
if (neHdr.signature == NE.Signature)
if (neHdr.signature == NE.Consts.Signature)
{
NE.PrintInfo(neHdr);
NE.GetResources(exeFs, mzHdr.new_offset, neHdr.resource_table_offset);
NE.Info.PrintInfo(neHdr);
NE.ResourceTable resources = NE.Info.GetResources(exeFs, mzHdr.new_offset, neHdr.resource_table_offset);
foreach(NE.ResourceType type in resources.types)
{
if((type.id & 0x7FFF) == (int)NE.ResourceTypes.RT_VERSION)
{
foreach(NE.Resource resource in type.resources)
{
NE.Version vers = new NE.Version(resource.data);
Console.WriteLine("\tVersion resource {0}:", resource.name);
Console.WriteLine("\t\tFile version: {0}", vers.FileVersion);
Console.WriteLine("\t\tProduct version: {0}", vers.ProductVersion);
Console.WriteLine("\t\tFile type: {0}", NE.Version.TypeToString(vers.FileType));
if(vers.FileType == NE.VersionFileType.VFT_DRV)
Console.WriteLine("\t\tFile subtype: {0} driver", NE.Version.DriverToString(vers.FileSubtype));
else if (vers.FileType == NE.VersionFileType.VFT_DRV)
Console.WriteLine("\t\tFile subtype: {0} font", NE.Version.FontToString(vers.FileSubtype));
else if(vers.FileSubtype > 0)
Console.WriteLine("\t\tFile subtype: {0}", (uint)vers.FileSubtype);
Console.WriteLine("\t\tFile flags: {0}", vers.FileFlags);
Console.WriteLine("\t\tFile OS: {0}", NE.Version.OsToString(vers.FileOS));
foreach (KeyValuePair<string, Dictionary<string, string>> strByLang in vers.StringsByLanguage)
{
CultureInfo cult = new CultureInfo(Convert.ToInt32(strByLang.Key.Substring(0, 4), 16));
Encoding encoding = Encoding.GetEncoding(Convert.ToInt32(strByLang.Key.Substring(4), 16));
Console.WriteLine("\t\tStrings for {0} in codepage {1}:", cult.DisplayName, encoding.EncodingName);
foreach(KeyValuePair<string, string> strings in strByLang.Value)
Console.WriteLine("\t\t\t{0}: {1}", strings.Key, strings.Value);
}
}
}
}
}
}
}

View File

@@ -35,7 +35,14 @@
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MZ.cs" />
<Compile Include="NE.cs" />
<Compile Include="NE\Version.cs" />
<Compile Include="NE\Structs.cs" />
<Compile Include="NE\Enums.cs" />
<Compile Include="NE\Consts.cs" />
<Compile Include="NE\Info.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="NE\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>