-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
More work on porting various resources.
- Loading branch information
Lloyd Kinsella
committed
Sep 5, 2018
1 parent
ab94e95
commit 857fd55
Showing
10 changed files
with
452 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Resources.Messages | ||
{ | ||
public sealed class MessageTable : IEnumerable<MessageTableBlock> | ||
{ | ||
private readonly MessageTableBlock[] _blocks; | ||
|
||
internal MessageTable(MessageTableResource resource, uint languageId, MessageTableBlock[] blocks) | ||
{ | ||
_blocks = blocks; | ||
|
||
Resource = resource; | ||
Language = languageId; | ||
Count = _blocks.Length; | ||
} | ||
|
||
#region Methods | ||
|
||
public IEnumerator<MessageTableBlock> GetEnumerator() | ||
{ | ||
foreach (var block in _blocks) | ||
yield return block; | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() | ||
{ | ||
return GetEnumerator(); | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
public MessageTableResource Resource { get; } | ||
public ResourceLanguage Language { get; } | ||
|
||
public int Count { get; } | ||
public MessageTableBlock this[int index] => _blocks[index]; | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Resources.Messages | ||
{ | ||
public sealed class MessageTableBlock : IEnumerable<MessageTableEntry> | ||
{ | ||
private readonly MessageTableEntry[] _entries; | ||
|
||
internal MessageTableBlock(uint lowId, uint highId, uint offsetToEntries, MessageTableEntry[] entries) | ||
{ | ||
_entries = entries; | ||
|
||
LowId = lowId; | ||
HighId = highId; | ||
OffsetToEntries = offsetToEntries; | ||
Count = _entries.Length; | ||
} | ||
|
||
#region Methods | ||
|
||
public IEnumerator<MessageTableEntry> GetEnumerator() | ||
{ | ||
foreach (var entry in _entries) | ||
yield return entry; | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() | ||
{ | ||
return GetEnumerator(); | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
public uint LowId { get; } | ||
public uint HighId { get; } | ||
public uint OffsetToEntries { get; } | ||
|
||
public int Count { get; } | ||
public MessageTableEntry this[int index] => _entries[index]; | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Resources.Messages | ||
{ | ||
public sealed class MessageTableEntry | ||
{ | ||
internal MessageTableEntry(uint id, string message, bool isUnicode) | ||
{ | ||
Id = id; | ||
Message = message; | ||
IsUnicode = isUnicode; | ||
} | ||
|
||
#region Methods | ||
|
||
public override string ToString() | ||
{ | ||
return $"0x{Id:X8}: {Message}"; | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
public uint Id { get; } | ||
public string Message { get; } | ||
public bool IsUnicode { get; } | ||
|
||
#endregion | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
src/Workshell.PE.Resources/Messages/MessageTableResource.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Workshell.PE.Extensions; | ||
using Workshell.PE.Resources.Native; | ||
|
||
namespace Workshell.PE.Resources.Messages | ||
{ | ||
public sealed class MessageTableResource : Resource | ||
{ | ||
public MessageTableResource(PortableExecutableImage image, ResourceType type, ResourceDirectoryEntry entry, ResourceId id) : base(image, type, entry, id) | ||
{ | ||
} | ||
|
||
#region Static Methods | ||
|
||
public static bool Register() | ||
{ | ||
var type = new ResourceId(ResourceType.MessageTable); | ||
|
||
return ResourceType.Register<MessageTableResource>(type); | ||
} | ||
|
||
#endregion | ||
|
||
#region Methods | ||
|
||
public MessageTable GetTable() | ||
{ | ||
return GetTable(ResourceLanguage.English.UnitedStates); | ||
} | ||
|
||
public async Task<MessageTable> GetTableAsync() | ||
{ | ||
return await GetTableAsync(ResourceLanguage.English.UnitedStates).ConfigureAwait(false); | ||
} | ||
|
||
public MessageTable GetTable(ResourceLanguage language) | ||
{ | ||
return GetTableAsync(language).GetAwaiter().GetResult(); | ||
} | ||
|
||
public async Task<MessageTable> GetTableAsync(ResourceLanguage language) | ||
{ | ||
var buffer = await GetBytesAsync(language).ConfigureAwait(false); | ||
|
||
using (var mem = new MemoryStream(buffer)) | ||
{ | ||
var tuples = new List<Tuple<uint, uint, uint>>(); | ||
var resourceData = await mem.ReadStructAsync<MESSAGE_RESOURCE_DATA>().ConfigureAwait(false); | ||
|
||
for(var i = 0; i < resourceData.NumberOfBlocks; i++) | ||
{ | ||
var block = await mem.ReadStructAsync<MESSAGE_RESOURCE_BLOCK>().ConfigureAwait(false); | ||
var tuple = new Tuple<uint, uint, uint>(block.OffsetToEntries, block.LowId, block.HighId); | ||
|
||
tuples.Add(tuple); | ||
} | ||
|
||
var blocks = new MessageTableBlock[resourceData.NumberOfBlocks]; | ||
|
||
for(var i = 0; i < tuples.Count; i++) | ||
{ | ||
var tuple = tuples[i]; | ||
|
||
mem.Seek(tuple.Item1, SeekOrigin.Begin); | ||
|
||
var count = (tuple.Item3 - tuple.Item2).ToInt32() + 1; | ||
var entries = new MessageTableEntry[count]; | ||
var id = tuple.Item2; | ||
|
||
for (var j = 0; j < count; j++) | ||
{ | ||
var resourceEntry = await mem.ReadStructAsync<MESSAGE_RESOURCE_ENTRY>().ConfigureAwait(false); | ||
var stringBuffer = await mem.ReadBytesAsync(resourceEntry.Length - sizeof(uint)).ConfigureAwait(false); | ||
var message = (resourceEntry.Flags == 0 ? Encoding.ASCII.GetString(stringBuffer) : Encoding.Unicode.GetString(stringBuffer)); | ||
var entry = new MessageTableEntry(id, message, resourceEntry.Flags != 0); | ||
|
||
entries[j] = entry; | ||
id++; | ||
} | ||
|
||
var block = new MessageTableBlock(tuple.Item2, tuple.Item3, tuple.Item1, entries); | ||
|
||
blocks[i] = block; | ||
} | ||
|
||
var table = new MessageTable(this, language, blocks); | ||
|
||
return table; | ||
} | ||
} | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Runtime.InteropServices; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Resources.Native | ||
{ | ||
[StructLayout(LayoutKind.Sequential, Pack = 1)] | ||
public struct MESSAGE_RESOURCE_DATA | ||
{ | ||
public uint NumberOfBlocks; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)] | ||
public struct MESSAGE_RESOURCE_BLOCK | ||
{ | ||
public uint LowId; | ||
public uint HighId; | ||
public uint OffsetToEntries; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)] | ||
public struct MESSAGE_RESOURCE_ENTRY | ||
{ | ||
public ushort Length; | ||
public ushort Flags; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Resources.Strings | ||
{ | ||
public sealed class StringTable : IEnumerable<StringTableEntry> | ||
{ | ||
private readonly StringTableEntry[] _entries; | ||
|
||
internal StringTable(StringTableResource resource, uint languageId, StringTableEntry[] entries) | ||
{ | ||
_entries = entries; | ||
|
||
Count = _entries.Length; | ||
Resource = resource; | ||
Language = languageId; | ||
} | ||
|
||
#region Methods | ||
|
||
public IEnumerator<StringTableEntry> GetEnumerator() | ||
{ | ||
foreach (var entry in _entries) | ||
yield return entry; | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() | ||
{ | ||
return GetEnumerator(); | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
public StringTableResource Resource { get; } | ||
public ResourceLanguage Language { get; } | ||
|
||
public int Count { get; } | ||
public StringTableEntry this[int index] => _entries[index]; | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Resources.Strings | ||
{ | ||
public sealed class StringTableEntry | ||
{ | ||
internal StringTableEntry(ushort id, string value) | ||
{ | ||
Id = id; | ||
Value = value; | ||
} | ||
|
||
#region Methods | ||
|
||
public override string ToString() | ||
{ | ||
if (Id == 0) | ||
return "(Empty)"; | ||
|
||
return $"{Id} = {Value}"; | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
public ushort Id { get; } | ||
public string Value { get; } | ||
public bool IsEmpty => (Id == 0); | ||
|
||
#endregion | ||
} | ||
} |
Oops, something went wrong.