diff --git a/SabreTools.Serialization/Extensions/PortableExecutable.cs b/SabreTools.Serialization/Extensions/PortableExecutable.cs index 456885cb..ed865f3a 100644 --- a/SabreTools.Serialization/Extensions/PortableExecutable.cs +++ b/SabreTools.Serialization/Extensions/PortableExecutable.cs @@ -173,75 +173,6 @@ namespace SabreTools.Data.Extensions } } - /// - /// Read resource data as a font group - /// - /// Resource data entry to parse into a font group - /// A filled font group on success, null on error - public static FontGroupHeader? AsFontGroup(this Models.PortableExecutable.Resource.DataEntry? entry) - { - // If we have an invalid entry, just skip - if (entry?.Data is null) - return null; - - // Initialize the iterator - int offset = 0; - - // Create the output object - var fontGroupHeader = new FontGroupHeader(); - - fontGroupHeader.NumberOfFonts = entry.Data.ReadUInt16LittleEndian(ref offset); - if (fontGroupHeader.NumberOfFonts > 0) - { - fontGroupHeader.DE = new DirEntry[fontGroupHeader.NumberOfFonts]; - for (int i = 0; i < fontGroupHeader.NumberOfFonts; i++) - { - var dirEntry = new DirEntry(); - - dirEntry.FontOrdinal = entry.Data.ReadUInt16LittleEndian(ref offset); - - dirEntry.Entry = new FontDirEntry(); - dirEntry.Entry.Version = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.Size = entry.Data.ReadUInt32LittleEndian(ref offset); - dirEntry.Entry.Copyright = entry.Data.ReadBytes(ref offset, 60); - dirEntry.Entry.Type = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.Points = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.VertRes = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.HorizRes = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.Ascent = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.InternalLeading = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.ExternalLeading = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.Italic = entry.Data.ReadByte(ref offset); - dirEntry.Entry.Underline = entry.Data.ReadByte(ref offset); - dirEntry.Entry.StrikeOut = entry.Data.ReadByte(ref offset); - dirEntry.Entry.Weight = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.CharSet = entry.Data.ReadByte(ref offset); - dirEntry.Entry.PixWidth = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.PixHeight = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.PitchAndFamily = entry.Data.ReadByte(ref offset); - dirEntry.Entry.AvgWidth = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.MaxWidth = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.FirstChar = entry.Data.ReadByte(ref offset); - dirEntry.Entry.LastChar = entry.Data.ReadByte(ref offset); - dirEntry.Entry.DefaultChar = entry.Data.ReadByte(ref offset); - dirEntry.Entry.BreakChar = entry.Data.ReadByte(ref offset); - dirEntry.Entry.WidthBytes = entry.Data.ReadUInt16LittleEndian(ref offset); - dirEntry.Entry.Device = entry.Data.ReadUInt32LittleEndian(ref offset); - dirEntry.Entry.Face = entry.Data.ReadUInt32LittleEndian(ref offset); - dirEntry.Entry.Reserved = entry.Data.ReadUInt32LittleEndian(ref offset); - - // TODO: Determine how to read these two? Immediately after? - dirEntry.Entry.DeviceName = entry.Data.ReadNullTerminatedAnsiString(ref offset) ?? string.Empty; - dirEntry.Entry.FaceName = entry.Data.ReadNullTerminatedAnsiString(ref offset) ?? string.Empty; - - fontGroupHeader.DE[i] = dirEntry; - } - } - - // TODO: Implement entry parsing - return fontGroupHeader; - } - /// /// Read resource data as a string table resource /// @@ -274,20 +205,6 @@ namespace SabreTools.Data.Extensions return stringTable; } - /// - /// Read resource data as a version info resource - /// - /// Resource data entry to parse into a version info resource - /// A filled version info resource on success, null on error - public static VersionInfo? AsVersionInfo(this Models.PortableExecutable.Resource.DataEntry? entry) - { - // If we have an invalid entry, just skip - if (entry?.Data is null) - return null; - - return Serialization.Readers.PortableExecutable.ParseVersionInfo(entry.Data); - } - /// /// Parse a byte array into a ResourceHeader /// diff --git a/SabreTools.Serialization/Readers/PortableExecutable.cs b/SabreTools.Serialization/Readers/PortableExecutable.cs index 9db1f0f5..2fbf4d31 100644 --- a/SabreTools.Serialization/Readers/PortableExecutable.cs +++ b/SabreTools.Serialization/Readers/PortableExecutable.cs @@ -1287,6 +1287,22 @@ namespace SabreTools.Serialization.Readers return obj; } + /// + /// Parse a byte array into a DirEntry + /// + /// Data to parse + /// Offset into the byte array + /// A filled DirEntry on success, null on error + public static Data.Models.PortableExecutable.Resource.Entries.DirEntry ParseDirEntry(byte[] data, ref int offset) + { + var obj = new Data.Models.PortableExecutable.Resource.Entries.DirEntry(); + + obj.FontOrdinal = data.ReadUInt16LittleEndian(ref offset); + obj.Entry = ParseFontDirEntry(data, ref offset); + + return obj; + } + /// /// Parse a Stream into a ExportAddressTable /// @@ -1477,6 +1493,80 @@ namespace SabreTools.Serialization.Readers return obj; } + /// + /// Parse a byte array into a FontDirEntry + /// + /// Data to parse + /// Offset into the byte array + /// A filled FontDirEntry on success, null on error + public static Data.Models.PortableExecutable.Resource.Entries.FontDirEntry ParseFontDirEntry(byte[] data, ref int offset) + { + var obj = new Data.Models.PortableExecutable.Resource.Entries.FontDirEntry(); + + obj.Version = data.ReadUInt16LittleEndian(ref offset); + obj.Size = data.ReadUInt32LittleEndian(ref offset); + obj.Copyright = data.ReadBytes(ref offset, 60); + obj.Type = data.ReadUInt16LittleEndian(ref offset); + obj.Points = data.ReadUInt16LittleEndian(ref offset); + obj.VertRes = data.ReadUInt16LittleEndian(ref offset); + obj.HorizRes = data.ReadUInt16LittleEndian(ref offset); + obj.Ascent = data.ReadUInt16LittleEndian(ref offset); + obj.InternalLeading = data.ReadUInt16LittleEndian(ref offset); + obj.ExternalLeading = data.ReadUInt16LittleEndian(ref offset); + obj.Italic = data.ReadByte(ref offset); + obj.Underline = data.ReadByte(ref offset); + obj.StrikeOut = data.ReadByte(ref offset); + obj.Weight = data.ReadUInt16LittleEndian(ref offset); + obj.CharSet = data.ReadByte(ref offset); + obj.PixWidth = data.ReadUInt16LittleEndian(ref offset); + obj.PixHeight = data.ReadUInt16LittleEndian(ref offset); + obj.PitchAndFamily = data.ReadByte(ref offset); + obj.AvgWidth = data.ReadUInt16LittleEndian(ref offset); + obj.MaxWidth = data.ReadUInt16LittleEndian(ref offset); + obj.FirstChar = data.ReadByte(ref offset); + obj.LastChar = data.ReadByte(ref offset); + obj.DefaultChar = data.ReadByte(ref offset); + obj.BreakChar = data.ReadByte(ref offset); + obj.WidthBytes = data.ReadUInt16LittleEndian(ref offset); + obj.Device = data.ReadUInt32LittleEndian(ref offset); + obj.Face = data.ReadUInt32LittleEndian(ref offset); + obj.Reserved = data.ReadUInt32LittleEndian(ref offset); + + // TODO: Determine how to read these two? Immediately after? + obj.DeviceName = data.ReadNullTerminatedAnsiString(ref offset) ?? string.Empty; + obj.FaceName = data.ReadNullTerminatedAnsiString(ref offset) ?? string.Empty; + + return obj; + } + + /// + /// Parse a byte array into a FontGroupHeader + /// + /// Data to parse + /// Offset into the byte array + /// A filled FontGroupHeader on success, null on error + public static Data.Models.PortableExecutable.Resource.Entries.FontGroupHeader ParseFontGroupHeader(byte[] data) + { + // Initialize the iterator + int offset = 0; + + // Create the output object + var fontGroupHeader = new Data.Models.PortableExecutable.Resource.Entries.FontGroupHeader(); + + fontGroupHeader.NumberOfFonts = data.ReadUInt16LittleEndian(ref offset); + if (fontGroupHeader.NumberOfFonts > 0) + { + fontGroupHeader.DE = new Data.Models.PortableExecutable.Resource.Entries.DirEntry[fontGroupHeader.NumberOfFonts]; + for (int i = 0; i < fontGroupHeader.NumberOfFonts; i++) + { + fontGroupHeader.DE[i] = ParseDirEntry(data, ref offset); + } + } + + // TODO: Implement entry parsing + return fontGroupHeader; + } + /// /// Parse a Stream into a FunctionDefinition ///