diff --git a/BurnOutSharp.Builder/Extensions.cs b/BurnOutSharp.Builder/Extensions.cs index 0e87f1b4..1ddff617 100644 --- a/BurnOutSharp.Builder/Extensions.cs +++ b/BurnOutSharp.Builder/Extensions.cs @@ -418,6 +418,47 @@ namespace BurnOutSharp.Builder return table; } + /// + /// Read resource data as a string table resource + /// + /// Resource data entry to parse into a string table resource + /// A filled string table resource on success, null on error + public static Dictionary AsStringTable(this Models.PortableExecutable.ResourceDataEntry entry) + { + // If we have an invalid entry, just skip + if (entry?.Data == null) + return null; + + // Initialize the iterators + int offset = 0, stringIndex = 0; + + // Create the output table + var stringTable = new Dictionary(); + + // Create the string encoding + Encoding stringEncoding = (entry.Codepage != 0 ? Encoding.GetEncoding((int)entry.Codepage) : Encoding.Unicode); + + // Loop through and add + while (offset < entry.Data.Length) + { + ushort stringLength = entry.Data.ReadUInt16(ref offset); + if (stringLength == 0) + { + stringTable[stringIndex++] = "[EMPTY]"; + } + else + { + string fullEncodedString = stringEncoding.GetString(entry.Data, offset, entry.Data.Length - offset); + string stringValue = fullEncodedString.Substring(0, stringLength); + offset += stringEncoding.GetByteCount(stringValue); + stringValue = stringValue.Replace("\n", "\\n").Replace("\r", "\\r"); + stringTable[stringIndex++] = stringValue; + } + } + + return stringTable; + } + #endregion } } \ No newline at end of file diff --git a/ExecutableTest/Program.cs b/ExecutableTest/Program.cs index 9df1b1b9..129bd6ee 100644 --- a/ExecutableTest/Program.cs +++ b/ExecutableTest/Program.cs @@ -880,22 +880,16 @@ namespace ExecutableTest Console.WriteLine($"{padding}Dialog box found, not parsed yet"); break; case BurnOutSharp.Models.PortableExecutable.ResourceType.RT_STRING: - int stringIndex = 0; - Encoding stringEncoding = (entry.Codepage != 0 ? Encoding.GetEncoding((int)entry.Codepage) : Encoding.Unicode); - while (offset < entry.Data.Length) + var stringTable = entry.AsStringTable(); + if (stringTable == null) { - ushort stringLength = entry.Data.ReadUInt16(ref offset); - if (stringLength == 0) + Console.WriteLine($"{padding}String table resource found, but malformed"); + } + else + { + foreach ((int index, string stringValue) in stringTable) { - Console.WriteLine($"{padding}String entry {stringIndex++} ({stringLength}): [EMPTY]"); - } - else - { - string fullEncodedString = stringEncoding.GetString(entry.Data, offset, entry.Data.Length - offset); - string stringValue = fullEncodedString.Substring(0, stringLength); - offset += stringEncoding.GetByteCount(stringValue); - stringValue = stringValue.Replace("\n", "\\n").Replace("\r", "\\r"); - Console.WriteLine($"{padding}String entry {stringIndex++} ({stringLength}): {stringValue}"); + Console.WriteLine($"{padding}String entry {index}: {stringValue}"); } } break; @@ -907,7 +901,11 @@ namespace ExecutableTest break; case BurnOutSharp.Models.PortableExecutable.ResourceType.RT_ACCELERATOR: var acceleratorTable = entry.Data.AsAcceleratorTableResource(ref offset); - if (acceleratorTable != null) + if (acceleratorTable == null) + { + Console.WriteLine($"{padding}Accelerator table resource found, but malformed"); + } + else { for (int i = 0; i < acceleratorTable.Length; i++) {