Skip to content

Commit

Permalink
Finished work on reading menu resources.
Browse files Browse the repository at this point in the history
  • Loading branch information
lkinsella committed Jul 10, 2016
1 parent 83ecd3c commit 4c024a6
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 17 deletions.
9 changes: 5 additions & 4 deletions Src/Demo Application/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ static void Main(string[] args)
//string file_name = @"C:\Windows\System32\kernel32.dll";
//string file_name = @"C:\Windows\SysWOW64\shell32.dll";
//string file_name = @"C:\Windows\System32\shell32.dll";
string file_name = @"C:\Windows\System32\user32.dll";
//string file_name = @"C:\Windows\System32\user32.dll";
//string file_name = @"C:\Windows\explorer.exe";
//string file_name = @"C:\Windows\SysWOW64\xpsservices.dll";
//string file_name = @"c:\windows\system32\advapi32.dll";
string file_name = @"C:\Program Files (x86)\Notepad++\notepad++.exe";
string error_message;

if (!ExecutableImage.IsValid(file_name,out error_message))
Expand All @@ -39,9 +40,9 @@ static void Main(string[] args)

ExecutableImage image = ExecutableImage.FromFile(file_name);
Resources resources = Resources.Get(image);
ResourceType types = resources.First(t => t.Id == ResourceType.RT_VERSION);
Resource resource = types.First();
VersionResource version = VersionResource.Load(resource);
ResourceType types = resources.First(t => t.Id == ResourceType.RT_MENU);
Resource resource = types.First(r => r.Id == 1500);
MenuResource menus = MenuResource.Load(resource);

//Console.ReadKey();
}
Expand Down
2 changes: 1 addition & 1 deletion Src/Workshell.PE.Resources/LocaleIdentifiers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public sealed class LocaleIdentifiers
public const ushort SUBLANG_HINDI_INDIA = 0x0439;
public const ushort SUBLANG_HUNGARIAN_HUNGARY = 0x040E;
public const ushort SUBLANG_ICELANDIC_ICELAND = 0x040F;
public const ushort SUBLANG_IGBO_NIGERIA = 0x0470
public const ushort SUBLANG_IGBO_NIGERIA = 0x0470;
public const ushort SUBLANG_INDONESIAN_INDONESIA = 0x0421;
public const ushort SUBLANG_INUKTITUT_CANADA_LATIN = 0x085D;
public const ushort SUBLANG_INUKTITUT_CANADA = 0x045D;
Expand Down
178 changes: 168 additions & 10 deletions Src/Workshell.PE.Resources/Menus/MenuItem.cs
Original file line number Diff line number Diff line change
@@ -1,50 +1,208 @@
using System;
#region License
// Copyright(c) 2016, Workshell Ltd
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of Workshell Ltd nor the names of its contributors
// may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED.IN NO EVENT SHALL WORKSHELL BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Workshell.PE.Annotations;

namespace Workshell.PE
{

[Flags]
public enum MenuItemFlags : ushort
{
Enabled = 0,
Grayed = 0x0001,
Disabled = 0x0002,
Bitmap = 0x0004,
OwnerDraw = 0x0100,
Checked = 0x0008,
Popup = 0x0010,
MenubarBreak = 0x0020,
MenuBreak = 0x0040,
EndMenu = 0x0080,
Seperator = 0x0800
}

public class MenuItem
{

private ushort id;
private string text;
private string shortcut;
private ushort flags;

internal MenuItem(ushort itemId, string itemText, ushort itemFlags)
{
id = itemId;

string[] parts = itemText.Split(new char[] { '\t' }, 2);

text = parts[0];

if (parts.Length > 1)
{
shortcut = parts[1];
}
else
{
shortcut = String.Empty;
}

flags = itemFlags;
}

#region Methods

public override string ToString()
{
if (!IsSeperator)
{
string result = text;

if (IsPopup)
result = "+" + result;

if (shortcut != String.Empty)
result += " | " + shortcut;

return result;
}
else
{
return "-";
}
}

#endregion

#region Properties

public ushort Id
{
get;
set;
get
{
return id;
}
}

public string Text
{
get;
set;
get
{
return text;
}
}

public string Shortcut
{
get;
set;
get
{
return shortcut;
}
}

public MenuItemFlags Flags
{
get
{
return (MenuItemFlags)flags;
}
}

public bool IsPopup
{
get;
set;
get
{
return (id == 0);
}
}

public bool IsSeperator
{
get
{
return (id == 0 && flags == 0 && shortcut == String.Empty);
}
}

#endregion

}

public class PopupMenuItem : MenuItem
public sealed class PopupMenuItem : MenuItem, IEnumerable<MenuItem>
{

private MenuItem[] items;

internal PopupMenuItem(ushort itemId, string itemText, ushort itemFlags, MenuItem[] subItems) : base(itemId, itemText, itemFlags)
{
items = subItems;
}

#region Methods

public IEnumerator<MenuItem> GetEnumerator()
{
for (var i = 0; i < items.Length; i++)
yield return items[i];
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

#endregion

#region Properties

public int Count
{
get
{
return items.Length;
}
}

public MenuItem this[int index]
{
get
{
return items[index];
}
}

#endregion

}
Expand Down
90 changes: 89 additions & 1 deletion Src/Workshell.PE.Resources/Menus/MenuResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,12 @@ public enum MenuSaveFormat
Resource
}

public sealed class MenuResource
public sealed class MenuResource : IEnumerable<MenuItem>
{

private Resource resource;
private uint language_id;
private MenuItem[] items;

internal MenuResource(Resource sourceResource, uint languageId, byte[] data)
{
Expand All @@ -63,7 +64,13 @@ internal MenuResource(Resource sourceResource, uint languageId, byte[] data)

using (mem)
{
ushort version = Utils.ReadUInt16(mem);
ushort header_size = Utils.ReadUInt16(mem);
List<MenuItem> menu_items = new List<MenuItem>();

LoadMenu(mem, menu_items);

items = menu_items.ToArray();
}
}

Expand Down Expand Up @@ -92,6 +99,17 @@ public static MenuResource Load(Resource resource, uint language)

#region Methods

public IEnumerator<MenuItem> GetEnumerator()
{
for (var i = 0; i < items.Length; i++)
yield return items[i];
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public void Save(string fileName)
{
Save(fileName, MenuSaveFormat.Raw);
Expand Down Expand Up @@ -136,6 +154,60 @@ private void SaveResource(Stream stream)
throw new NotImplementedException();
}

private void LoadMenu(Stream stream, List<MenuItem> items)
{
while (true)
{
ushort flags = Utils.ReadUInt16(stream);
MenuItemFlags menu_item_flags = (MenuItemFlags)flags;

if ((menu_item_flags & MenuItemFlags.Popup) == MenuItemFlags.Popup)
{
StringBuilder builder = new StringBuilder();

while (true)
{
ushort value = Utils.ReadUInt16(stream);

if (value == 0)
break;

builder.Append((char)value);
}

List<MenuItem> sub_menu_items = new List<MenuItem>();

LoadMenu(stream, sub_menu_items);

PopupMenuItem popup_menu_item = new PopupMenuItem(0, builder.ToString(), flags, sub_menu_items.ToArray());

items.Add(popup_menu_item);
}
else
{
ushort id = Utils.ReadUInt16(stream);
StringBuilder builder = new StringBuilder();

while (true)
{
ushort value = Utils.ReadUInt16(stream);

if (value == 0)
break;

builder.Append((char)value);
}

MenuItem menu_item = new MenuItem(id, builder.ToString(), flags);

items.Add(menu_item);
}

if ((menu_item_flags & MenuItemFlags.EndMenu) == MenuItemFlags.EndMenu)
break;
}
}

#endregion

#region Properties
Expand All @@ -156,6 +228,22 @@ public uint Language
}
}

public int Count
{
get
{
return items.Length;
}
}

public MenuItem this[int index]
{
get
{
return items[index];
}
}

#endregion

}
Expand Down
3 changes: 2 additions & 1 deletion Src/Workshell.PE.Resources/Workshell.PE.Resources.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Languages.cs" />
<Compile Include="LanguageIdentifiers.cs" />
<Compile Include="LocaleIdentifiers.cs" />
<Compile Include="Menus\MenuItem.cs" />
<Compile Include="Menus\MenuResource.cs" />
<Compile Include="Native\VS_FIXEDFILEINFO.cs" />
Expand Down

0 comments on commit 4c024a6

Please sign in to comment.