mirror of
https://github.com/claunia/libexeinfo.git
synced 2025-12-16 19:14:24 +00:00
317 lines
11 KiB
C#
317 lines
11 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|