From 93aab4eeae9eb02c1c53c8b6cc78293611083eca Mon Sep 17 00:00:00 2001 From: Lloyd Kinsella Date: Sat, 20 May 2023 00:35:50 +0100 Subject: [PATCH] Switched to using .NET6+ only to simplify things. Still dependent on System.Drawing.Common for now though. --- .../Workshell.PE.Resources.csproj | 100 ++++++++-------- .../Content/CLR/CLRMetaDataStreams.cs | 1 + .../Imports/DelayedImportAddressTables.cs | 5 + .../Content/Imports/ImportAddressTables.cs | 3 + src/Workshell.PE/Extensions/Enumerable.cs | 111 ------------------ src/Workshell.PE/Extensions/Stream.cs | 30 ++++- src/Workshell.PE/Utils.cs | 9 +- src/Workshell.PE/Workshell.PE.csproj | 8 +- tests/Workshell.PE.Tests/UtilsTests.cs | 6 +- .../Workshell.PE.Tests.csproj | 10 +- 10 files changed, 105 insertions(+), 178 deletions(-) delete mode 100644 src/Workshell.PE/Extensions/Enumerable.cs diff --git a/src/Workshell.PE.Resources/Workshell.PE.Resources.csproj b/src/Workshell.PE.Resources/Workshell.PE.Resources.csproj index 4451230..873a3e9 100644 --- a/src/Workshell.PE.Resources/Workshell.PE.Resources.csproj +++ b/src/Workshell.PE.Resources/Workshell.PE.Resources.csproj @@ -1,55 +1,55 @@ - - - - netstandard2.0;net45 - false - false - Workshell.snk - Debug;Release;CI - - - - Workshell.PE.Resources - A set of classes that extends the Workshell.PE class library to help deal with the standard resource types within an executable such as bitmaps, icons, cursors etc. - https://github.com/Workshell/pe - http://img.workshell.co.uk/logo_128.png - workshell pe executable native resources - license.txt - Workshell Ltd - Workshell Ltd - https://github.com/Workshell/pe - git - 0.0.0.1 - - - - - - - ..\..\bin\debug - TRACE - - - - ..\..\bin\release - TRACE - - + + + + net7.0;net6.0 + false + false + Workshell.snk + Debug;Release;CI + + + + Workshell.PE.Resources + A set of classes that extends the Workshell.PE class library to help deal with the standard resource types within an executable such as bitmaps, icons, cursors etc. + https://github.com/Workshell/pe + http://img.workshell.co.uk/logo_128.png + workshell pe executable native resources + license.txt + Workshell Ltd + Workshell Ltd + https://github.com/Workshell/pe + git + 0.0.0.1 + + + + + + + ..\..\bin\debug + TRACE + + + + ..\..\bin\release + TRACE + + ..\..\bin\ci TRACE;SIGNED - - - - - - - - - - + + + + + + + + + + - - - + + + diff --git a/src/Workshell.PE/Content/CLR/CLRMetaDataStreams.cs b/src/Workshell.PE/Content/CLR/CLRMetaDataStreams.cs index ecf2926..ec4ca1e 100644 --- a/src/Workshell.PE/Content/CLR/CLRMetaDataStreams.cs +++ b/src/Workshell.PE/Content/CLR/CLRMetaDataStreams.cs @@ -26,6 +26,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; + using Workshell.PE.Extensions; namespace Workshell.PE.Content diff --git a/src/Workshell.PE/Content/Imports/DelayedImportAddressTables.cs b/src/Workshell.PE/Content/Imports/DelayedImportAddressTables.cs index 0d7efe6..c19c487 100644 --- a/src/Workshell.PE/Content/Imports/DelayedImportAddressTables.cs +++ b/src/Workshell.PE/Content/Imports/DelayedImportAddressTables.cs @@ -23,6 +23,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Threading.Tasks; @@ -106,7 +107,9 @@ private static async Task GetTablesAsync(PortableExe entries.Add(entry); if (entry == 0) + { break; + } } var table = new Tuple(thunk, entries.ToArray(), dirEntry); @@ -117,7 +120,9 @@ private static async Task GetTablesAsync(PortableExe var rva = 0u; if (tables.Count > 0) + { rva = tables.MinBy(table => table.Item1).Item1; + } var imageBase = image.NTHeaders.OptionalHeader.ImageBase; var va = imageBase + rva; diff --git a/src/Workshell.PE/Content/Imports/ImportAddressTables.cs b/src/Workshell.PE/Content/Imports/ImportAddressTables.cs index d860f64..851da78 100644 --- a/src/Workshell.PE/Content/Imports/ImportAddressTables.cs +++ b/src/Workshell.PE/Content/Imports/ImportAddressTables.cs @@ -23,6 +23,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Threading.Tasks; @@ -99,7 +100,9 @@ private static async Task GetTablesAsync(PortableExecutable var rva = 0u; if (tables.Count > 0) + { rva = tables.MinBy(table => table.Item1).Item1; + } var imageBase = image.NTHeaders.OptionalHeader.ImageBase; var va = imageBase + rva; diff --git a/src/Workshell.PE/Extensions/Enumerable.cs b/src/Workshell.PE/Extensions/Enumerable.cs deleted file mode 100644 index 826b037..0000000 --- a/src/Workshell.PE/Extensions/Enumerable.cs +++ /dev/null @@ -1,111 +0,0 @@ -#region License -// Copyright(c) Workshell Ltd -// -// 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. -#endregion - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Workshell.PE.Extensions -{ - internal static class EnumerableExtensions - { - public static TSource MinBy(this IEnumerable source, Func selector) - { - return source.MinBy(selector, Comparer.Default); - } - - public static TSource MinBy(this IEnumerable source, Func selector, IComparer comparer) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - - if (selector == null) - throw new ArgumentNullException(nameof(selector)); - - if (comparer == null) - throw new ArgumentNullException(nameof(comparer)); - - using (var sourceIterator = source.GetEnumerator()) - { - if (!sourceIterator.MoveNext()) - throw new InvalidOperationException("Sequence contains no elements"); - - var min = sourceIterator.Current; - var minKey = selector(min); - - while (sourceIterator.MoveNext()) - { - var candidate = sourceIterator.Current; - var candidateProjected = selector(candidate); - - if (comparer.Compare(candidateProjected, minKey) < 0) - { - min = candidate; - minKey = candidateProjected; - } - } - - return min; - } - } - - public static TSource MaxBy(this IEnumerable source, Func selector) - { - return source.MaxBy(selector, Comparer.Default); - } - - public static TSource MaxBy(this IEnumerable source, Func selector, IComparer comparer) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - - if (selector == null) - throw new ArgumentNullException(nameof(selector)); - - if (comparer == null) - throw new ArgumentNullException(nameof(comparer)); - - using (var sourceIterator = source.GetEnumerator()) - { - if (!sourceIterator.MoveNext()) - throw new InvalidOperationException("Sequence contains no elements"); - - var max = sourceIterator.Current; - var maxKey = selector(max); - - while (sourceIterator.MoveNext()) - { - var candidate = sourceIterator.Current; - var candidateProjected = selector(candidate); - - if (comparer.Compare(candidateProjected, maxKey) > 0) - { - max = candidate; - maxKey = candidateProjected; - } - } - - return max; - } - } - } -} diff --git a/src/Workshell.PE/Extensions/Stream.cs b/src/Workshell.PE/Extensions/Stream.cs index 6c2174b..ff549ad 100644 --- a/src/Workshell.PE/Extensions/Stream.cs +++ b/src/Workshell.PE/Extensions/Stream.cs @@ -46,10 +46,14 @@ public static async Task ReadStructAsync(this Stream stream, int size, boo var numRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (!allowSmaller && numRead < size) + { throw new IOException("Could not read all of structure from stream."); + } if (numRead < size) + { return default(T); + } return Utils.Read(buffer); } @@ -73,7 +77,9 @@ public static async Task ReadInt16Async(this Stream stream) var numRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (numRead < buffer.Length) + { throw new IOException("Could not read int16 from stream."); + } return Utils.ReadInt16(buffer); } @@ -84,7 +90,9 @@ public static async Task ReadInt32Async(this Stream stream) var numRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (numRead < buffer.Length) + { throw new IOException("Could not read int32 from stream."); + } return Utils.ReadInt32(buffer); } @@ -95,7 +103,9 @@ public static async Task ReadInt64Async(this Stream stream) var numRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (numRead < buffer.Length) + { throw new IOException("Could not read int64 from stream."); + } return Utils.ReadInt64(buffer); } @@ -106,7 +116,9 @@ public static async Task ReadUInt16Async(this Stream stream) var numRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (numRead < buffer.Length) + { throw new IOException("Could not read uint16 from stream."); + } return Utils.ReadUInt16(buffer); } @@ -117,7 +129,9 @@ public static async Task ReadUInt32Async(this Stream stream) var numRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (numRead < buffer.Length) + { throw new IOException("Could not read uint32 from stream."); + } return Utils.ReadUInt32(buffer); } @@ -128,7 +142,9 @@ public static async Task ReadUInt64Async(this Stream stream) var numRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (numRead < buffer.Length) + { throw new IOException("Could not read uint64 from stream."); + } return Utils.ReadUInt64(buffer); } @@ -143,7 +159,9 @@ public static async Task ReadStringAsync(this Stream stream) var numRead = await stream.ReadAsync(buffer, 0, buffer.Length); if (numRead < 1 || buffer[0] == 0) + { break; + } builder.Append((char) buffer[0]); } @@ -157,14 +175,18 @@ public static async Task ReadStringAsync(this Stream stream, int size, b var numRead = await stream.ReadAsync(buffer, 0, buffer.Length); if (!allowSmaller && numRead < buffer.Length) + { throw new IOException("Could not read string from stream."); - + } + var builder = new StringBuilder(256); foreach(var b in buffer) { if (b == 0) + { break; + } builder.Append((char)b); } @@ -181,7 +203,9 @@ public static async Task ReadUnicodeStringAsync(this Stream stream) var value = await ReadUInt16Async(stream).ConfigureAwait(false); if (value == 0) + { break; + } builder.Append((char)value); } @@ -198,7 +222,9 @@ public static async Task ReadUnicodeStringAsync(this Stream stream, int var value = await ReadUInt16Async(stream).ConfigureAwait(false); if (value == 0) + { break; + } builder.Append((char)value); } @@ -209,7 +235,9 @@ public static async Task ReadUnicodeStringAsync(this Stream stream, int public static async Task ReadBytesAsync(this Stream stream, int count, long offset = -1) { if (offset >= 0) + { stream.Seek(offset, SeekOrigin.Begin); + } var buffer = new byte[count]; var numRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); diff --git a/src/Workshell.PE/Utils.cs b/src/Workshell.PE/Utils.cs index f81a79d..f088998 100644 --- a/src/Workshell.PE/Utils.cs +++ b/src/Workshell.PE/Utils.cs @@ -193,7 +193,14 @@ public static void Write(T structure, Stream stream, int size) where T : stru public static DateTime ConvertTimeDateStamp(uint timeDateStamp) { - var result = UnixEpoch.AddSeconds(timeDateStamp).Add(DateTimeOffset.Now.Offset); + var result = UnixEpoch.AddSeconds(timeDateStamp); + + if (result.Kind == DateTimeKind.Utc) + { + return result; + } + + result = new DateTime(result.Year, result.Month, result.Day, result.Hour, result.Minute, result.Second, DateTimeKind.Utc); return result; } diff --git a/src/Workshell.PE/Workshell.PE.csproj b/src/Workshell.PE/Workshell.PE.csproj index f7c3026..062fa02 100644 --- a/src/Workshell.PE/Workshell.PE.csproj +++ b/src/Workshell.PE/Workshell.PE.csproj @@ -1,7 +1,7 @@  - netstandard1.6;net45 + net7.0;net6.0 false false Workshell.snk @@ -44,10 +44,4 @@ - - - - - - diff --git a/tests/Workshell.PE.Tests/UtilsTests.cs b/tests/Workshell.PE.Tests/UtilsTests.cs index 49f02a0..eac3d31 100644 --- a/tests/Workshell.PE.Tests/UtilsTests.cs +++ b/tests/Workshell.PE.Tests/UtilsTests.cs @@ -145,11 +145,11 @@ public void Write_Structure_To_Stream_Succeeds() } } - [TestCase(0U, "1970-01-01T00:00:00")] - [TestCase(1573219373U, "2019-11-08T13:22:53")] + [TestCase(0U, "1970-01-01T00:00:00Z")] + [TestCase(1573219373U, "2019-11-08T13:22:53Z")] public void ConvertTimeDateStamp_Returns_Correct_DateTime(uint input, string expectedValue) { - var parsedExpectedValue = DateTime.ParseExact(expectedValue, "yyyy-MM-ddTHH:mm:ss", null); + var parsedExpectedValue = DateTime.ParseExact(expectedValue, "yyyy-MM-ddTHH:mm:ssZ", null); var output = Utils.ConvertTimeDateStamp(input); output.Should().Be(parsedExpectedValue); diff --git a/tests/Workshell.PE.Tests/Workshell.PE.Tests.csproj b/tests/Workshell.PE.Tests/Workshell.PE.Tests.csproj index 0a56a6a..8235cf5 100644 --- a/tests/Workshell.PE.Tests/Workshell.PE.Tests.csproj +++ b/tests/Workshell.PE.Tests/Workshell.PE.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + net6.0 false false Workshell.snk @@ -41,10 +41,10 @@ - - - - + + + +