diff --git a/Src/Demo Application/Program.cs b/Src/Demo Application/Program.cs index 5b7e440..c13d94f 100644 --- a/Src/Demo Application/Program.cs +++ b/Src/Demo Application/Program.cs @@ -39,13 +39,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_BITMAP); - Resource resource = types.First(t => t.Id == 32661); - BitmapResource bitmap_resource = BitmapResource.Load(resource); - - var x = bitmap_resource.ToBitmap(); - - x.Save(@"D:\test.bmp"); + ResourceType types = resources.First(t => t.Id == ResourceType.RT_VERSION); + Resource resource = types.First(); + VersionResource version = VersionResource.Load(resource); //Console.ReadKey(); } diff --git a/Src/Workshell.PE.Resources/Native/VS_FIXEDFILEINFO.cs b/Src/Workshell.PE.Resources/Native/VS_FIXEDFILEINFO.cs new file mode 100644 index 0000000..ca245bc --- /dev/null +++ b/Src/Workshell.PE.Resources/Native/VS_FIXEDFILEINFO.cs @@ -0,0 +1,58 @@ +#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.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Workshell.PE.Native +{ + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct VS_FIXEDFILEINFO + { + + public uint dwSignature; + public uint dwStrucVersion; + public uint dwFileVersionMS; + public uint dwFileVersionLS; + public uint dwProductVersionMS; + public uint dwProductVersionLS; + public uint dwFileFlagsMask; + public uint dwFileFlags; + public uint dwFileOS; + public uint dwFileType; + public uint dwFileSubtype; + public uint dwFileDateMS; + public uint dwFileDateLS; + + } + +} diff --git a/Src/Workshell.PE.Resources/Version/FixedFileInfo.cs b/Src/Workshell.PE.Resources/Version/FixedFileInfo.cs new file mode 100644 index 0000000..baa4b99 --- /dev/null +++ b/Src/Workshell.PE.Resources/Version/FixedFileInfo.cs @@ -0,0 +1,244 @@ +#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.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +using Workshell.PE.Annotations; + +namespace Workshell.PE.Native +{ + + [Flags] + public enum FileFlags : int + { + [EnumAnnotation("VS_FF_DEBUG")] + Debug = 0x00000001, + [EnumAnnotation("VS_FF_INFOINFERRED")] + InfoInferred = 0x00000010, + [EnumAnnotation("VS_FF_PATCHED")] + Patched = 0x00000004, + [EnumAnnotation("VS_FF_PRERELEASE")] + PreRelease = 0x00000002, + [EnumAnnotation("VS_FF_PRIVATEBUILD")] + PrivateBuild = 0x00000008, + [EnumAnnotation("VS_FF_SPECIALBUILD")] + SpecialBuild = 0x00000020 + } + + [Flags] + public enum FileOS : int + { + [EnumAnnotation("VOS_DOS")] + DOS = 0x00010000, + [EnumAnnotation("VOS_NT")] + NT = 0x00040000, + [EnumAnnotation("VOS__WINDOWS16")] + Win16 = 0x00000001, + [EnumAnnotation("VOS__WINDOWS32")] + Win32 = 0x00000004, + [EnumAnnotation("VOS_OS216")] + OS2_16 = 0x00020000, + [EnumAnnotation("VOS_OS232")] + OS2_32 = 0x00030000, + [EnumAnnotation("VOS__PM16")] + PM16 = 0x00000002, + [EnumAnnotation("VOS__PM32")] + PM32 = 0x00000003, + [EnumAnnotation("VOS_UNKNOWN")] + Unknown = 0x00000000, + + [EnumAnnotation("VOS_DOS_WINDOWS16")] + DOS_Win16 = 0x00010001, + [EnumAnnotation("VOS_DOS_WINDOWS32")] + DOS_Win32 = 0x00010004, + [EnumAnnotation("VOS_NT_WINDOWS32")] + NT_Win32 = 0x00040004, + [EnumAnnotation("VOS_OS216_PM16")] + OS2_PM16 = 0x00020002, + [EnumAnnotation("VOS_OS232_PM32")] + OS2_PM32 = 0x00030003 + } + + public enum FileType : int + { + [EnumAnnotation("VFT_APP")] + Application = 0x00000001, + [EnumAnnotation("VFT_DLL")] + Library = 0x00000002, + [EnumAnnotation("VFT_DRV")] + Driver = 0x00000003, + [EnumAnnotation("VFT_FONT")] + Font = 0x00000004, + [EnumAnnotation("VFT_STATIC_LIB")] + StaticLibrary = 0x00000007, + [EnumAnnotation("VFT_UNKNOWN")] + Unknown = 0x00000000, + [EnumAnnotation("VFT_VXD")] + VxD = 0x00000005 + } + + public enum DriverFileSubType : int + { + [EnumAnnotation("VFT2_DRV_COMM")] + Communications = 0x0000000A, + [EnumAnnotation("VFT2_DRV_DISPLAY")] + Display = 0x00000004, + [EnumAnnotation("VFT2_DRV_INSTALLABLE")] + Installable = 0x00000008, + [EnumAnnotation("VFT2_DRV_KEYBOARD")] + Keyboard = 0x00000002, + [EnumAnnotation("VFT2_DRV_LANGUAGE")] + Language = 0x00000003, + [EnumAnnotation("VFT2_DRV_MOUSE")] + Mouse = 0x00000005, + [EnumAnnotation("VFT2_DRV_NETWORK")] + Network = 0x00000006, + [EnumAnnotation("VFT2_DRV_PRINTER")] + Printer = 0x00000001, + [EnumAnnotation("VFT2_DRV_SOUND")] + Sound = 0x00000009, + [EnumAnnotation("VFT2_DRV_SYSTEM")] + System = 0x00000007, + [EnumAnnotation("VFT2_DRV_VERSIONED_PRINTER")] + VersionedPrinter = 0x0000000C, + [EnumAnnotation("VFT2_UNKNOWN")] + Unknown = 0x00000000 + } + + public enum FontSubType : int + { + [EnumAnnotation("VFT2_FONT_RASTER")] + Raster = 0x00000001, + [EnumAnnotation("VFT2_FONT_TRUETYPE")] + TrueType = 0x00000003, + [EnumAnnotation("VFT2_FONT_VECTOR")] + Vector = 0x00000002, + [EnumAnnotation("VFT2_UNKNOWN")] + Unknown = 0x00000000 + } + + public sealed class FixedFileInfo + { + + private VS_FIXEDFILEINFO fixed_file_info; + private Lazy file_version; + private Lazy product_version; + private Lazy file_date; + + internal FixedFileInfo(Stream stream) + { + fixed_file_info = Utils.Read(stream); + file_version = new Lazy(() => GetFileVersion()); + product_version = new Lazy(() => GetProductVersion()); + file_date = new Lazy(() => GetFileDate()); + } + + #region Methods + + private Version GetFileVersion() + { + ushort major = Utils.HiWord(fixed_file_info.dwFileVersionMS); + ushort minor = Utils.LoWord(fixed_file_info.dwFileVersionMS); + ushort build = Utils.HiWord(fixed_file_info.dwFileVersionLS); + ushort priv = Utils.LoWord(fixed_file_info.dwFileVersionLS); + + return new Version(major, minor, build, priv); + } + + private Version GetProductVersion() + { + ushort major = Utils.HiWord(fixed_file_info.dwProductVersionMS); + ushort minor = Utils.LoWord(fixed_file_info.dwProductVersionMS); + ushort build = Utils.HiWord(fixed_file_info.dwProductVersionLS); + ushort priv = Utils.LoWord(fixed_file_info.dwProductVersionLS); + + return new Version(major, minor, build, priv); + } + + private DateTime GetFileDate() + { + ulong value = Utils.MakeUInt64(fixed_file_info.dwFileDateMS, fixed_file_info.dwFileDateLS); + DateTime result = DateTime.FromFileTime(Convert.ToInt64(value)); + + return result; + } + + #endregion + + #region Properties + + public Version FileVersion + { + get + { + return file_version.Value; + } + } + + public Version ProductVersion + { + get + { + return product_version.Value; + } + } + + public DateTime FileDate + { + get + { + return file_date.Value; + } + } + + public FileOS FileOS + { + get + { + return (FileOS)fixed_file_info.dwFileOS; + } + } + + public FileType FileType + { + get + { + return (FileType)fixed_file_info.dwFileType; + } + } + + #endregion + + } + +} diff --git a/Src/Workshell.PE.Resources/Version/StringFileInfo.cs b/Src/Workshell.PE.Resources/Version/StringFileInfo.cs new file mode 100644 index 0000000..615d9e4 --- /dev/null +++ b/Src/Workshell.PE.Resources/Version/StringFileInfo.cs @@ -0,0 +1,150 @@ +#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.Extensions; + +namespace Workshell.PE +{ + + public sealed class StringFileInfo : IEnumerable + { + + private VersionResource resource; + private ushort len; + private ushort val_len; + private ushort type; + private string key; + private List tables; + + internal StringFileInfo(VersionResource versionResource, Stream stream) + { + resource = versionResource; + + int count = 0; + + len = Utils.ReadUInt16(stream); + val_len = Utils.ReadUInt16(stream); + type = Utils.ReadUInt16(stream); + + count += 3 * sizeof(ushort); + + key = Utils.ReadUnicodeString(stream); + + count += (key.Length + 1) * sizeof(ushort); + + if (stream.Position % 4 != 0) + { + Utils.ReadUInt16(stream); + + count += sizeof(ushort); + } + + tables = new List(); + + byte[] buffer = Utils.ReadBytes(stream, len - count); + MemoryStream mem = resource.Resource.Type.Resources.Image.MemoryStreamProvider.GetStream(buffer); + + using (mem) + { + while (mem.Position < mem.Length) + { + VerStringTable table = new VerStringTable(mem); + + tables.Add(table); + } + } + } + + #region Methods + + public override string ToString() + { + return String.Format("Key: {0}, Tables: {1:n0}", key, tables.Count); + } + + public IEnumerator GetEnumerator() + { + for (var i = 0; i < tables.Count; i++) + yield return tables[i]; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #endregion + + #region Properties + + public string Key + { + get + { + return key; + } + } + + public int Count + { + get + { + return tables.Count; + } + } + + public VerStringTable this[int index] + { + get + { + return tables[index]; + } + } + + public VerStringTable this[string key] + { + get + { + VerStringTable table = tables.FirstOrDefault(t => String.Compare(key, t.Key, true) == 0); + + return table; + } + } + + #endregion + + } + +} diff --git a/Src/Workshell.PE.Resources/Version/VarFileInfo.cs b/Src/Workshell.PE.Resources/Version/VarFileInfo.cs new file mode 100644 index 0000000..01134bc --- /dev/null +++ b/Src/Workshell.PE.Resources/Version/VarFileInfo.cs @@ -0,0 +1,150 @@ +#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.Extensions; + +namespace Workshell.PE +{ + + public sealed class VarFileInfo : IEnumerable + { + + private VersionResource resource; + private ushort len; + private ushort val_len; + private ushort type; + private string key; + private List vars; + + internal VarFileInfo(VersionResource versionResource, Stream stream) + { + resource = versionResource; + + int count = 0; + + len = Utils.ReadUInt16(stream); + val_len = Utils.ReadUInt16(stream); + type = Utils.ReadUInt16(stream); + + count += 3 * sizeof(ushort); + + key = Utils.ReadUnicodeString(stream); + + count += (key.Length + 1) * sizeof(ushort); + + if (stream.Position % 4 != 0) + { + Utils.ReadUInt16(stream); + + count += sizeof(ushort); + } + + vars = new List(); + + byte[] buffer = Utils.ReadBytes(stream, len - count); + MemoryStream mem = resource.Resource.Type.Resources.Image.MemoryStreamProvider.GetStream(buffer); + + using (mem) + { + while (mem.Position < mem.Length) + { + VerVar v = new VerVar(mem); + + vars.Add(v); + } + } + } + + #region Methods + + public override string ToString() + { + return String.Format("Key: {0}, Vars: {1:n0}", key, vars.Count); + } + + public IEnumerator GetEnumerator() + { + for (var i = 0; i < vars.Count; i++) + yield return vars[i]; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #endregion + + #region Properties + + public string Key + { + get + { + return key; + } + } + + public int Count + { + get + { + return vars.Count; + } + } + + public VerVar this[int index] + { + get + { + return vars[index]; + } + } + + public VerVar this[string key] + { + get + { + VerVar result = vars.FirstOrDefault(v => String.Compare(key, v.Key, true) == 0); + + return result; + } + } + + #endregion + + } + +} diff --git a/Src/Workshell.PE.Resources/Version/VerString.cs b/Src/Workshell.PE.Resources/Version/VerString.cs new file mode 100644 index 0000000..8c8f714 --- /dev/null +++ b/Src/Workshell.PE.Resources/Version/VerString.cs @@ -0,0 +1,93 @@ +#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.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Workshell.PE.Extensions; + +namespace Workshell.PE +{ + + public sealed class VerString + { + + private ushort len; + private ushort val_len; + private ushort type; + private string key; + private string value; + + internal VerString(Stream stream) + { + len = Utils.ReadUInt16(stream); + val_len = Utils.ReadUInt16(stream); + type = Utils.ReadUInt16(stream); + key = Utils.ReadUnicodeString(stream); + + if (stream.Position % 4 != 0) + Utils.ReadUInt16(stream); + + value = Utils.ReadUnicodeString(stream, val_len); + } + + #region Methods + + public override string ToString() + { + return String.Format("{0} = {1}", key, value); + } + + #endregion + + #region Properties + + public string Key + { + get + { + return key; + } + } + + public string Value + { + get + { + return value; + } + } + + #endregion + + } + +} diff --git a/Src/Workshell.PE.Resources/Version/VerStringTable.cs b/Src/Workshell.PE.Resources/Version/VerStringTable.cs new file mode 100644 index 0000000..5051d42 --- /dev/null +++ b/Src/Workshell.PE.Resources/Version/VerStringTable.cs @@ -0,0 +1,149 @@ +#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.Extensions; + +namespace Workshell.PE +{ + + public sealed class VerStringTable : IEnumerable + { + + private ushort len; + private ushort val_len; + private ushort type; + private string key; + private List strings; + + internal VerStringTable(Stream stream) + { + int count = 0; + + len = Utils.ReadUInt16(stream); + val_len = Utils.ReadUInt16(stream); + type = Utils.ReadUInt16(stream); + + count += 3 * sizeof(ushort); + + key = Utils.ReadUnicodeString(stream); + + count += (key.Length + 1) * sizeof(ushort); + + if (stream.Position % 4 != 0) + { + Utils.ReadUInt16(stream); + + count += sizeof(ushort); + } + + strings = new List(); + + byte[] buffer = Utils.ReadBytes(stream, len - count); + + using (MemoryStream mem = new MemoryStream(buffer)) + { + while (mem.Position < mem.Length) + { + VerString str = new VerString(mem); + + strings.Add(str); + + if (mem.Position % 4 != 0) + Utils.ReadUInt16(mem); + } + } + } + + #region Methods + + public IEnumerator GetEnumerator() + { + for (var i = 0; i < strings.Count; i++) + yield return strings[i]; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public override string ToString() + { + return String.Format("Count: {0:n0}", strings.Count); + } + + #endregion + + #region Properties + + public string Key + { + get + { + return key; + } + } + + public int Count + { + get + { + return strings.Count; + } + } + + public VerString this[int index] + { + get + { + return strings[index]; + } + } + + public VerString this[string key] + { + get + { + VerString str = strings.FirstOrDefault(s => String.Compare(key, s.Key, true) == 0); + + return str; + } + } + + #endregion + + } + +} diff --git a/Src/Workshell.PE.Resources/Version/VerVar.cs b/Src/Workshell.PE.Resources/Version/VerVar.cs new file mode 100644 index 0000000..085e4cd --- /dev/null +++ b/Src/Workshell.PE.Resources/Version/VerVar.cs @@ -0,0 +1,93 @@ +#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.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Workshell.PE.Extensions; + +namespace Workshell.PE +{ + + public sealed class VerVar + { + + private ushort len; + private ushort val_len; + private ushort type; + private string key; + private uint value; + + internal VerVar(Stream stream) + { + len = Utils.ReadUInt16(stream); + val_len = Utils.ReadUInt16(stream); + type = Utils.ReadUInt16(stream); + key = Utils.ReadUnicodeString(stream); + + if (stream.Position % 4 != 0) + Utils.ReadUInt16(stream); + + value = Utils.ReadUInt32(stream); + } + + #region Methods + + public override string ToString() + { + return String.Format("{0} = 0x{1:X8}", key, value); + } + + #endregion + + #region Properties + + public string Key + { + get + { + return key; + } + } + + public uint Value + { + get + { + return value; + } + } + + #endregion + + } + +} diff --git a/Src/Workshell.PE.Resources/VersionResource.cs b/Src/Workshell.PE.Resources/VersionResource.cs new file mode 100644 index 0000000..2e98b4c --- /dev/null +++ b/Src/Workshell.PE.Resources/VersionResource.cs @@ -0,0 +1,204 @@ +#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.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +using Workshell.PE.Extensions; +using Workshell.PE.Native; + +namespace Workshell.PE +{ + + public enum VersionSaveFormat + { + Raw, + Resource + } + + public sealed class VersionResource + { + + private Resource resource; + private uint language_id; + private FixedFileInfo fixed_file_info; + private StringFileInfo string_file_info; + private VarFileInfo var_file_info; + + internal VersionResource(Resource sourceResource, uint languageId, byte[] data) + { + resource = sourceResource; + language_id = languageId; + + MemoryStream mem = resource.Type.Resources.Image.MemoryStreamProvider.GetStream(data); + + using (mem) + { + ushort len = Utils.ReadUInt16(mem); + ushort val_len = Utils.ReadUInt16(mem); + ushort type = Utils.ReadUInt16(mem); + string key = Utils.ReadUnicodeString(mem); + + if (mem.Position % 4 != 0) + Utils.ReadUInt16(mem); + + fixed_file_info = new FixedFileInfo(mem); + + if (mem.Position % 4 != 0) + Utils.ReadUInt16(mem); + + string_file_info = new StringFileInfo(this, mem); + + if (mem.Position % 4 != 0) + Utils.ReadUInt16(mem); + + var_file_info = new VarFileInfo(this, mem); + } + } + + #region Static Methods + + public static VersionResource Load(Resource resource) + { + return Load(resource, Resource.DEFAULT_LANGUAGE); + } + + public static VersionResource Load(Resource resource, uint language) + { + if (!resource.Languages.Contains(language)) + return null; + + byte[] data = resource.GetBytes(language); + VersionResource result = new VersionResource(resource, language, data); + + return result; + } + + #endregion + + #region Methods + + public void Save(string fileName) + { + Save(fileName, VersionSaveFormat.Raw); + } + + public void Save(Stream stream) + { + Save(stream, VersionSaveFormat.Raw); + } + + public void Save(string fileName, VersionSaveFormat format) + { + using (FileStream file = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) + { + Save(file, format); + file.Flush(); + } + } + + public void Save(Stream stream, VersionSaveFormat format) + { + switch (format) + { + case VersionSaveFormat.Raw: + SaveRaw(stream); + break; + case VersionSaveFormat.Resource: + SaveResource(stream); + break; + } + } + + private void SaveRaw(Stream stream) + { + byte[] data = resource.GetBytes(language_id); + + stream.Write(data, 0, data.Length); + } + + private void SaveResource(Stream stream) + { + throw new NotImplementedException(); + } + + #endregion + + #region Properties + + public Resource Resource + { + get + { + return resource; + } + } + + public uint Language + { + get + { + return language_id; + } + } + + public FixedFileInfo Fixed + { + get + { + return fixed_file_info; + } + } + + public StringFileInfo Strings + { + get + { + return string_file_info; + } + } + + public VarFileInfo Vars + { + get + { + return var_file_info; + } + } + + #endregion + + } + +} diff --git a/Src/Workshell.PE.Resources/Workshell.PE.Resources.csproj b/Src/Workshell.PE.Resources/Workshell.PE.Resources.csproj index 2a690d0..5ee4696 100644 --- a/Src/Workshell.PE.Resources/Workshell.PE.Resources.csproj +++ b/Src/Workshell.PE.Resources/Workshell.PE.Resources.csproj @@ -17,7 +17,7 @@ full false ..\..\Bin\Debug\ - DEBUG;TRACE + TRACE;DEBUG;SIGNED prompt 4 @@ -25,7 +25,7 @@ pdbonly true ..\..\Bin\Release\ - TRACE + TRACE;SIGNED prompt 4 @@ -48,6 +48,10 @@ + + + + @@ -61,6 +65,10 @@ + + + + diff --git a/Src/Workshell.PE.Resources/Workshell.PE.Resources.nuspec b/Src/Workshell.PE.Resources/Workshell.PE.Resources.nuspec index e63e815..5251244 100644 --- a/Src/Workshell.PE.Resources/Workshell.PE.Resources.nuspec +++ b/Src/Workshell.PE.Resources/Workshell.PE.Resources.nuspec @@ -3,8 +3,8 @@ Workshell.PE.Resources $version$ - Workshell PE Resource Extentensions - A set of extensions for Workshell PE to help deal with resources. + Workshell PE Resource Extensions + A set of classes for Workshell PE to help deal with resources. A set of classes to help deal with resources within an executable such as bitmaps, icons and cursors. Workshell Ltd Workshell Ltd diff --git a/Src/Workshell.PE/Utils.cs b/Src/Workshell.PE/Utils.cs index 8816116..5a92254 100644 --- a/Src/Workshell.PE/Utils.cs +++ b/Src/Workshell.PE/Utils.cs @@ -216,6 +216,49 @@ public static string ReadString(Stream stream, long size) return builder.ToString(); } + public static string ReadUnicodeString(Stream stream) + { + StringBuilder builder = new StringBuilder(); + + while (true) + { + ushort value = Utils.ReadUInt16(stream); + + if (value == 0) + break; + + builder.Append((char)value); + } + + return builder.ToString(); + } + + public static string ReadUnicodeString(Stream stream, int charCount) + { + StringBuilder builder = new StringBuilder(); + + for(var i = 0; i < charCount; i++) + { + ushort value = Utils.ReadUInt16(stream); + + if (value == 0) + break; + + builder.Append((char)value); + } + + return builder.ToString(); + } + + public static byte[] ReadBytes(Stream stream, long size) + { + byte[] buffer = new byte[size]; + + stream.Read(buffer, 0, buffer.Length); + + return buffer; + } + public static byte[] ReadBytes(Stream stream, long offset, long size) { byte[] buffer = new byte[size]; @@ -426,6 +469,13 @@ public static uint LoDWord(ulong value) return Convert.ToUInt32(value & 0xFFFFFFFF); } + public static ulong MakeUInt64(uint ms, uint ls) + { + ulong result = (((ulong)ms) << 32) | ls; + + return result; + } + #endregion }