From 03b452118efc05b884c8b926700c539b282fef92 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 3 Mar 2018 04:57:40 +0000 Subject: [PATCH] Added GUI panel for Windows NE resources and RT_VERSION. --- exeinfogui/MainForm.xeto.cs | 20 ++- exeinfogui/NE/TabNeResources.xeto | 15 +++ exeinfogui/NE/TabNeResources.xeto.cs | 107 +++++++++++++++ exeinfogui/Win16/PanelWin16Version.xeto | 85 ++++++++++++ exeinfogui/Win16/PanelWin16Version.xeto.cs | 147 +++++++++++++++++++++ exeinfogui/exeinfogui.csproj | 3 + libexeinfo/NE/Consts.cs | 2 +- 7 files changed, 376 insertions(+), 3 deletions(-) create mode 100644 exeinfogui/NE/TabNeResources.xeto create mode 100644 exeinfogui/NE/TabNeResources.xeto.cs create mode 100644 exeinfogui/Win16/PanelWin16Version.xeto create mode 100644 exeinfogui/Win16/PanelWin16Version.xeto.cs diff --git a/exeinfogui/MainForm.xeto.cs b/exeinfogui/MainForm.xeto.cs index 1bdc418..09f9cc9 100644 --- a/exeinfogui/MainForm.xeto.cs +++ b/exeinfogui/MainForm.xeto.cs @@ -27,6 +27,7 @@ using System; using System.Linq; using exeinfogui.GEM; +using exeinfogui.NE; using Eto.Forms; using Eto.Serialization.Xaml; using libexeinfo; @@ -46,6 +47,7 @@ namespace exeinfogui TextBox txtSubsystem; TextBox txtType; TabPageSegments tabSegments; + TabNeResources tabNeResources; public MainForm() { @@ -54,9 +56,11 @@ namespace exeinfogui tabSegments = new TabPageSegments {Visible = false}; tabStrings = new TabPageStrings {Visible = false}; tabGemResources = new TabGemResources {Visible = false}; + tabNeResources = new TabNeResources {Visible = false}; tabMain.Pages.Add(tabSegments); tabMain.Pages.Add(tabStrings); tabMain.Pages.Add(tabGemResources); + tabMain.Pages.Add(tabNeResources); } protected void OnBtnLoadClick(object sender, EventArgs e) @@ -75,9 +79,13 @@ namespace exeinfogui if(dlgOpen.ShowDialog(this) != DialogResult.Ok) return; txtFile.Text = dlgOpen.FileName; + txtInformation.Text = ""; + txtOs.Text = ""; + txtSubsystem.Text = ""; + txtType.Text = ""; IExecutable mzExe = new MZ(dlgOpen.FileName); - IExecutable neExe = new NE(dlgOpen.FileName); + IExecutable neExe = new libexeinfo.NE(dlgOpen.FileName); IExecutable stExe = new AtariST(dlgOpen.FileName); IExecutable lxExe = new LX(dlgOpen.FileName); IExecutable coffExe = new COFF(dlgOpen.FileName); @@ -94,7 +102,15 @@ namespace exeinfogui } } - if(neExe.Recognized) recognizedExe = neExe; + if(neExe.Recognized) + { + recognizedExe = neExe; + if(((libexeinfo.NE)neExe).Resources.types != null && ((libexeinfo.NE)neExe).Resources.types.Any()) + { + tabNeResources.Update(((libexeinfo.NE)neExe).Resources.types, ((libexeinfo.NE)neExe).Header.target_os); + tabNeResources.Visible = true; + } + } else if(lxExe.Recognized) recognizedExe = lxExe; else if(peExe.Recognized) diff --git a/exeinfogui/NE/TabNeResources.xeto b/exeinfogui/NE/TabNeResources.xeto new file mode 100644 index 0000000..3c920ac --- /dev/null +++ b/exeinfogui/NE/TabNeResources.xeto @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/exeinfogui/NE/TabNeResources.xeto.cs b/exeinfogui/NE/TabNeResources.xeto.cs new file mode 100644 index 0000000..016d77e --- /dev/null +++ b/exeinfogui/NE/TabNeResources.xeto.cs @@ -0,0 +1,107 @@ +// +// TabNeResources.xeto.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using exeinfogui.Win16; +using Eto.Forms; +using Eto.Serialization.Xaml; + +namespace exeinfogui.NE +{ + public class TabNeResources : TabPage + { + Panel pnlResource; + TreeGridItemCollection treeData; + TreeGridView treeResources; + PanelWin16Version panelWin16Version; + + public TabNeResources() + { + XamlReader.Load(this); + + treeResources.Columns.Add(new GridColumn {HeaderText = "Type", DataCell = new TextBoxCell(0)}); + treeResources.Columns.Add(new GridColumn {HeaderText = "Size", DataCell = new TextBoxCell(1)}); + treeResources.Columns.Add(new GridColumn {HeaderText = "Flags", DataCell = new TextBoxCell(2)}); + + treeResources.AllowMultipleSelection = false; + treeResources.SelectionChanged += TreeResourcesOnSelectionChanged; + + panelWin16Version = new PanelWin16Version(); + } + + public void Update(IEnumerable resourceTypes, libexeinfo.NE.TargetOS os) + { + treeData = new TreeGridItemCollection(); + + foreach(libexeinfo.NE.ResourceType resourceType in resourceTypes.OrderBy(r => r.name)) + { + TreeGridItem root = new TreeGridItem + { + Values = new object[] {$"{resourceType.name}", null, null, null, os, null} + }; + + foreach(libexeinfo.NE.Resource resource in resourceType.resources.OrderBy(r => r.name)) + root.Children.Add(new TreeGridItem + { + Values = new object[] + { + $"{resource.name}", $"{resource.data.Length}", + $"{(libexeinfo.NE.ResourceFlags)((ushort)resource.flags & libexeinfo.NE.KNOWN_RSRC_FLAGS)}", + $"{resourceType.name}", os, resource + } + }); + + treeData.Add(root); + } + + treeResources.DataStore = treeData; + } + + void TreeResourcesOnSelectionChanged(object sender, EventArgs eventArgs) + { + if(!(((TreeGridItem)treeResources.SelectedItem)?.Values[5] is libexeinfo.NE.Resource resource)) + { + pnlResource.Content = null; + return; + } + + byte[] data = ((libexeinfo.NE.Resource)((TreeGridItem)treeResources.SelectedItem).Values[5]).data; + + switch(((TreeGridItem)treeResources.SelectedItem).Values[3]) + { + case "RT_VERSION": + pnlResource.Content = panelWin16Version; + panelWin16Version.Update(data); + break; + default: + pnlResource.Content = null; + break; + } + } + } +} \ No newline at end of file diff --git a/exeinfogui/Win16/PanelWin16Version.xeto b/exeinfogui/Win16/PanelWin16Version.xeto new file mode 100644 index 0000000..b77aae8 --- /dev/null +++ b/exeinfogui/Win16/PanelWin16Version.xeto @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/exeinfogui/Win16/PanelWin16Version.xeto.cs b/exeinfogui/Win16/PanelWin16Version.xeto.cs new file mode 100644 index 0000000..2b78b4d --- /dev/null +++ b/exeinfogui/Win16/PanelWin16Version.xeto.cs @@ -0,0 +1,147 @@ +// +// PanelWin16Version.xeto.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Text; +using Eto.Forms; +using Eto.Serialization.Xaml; + +namespace exeinfogui.Win16 +{ + public class PanelWin16Version : Panel + { + ObservableCollection stringsByLanguage; + GridView treeLanguages; + GridView treeStrings; + TextBox txtFileDate; + TextBox txtFileFlags; + TextBox txtFileOs; + TextBox txtFileSubtype; + TextBox txtFileType; + TextBox txtFileVersion; + TextBox txtProductVersion; + + public PanelWin16Version() + { + XamlReader.Load(this); + + treeLanguages.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Name)}, + HeaderText = "Language (codepage)" + }); + + treeStrings.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Key)}, + HeaderText = "Key" + }); + + treeStrings.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Value)}, + HeaderText = "Value" + }); + + stringsByLanguage = new ObservableCollection(); + treeLanguages.SelectionChanged += TreeLanguagesOnSelectionChanged; + treeLanguages.AllowMultipleSelection = false; + } + + void TreeLanguagesOnSelectionChanged(object sender, EventArgs eventArgs) + { + treeStrings.DataStore = null; + if(!(treeLanguages.SelectedItem is StrByLang strs)) return; + + List strings = new List(); + foreach(KeyValuePair kvp in strs.Strings) + strings.Add(new Strings {Key = kvp.Key, Value = kvp.Value}); + + treeStrings.DataStore = strings; + } + + public void Update(byte[] data) + { + libexeinfo.NE.Version version = new libexeinfo.NE.Version(data); + txtFileDate.Text = version.FileDate != new DateTime(1601, 1, 1) ? $"{version.FileDate}" : "Not set"; + txtFileFlags.Text = version.FileFlags == 0 ? "Normal" : $"{version.FileFlags}"; + txtFileOs.Text = libexeinfo.NE.Version.OsToString(version.FileOS); + + if(version.FileType == libexeinfo.NE.VersionFileType.VFT_DRV) + txtFileSubtype.Text = $"{libexeinfo.NE.Version.DriverToString(version.FileSubtype)} driver"; + else if(version.FileType == libexeinfo.NE.VersionFileType.VFT_DRV) + txtFileSubtype.Text = $"{libexeinfo.NE.Version.FontToString(version.FileSubtype)} font"; + else if(version.FileSubtype > 0) + txtFileSubtype.Text = $"{(uint)version.FileSubtype}"; + else + txtFileSubtype.Text = "None"; + + txtFileType.Text = libexeinfo.NE.Version.TypeToString(version.FileType); + txtFileVersion.Text = $"{version.FileVersion}"; + txtProductVersion.Text = $"{version.ProductVersion}"; + + stringsByLanguage.Clear(); + + foreach(KeyValuePair> strByLang in version.StringsByLanguage) + { + string cultureName; + string encodingName; + + try { cultureName = new CultureInfo(Convert.ToInt32(strByLang.Key.Substring(0, 4), 16)).DisplayName; } + catch { cultureName = $"0x{Convert.ToInt32(strByLang.Key.Substring(0, 4), 16):X4}"; } + + try + { + encodingName = Encoding.GetEncoding(Convert.ToInt32(strByLang.Key.Substring(4), 16)).EncodingName; + } + catch { encodingName = $"0x{Convert.ToInt32(strByLang.Key.Substring(4), 16):X4}"; } + + stringsByLanguage.Add(new StrByLang + { + Name = $"{cultureName} ({encodingName})", + Strings = strByLang.Value + }); + } + + treeLanguages.DataStore = stringsByLanguage; + } + + class StrByLang + { + public Dictionary Strings; + public string Name { get; set; } + } + + class Strings + { + public string Key { get; set; } + public string Value { get; set; } + } + } +} \ No newline at end of file diff --git a/exeinfogui/exeinfogui.csproj b/exeinfogui/exeinfogui.csproj index a023c6d..c74d95e 100644 --- a/exeinfogui/exeinfogui.csproj +++ b/exeinfogui/exeinfogui.csproj @@ -19,5 +19,8 @@ + + + \ No newline at end of file diff --git a/libexeinfo/NE/Consts.cs b/libexeinfo/NE/Consts.cs index 7aada08..062174b 100644 --- a/libexeinfo/NE/Consts.cs +++ b/libexeinfo/NE/Consts.cs @@ -45,7 +45,7 @@ namespace libexeinfo const ushort SEGMENT_FLAGS_MASK = 0x3F8; const ushort SEGMENT_DISCARD_MASK = 0xF000; const ushort SEGMENT_IOPRVL_MASK = 0xC00; - const ushort KNOWN_RSRC_FLAGS = 0x1070; + public const ushort KNOWN_RSRC_FLAGS = 0x1070; /// /// Gets the name of a resource type according to its identifier