Add decoding RT_ACCELERATOR (Windows) and RT_ACCELTABLE (OS/2) resources from NE, and appropriate GUI.

This commit is contained in:
2018-03-03 18:58:47 +00:00
parent 18464bacff
commit b78157bf4d
5 changed files with 459 additions and 7 deletions

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<Panel xmlns="http://schema.picoe.ca/eto.forms" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackLayout Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<StackLayoutItem HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Expand="True">
<StackLayout Orientation="Vertical">
<StackLayoutItem HorizontalAlignment="Right" Expand="True">
<Label ID="lblCodepage">Codepage</Label>
</StackLayoutItem>
</StackLayout>
</StackLayoutItem>
<StackLayoutItem HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Expand="True">
<StackLayout Orientation="Vertical">
<StackLayoutItem HorizontalAlignment="Stretch" Expand="True">
<TextBox ID="txtCodepage" ReadOnly="True"/>
</StackLayoutItem>
</StackLayout>
</StackLayoutItem>
</StackLayout>
<StackLayoutItem HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Expand="True">
<StackLayout Orientation="Vertical" ID="stkString">
<StackLayoutItem HorizontalAlignment="Center">
<Label ID="lblAccelerators">Accelerators</Label>
</StackLayoutItem>
<StackLayoutItem HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Expand="True">
<GridView ID="grdAccelerators"/>
</StackLayoutItem>
</StackLayout>
</StackLayoutItem>
</StackLayout>
</Panel>

View File

@@ -0,0 +1,78 @@
using System.Collections.Generic;
using System.Linq;
using Eto.Forms;
using Eto.Serialization.Xaml;
namespace exeinfogui.NE
{
public class PanelNeAccelerators : Panel
{
GridView grdAccelerators;
Label lblCodepage;
TextBox txtCodepage;
public PanelNeAccelerators()
{
XamlReader.Load(this);
grdAccelerators.Columns.Add(new GridColumn
{
DataCell = new TextBoxCell {Binding = Binding.Property<Accelerator, string>(a => $"{a.Type}")},
HeaderText = "Type"
});
grdAccelerators.Columns.Add(new GridColumn
{
DataCell = new TextBoxCell {Binding = Binding.Property<Accelerator, string>(a => $"{a.Key}")},
HeaderText = "Key"
});
grdAccelerators.Columns.Add(new GridColumn
{
DataCell = new TextBoxCell {Binding = Binding.Property<Accelerator, string>(a => $"{a.Command}")},
HeaderText = "Command"
});
}
public void Update(byte[] data, libexeinfo.NE.TargetOS targetOs)
{
grdAccelerators.DataStore = null;
List<Accelerator> accelerators = new List<Accelerator>();
if(targetOs == libexeinfo.NE.TargetOS.OS2)
{
libexeinfo.NE.Os2AcceleratorTable table = libexeinfo.NE.GetOs2Accelerators(data);
lblCodepage.Visible = true;
txtCodepage.Visible = true;
txtCodepage.Text = $"{table.CodePage}";
accelerators.AddRange(table.Accelerators.Select(accel => new Accelerator
{
Type = $"{accel.Type}",
Key = $"{accel.Key}",
Command = accel.Command
}));
}
else
{
lblCodepage.Visible = false;
txtCodepage.Visible = false;
accelerators.AddRange(libexeinfo.NE.GetWinAccelerators(data)
.Select(accel => new Accelerator
{
Type = $"{accel.Flags}",
Key = $"{accel.Key}",
Command = accel.Command
}));
}
if(accelerators.Count > 0) grdAccelerators.DataStore = accelerators;
}
class Accelerator
{
public ushort Command;
public string Key;
public string Type;
}
}
}

View File

@@ -35,11 +35,12 @@ namespace exeinfogui.NE
{
public class TabNeResources : TabPage
{
PanelNeAccelerators panelNeAccelerators;
PanelNeStrings panelNeStrings;
PanelWin16Version panelWin16Version;
Panel pnlResource;
TreeGridItemCollection treeData;
TreeGridView treeResources;
PanelWin16Version panelWin16Version;
PanelNeStrings panelNeStrings;
public TabNeResources()
{
@@ -51,9 +52,10 @@ namespace exeinfogui.NE
treeResources.AllowMultipleSelection = false;
treeResources.SelectionChanged += TreeResourcesOnSelectionChanged;
panelWin16Version = new PanelWin16Version();
panelNeStrings = new PanelNeStrings();
panelWin16Version = new PanelWin16Version();
panelNeStrings = new PanelNeStrings();
panelNeAccelerators = new PanelNeAccelerators();
}
public void Update(IEnumerable<libexeinfo.NE.ResourceType> resourceTypes, libexeinfo.NE.TargetOS os)
@@ -93,7 +95,7 @@ namespace exeinfogui.NE
}
byte[] data = ((libexeinfo.NE.Resource)((TreeGridItem)treeResources.SelectedItem).Values[5]).data;
switch(((TreeGridItem)treeResources.SelectedItem).Values[3])
{
case "RT_VERSION":
@@ -102,7 +104,16 @@ namespace exeinfogui.NE
break;
case "RT_STRING":
pnlResource.Content = panelNeStrings;
panelNeStrings.Update(data, (libexeinfo.NE.TargetOS)((TreeGridItem)treeResources.SelectedItem).Values[4]);
panelNeStrings.Update(data,
(libexeinfo.NE.TargetOS)((TreeGridItem)treeResources.SelectedItem).Values[4]);
break;
case "RT_ACCELERATOR":
pnlResource.Content = panelNeAccelerators;
panelNeAccelerators.Update(data, libexeinfo.NE.TargetOS.Windows);
break;
case "RT_ACCELTABLE":
pnlResource.Content = panelNeAccelerators;
panelNeAccelerators.Update(data, libexeinfo.NE.TargetOS.OS2);
break;
default:
pnlResource.Content = null;

View File

@@ -0,0 +1,331 @@
//
// Accelerator.cs
//
// Author:
// Natalia Portillo <claunia@claunia.com>
//
// 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.Runtime.InteropServices;
// ReSharper disable InconsistentNaming
namespace libexeinfo
{
public partial class NE
{
[Flags]
public enum Os2AcceleratorFlags : ushort
{
AF_CHAR = 0x0001,
AF_VIRTUALKEY = 0x0002,
AF_SCANCODE = 0x0004,
AF_SHIFT = 0x0008,
AF_CONTROL = 0x0010,
AF_ALT = 0x0020,
AF_LONEKEY = 0x0040,
AF_SYSCOMMAND = 0x0100,
AF_HELP = 0x0200
}
public enum Os2VirtualKey : ushort
{
VK_BUTTON1 = 0x01,
VK_BUTTON2 = 0x02,
VK_BUTTON3 = 0x03,
VK_BREAK = 0x04,
VK_BACKSPACE = 0x05,
VK_TAB = 0x06,
VK_BACKTAB = 0x07,
VK_NEWLINE = 0x08,
VK_SHIFT = 0x09,
VK_CTRL = 0x0A,
VK_ALT = 0x0B,
VK_ALTGRAF = 0x0C,
VK_PAUSE = 0x0D,
VK_CAPSLOCK = 0x0E,
VK_ESC = 0x0F,
VK_SPACE = 0x10,
VK_PAGEUP = 0x11,
VK_PAGEDOWN = 0x12,
VK_END = 0x13,
VK_HOME = 0x14,
VK_LEFT = 0x15,
VK_UP = 0x16,
VK_RIGHT = 0x17,
VK_DOWN = 0x18,
VK_PRINTSCRN = 0x19,
VK_INSERT = 0x1A,
VK_DELETE = 0x1B,
VK_SCRLLOCK = 0x1C,
VK_NUMLOCK = 0x1D,
VK_ENTER = 0x1E,
VK_SYSRQ = 0x1F,
VK_F1 = 0x20,
VK_F2 = 0x21,
VK_F3 = 0x22,
VK_F4 = 0x23,
VK_F5 = 0x24,
VK_F6 = 0x25,
VK_F7 = 0x26,
VK_F8 = 0x27,
VK_F9 = 0x28,
VK_F10 = 0x29,
VK_F11 = 0x2A,
VK_F12 = 0x2B,
VK_F13 = 0x2C,
VK_F14 = 0x2D,
VK_F15 = 0x2E,
VK_F16 = 0x2F,
VK_F17 = 0x30,
VK_F18 = 0x31,
VK_F19 = 0x32,
VK_F20 = 0x33,
VK_F21 = 0x34,
VK_F22 = 0x35,
VK_F23 = 0x36,
VK_F24 = 0x37
}
[Flags]
public enum WinAcceleratorFlags : byte
{
VirtualKey = 0x01,
NoInvert = 0x02,
Shift = 0x04,
Control = 0x08,
Alt = 0x10,
Last = 0x80
}
public enum WinVirtualKey : byte
{
VK_LBUTTON = 0x01,
VK_RBUTTON = 0x02,
VK_CANCEL = 0x03,
VK_MBUTTON = 0x04,
VK_BACK = 0x08,
VK_TAB = 0x09,
VK_CLEAR = 0x0C,
VK_RETURN = 0x0D,
VK_SHIFT = 0x10,
VK_CONTROL = 0x11,
VK_MENU = 0x12,
VK_PAUSE = 0x13,
VK_CAPITAL = 0x14,
VK_ESCAPE = 0x1B,
VK_SPACE = 0x20,
VK_PRIOR = 0x21,
VK_NEXT = 0x22,
VK_END = 0x23,
VK_HOME = 0x24,
VK_LEFT = 0x25,
VK_UP = 0x26,
VK_RIGHT = 0x27,
VK_DOWN = 0x28,
VK_SELECT = 0x29,
VK_PRINT = 0x2A,
VK_EXECUTE = 0x2B,
VK_SNAPSHOT = 0x2C,
VK_INSERT = 0x2D,
VK_DELETE = 0x2E,
VK_HELP = 0x2F,
VK_0 = 0x30,
VK_1 = 0x31,
VK_2 = 0x32,
VK_3 = 0x33,
VK_4 = 0x34,
VK_5 = 0x35,
VK_6 = 0x36,
VK_7 = 0x37,
VK_8 = 0x38,
VK_9 = 0x39,
VK_A = 0x41,
VK_B = 0x42,
VK_C = 0x43,
VK_D = 0x44,
VK_E = 0x45,
VK_F = 0x46,
VK_G = 0x47,
VK_H = 0x48,
VK_I = 0x49,
VK_J = 0x4A,
VK_K = 0x4B,
VK_L = 0x4C,
VK_M = 0x4D,
VK_N = 0x4E,
VK_O = 0x4F,
VK_P = 0x50,
VK_Q = 0x51,
VK_R = 0x52,
VK_S = 0x53,
VK_T = 0x54,
VK_U = 0x55,
VK_V = 0x56,
VK_W = 0x57,
VK_X = 0x58,
VK_Y = 0x59,
VK_Z = 0x5A,
VK_NUMPAD0 = 0x60,
VK_NUMPAD1 = 0x61,
VK_NUMPAD2 = 0x62,
VK_NUMPAD3 = 0x63,
VK_NUMPAD4 = 0x64,
VK_NUMPAD5 = 0x65,
VK_NUMPAD6 = 0x66,
VK_NUMPAD7 = 0x67,
VK_NUMPAD8 = 0x68,
VK_NUMPAD9 = 0x69,
VK_MULTIPLY = 0x6A,
VK_ADD = 0x6B,
VK_SEPARATOR = 0x6C,
VK_SUBTRACT = 0x6D,
VK_DECIMAL = 0x6E,
VK_DIVIDE = 0x6F,
VK_F1 = 0x70,
VK_F2 = 0x71,
VK_F3 = 0x72,
VK_F4 = 0x73,
VK_F5 = 0x74,
VK_F6 = 0x75,
VK_F7 = 0x76,
VK_F8 = 0x77,
VK_F9 = 0x78,
VK_F10 = 0x79,
VK_F11 = 0x7A,
VK_F12 = 0x7B,
VK_F13 = 0x7C,
VK_F14 = 0x7D,
VK_F15 = 0x7E,
VK_F16 = 0x7F,
VK_F17 = 0x80,
VK_F18 = 0x81,
VK_F19 = 0x82,
VK_F20 = 0x83,
VK_F21 = 0x84,
VK_F22 = 0x85,
VK_F23 = 0x86,
VK_F24 = 0x87,
VK_NUMLOCK = 0x90,
VK_SCROLL = 0x91
}
public static WinAccelerator[] GetWinAccelerators(byte[] data)
{
int pos = 0;
List<WinAccelerator> accelerators = new List<WinAccelerator>();
while(pos + 8 < data.Length)
{
byte[] accelBytes = new byte[Marshal.SizeOf(typeof(WinAccelerator))];
Array.Copy(data, pos, accelBytes, 0, accelBytes.Length);
WinAccelerator accelerator =
BigEndianMarshal.ByteArrayToStructureLittleEndian<WinAccelerator>(accelBytes);
accelerators.Add(accelerator);
if(accelerator.Flags.HasFlag(WinAcceleratorFlags.Last)) break;
pos += accelBytes.Length;
}
return accelerators.ToArray();
}
public static Os2AcceleratorTable GetOs2Accelerators(byte[] data)
{
int pos = 4;
Os2AcceleratorTable table = new Os2AcceleratorTable
{
Count = BitConverter.ToUInt16(data, 0),
CodePage = BitConverter.ToUInt16(data, 2)
};
table.Accelerators = new Os2Accelerator[table.Count];
for(int i = 0; i < table.Count; i++)
{
byte[] accelBytes = new byte[Marshal.SizeOf(typeof(Os2Accelerator))];
if(pos + accelBytes.Length > data.Length) break;
table.Accelerators[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian<Os2Accelerator>(accelBytes);
pos += accelBytes.Length;
}
return table;
}
public struct Os2AcceleratorTable
{
/// <summary>
/// How many accelerators are included in this table
/// </summary>
public ushort Count;
/// <summary>
/// Table's codepage
/// </summary>
public ushort CodePage;
/// <summary>
/// Array of accelerators
/// </summary>
public Os2Accelerator[] Accelerators;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Os2Accelerator
{
/// <summary>
/// Accelerator type
/// </summary>
public Os2AcceleratorFlags Type;
/// <summary>
/// Accelerator key
/// </summary>
public Os2VirtualKey Key;
/// <summary>
/// Accelerator command
/// </summary>
public ushort Command;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WinAccelerator
{
/// <summary>
/// Accelerator flags
/// </summary>
public WinAcceleratorFlags Flags;
/// <summary>
/// Accelerator key
/// </summary>
public WinVirtualKey Key;
/// <summary>
/// Padding
/// </summary>
public byte Padding;
/// <summary>
/// Accelerator command
/// </summary>
public byte Command;
}
}
}

View File

@@ -56,6 +56,7 @@
<Compile Include="GEM\Structs.cs" />
<Compile Include="GEM\Vdi.cs" />
<Compile Include="IExecutable.cs" />
<Compile Include="NE\Accelerators.cs" />
<Compile Include="NE\GetStrings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MZ\Consts.cs" />