diff --git a/SabreTools.Serialization.Test/SabreTools.Serialization.Test.csproj b/SabreTools.Serialization.Test/SabreTools.Serialization.Test.csproj
index 6c0798cc..f2175cfb 100644
--- a/SabreTools.Serialization.Test/SabreTools.Serialization.Test.csproj
+++ b/SabreTools.Serialization.Test/SabreTools.Serialization.Test.csproj
@@ -27,7 +27,7 @@
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/SabreTools.Serialization/Extensions.PortableExecutable.cs b/SabreTools.Serialization/Extensions.PortableExecutable.cs
index 2c243dfa..3036667a 100644
--- a/SabreTools.Serialization/Extensions.PortableExecutable.cs
+++ b/SabreTools.Serialization/Extensions.PortableExecutable.cs
@@ -604,7 +604,11 @@ namespace SabreTools.Serialization
#region Class resource
currentOffset = offset;
- ushort classResourceIdentifier = entry.Data.ReadUInt16(ref offset);
+ ushort classResourceIdentifier;
+ if (offset >= entry.Data.Length)
+ classResourceIdentifier = 0x0000;
+ else
+ classResourceIdentifier = entry.Data.ReadUInt16(ref offset);
offset = currentOffset;
// 0x0000 means no elements
@@ -640,7 +644,11 @@ namespace SabreTools.Serialization
#region Title resource
currentOffset = offset;
- ushort titleResourceIdentifier = entry.Data.ReadUInt16(ref offset);
+ ushort titleResourceIdentifier;
+ if (offset >= entry.Data.Length)
+ titleResourceIdentifier = 0x0000;
+ else
+ titleResourceIdentifier = entry.Data.ReadUInt16(ref offset);
offset = currentOffset;
// 0x0000 means no elements
@@ -900,7 +908,7 @@ namespace SabreTools.Serialization
if (menuHeaderExtended == null)
return null;
- menuResource.ExtendedMenuHeader = menuHeaderExtended;
+ menuResource.MenuHeader = menuHeaderExtended;
#endregion
@@ -929,7 +937,7 @@ namespace SabreTools.Serialization
}
}
- menuResource.ExtendedMenuItems = [.. extendedMenuItems];
+ menuResource.MenuItems = [.. extendedMenuItems];
#endregion
}
@@ -937,7 +945,7 @@ namespace SabreTools.Serialization
{
#region Menu header
- var menuHeader = entry.Data.ReadType(ref offset);
+ var menuHeader = entry.Data.ReadType(ref offset);
if (menuHeader == null)
return null;
@@ -1076,21 +1084,9 @@ namespace SabreTools.Serialization
// Loop through and add
while (offset < entry.Data.Length)
{
- ushort stringLength = entry.Data.ReadUInt16(ref offset);
- if (stringLength == 0)
+ string? stringValue = entry.Data.ReadPrefixedUnicodeString(ref offset);
+ if (stringValue != null)
{
- stringTable[stringIndex++] = "[EMPTY]";
- }
- else
- {
- if (stringLength * 2 > entry.Data.Length - offset)
- {
- Console.WriteLine($"{stringLength * 2} requested but {entry.Data.Length - offset} remains");
- stringLength = (ushort)((entry.Data.Length - offset) / 2);
- }
-
- string stringValue = Encoding.Unicode.GetString(entry.Data, offset, stringLength * 2);
- offset += stringLength * 2;
stringValue = stringValue.Replace("\n", "\\n").Replace("\r", newValue: "\\r");
stringTable[stringIndex++] = stringValue;
}
diff --git a/SabreTools.Serialization/Printers/PortableExecutable.cs b/SabreTools.Serialization/Printers/PortableExecutable.cs
index 25145cff..3ea201c6 100644
--- a/SabreTools.Serialization/Printers/PortableExecutable.cs
+++ b/SabreTools.Serialization/Printers/PortableExecutable.cs
@@ -1120,79 +1120,67 @@ namespace SabreTools.Serialization.Printers
if (menu.MenuHeader != null)
{
- builder.AppendLine(menu.MenuHeader.Version, $"{padding}Version");
- builder.AppendLine(menu.MenuHeader.HeaderSize, $"{padding}Header size");
+ if (menu.MenuHeader is NormalMenuHeader normalMenuHeader)
+ {
+ builder.AppendLine(normalMenuHeader.Version, $"{padding}Version");
+ builder.AppendLine(normalMenuHeader.HeaderSize, $"{padding}Header size");
+ }
+ else if (menu.MenuHeader is MenuHeaderExtended menuHeaderExtended)
+ {
+ builder.AppendLine(menuHeaderExtended.Version, $"{padding}Version");
+ builder.AppendLine(menuHeaderExtended.Offset, $"{padding}Offset");
+ builder.AppendLine(menuHeaderExtended.HelpID, $"{padding}Help ID");
+ }
+ else
+ {
+ builder.AppendLine($"{padding}Menu header found, but malformed");
+ }
builder.AppendLine();
- builder.AppendLine($"{padding}Menu items");
- builder.AppendLine($"{padding}-------------------------");
- if (menu.MenuItems == null || menu.MenuItems.Length == 0)
- {
- builder.AppendLine($"{padding}No menu items");
- return;
- }
-
- for (int i = 0; i < menu.MenuItems.Length; i++)
- {
- var menuItem = menu.MenuItems[i];
- builder.AppendLine($"{padding}Menu item {i}");
- if (menuItem == null)
- {
- builder.AppendLine($"{padding} [NULL]");
- continue;
- }
-
- if (menuItem is NormalMenuItem normalMenuItem)
- {
- builder.AppendLine($"{padding} Resource info: {normalMenuItem.NormalResInfo} (0x{normalMenuItem.NormalResInfo:X})");
- builder.AppendLine(normalMenuItem.NormalMenuText, $"{padding} Menu text");
- }
- else if (menuItem is PopupMenuItem popupMenuItem)
- {
- builder.AppendLine($"{padding} Item type: {popupMenuItem.PopupItemType} (0x{popupMenuItem.PopupItemType:X})");
- builder.AppendLine($"{padding} State: {popupMenuItem.PopupState} (0x{popupMenuItem.PopupState:X})");
- builder.AppendLine(popupMenuItem.PopupID, $"{padding} ID");
- builder.AppendLine($"{padding} Resource info: {popupMenuItem.PopupResInfo} (0x{popupMenuItem.PopupResInfo:X})");
- builder.AppendLine(popupMenuItem.PopupMenuText, $"{padding} Menu text");
- }
- }
}
- else if (menu.ExtendedMenuHeader != null)
+
+ builder.AppendLine($"{padding}Menu items");
+ builder.AppendLine($"{padding}-------------------------");
+ if (menu.MenuItems == null || menu.MenuItems.Length == 0)
{
- builder.AppendLine(menu.ExtendedMenuHeader.Version, $"{padding}Version");
- builder.AppendLine(menu.ExtendedMenuHeader.Offset, $"{padding}Offset");
- builder.AppendLine(menu.ExtendedMenuHeader.HelpID, $"{padding}Help ID");
- builder.AppendLine();
- builder.AppendLine($"{padding}Menu items");
- builder.AppendLine($"{padding}-------------------------");
- if (menu.ExtendedMenuHeader.Offset == 0
- || menu.ExtendedMenuItems == null
- || menu.ExtendedMenuItems.Length == 0)
- {
- builder.AppendLine($"{padding}No menu items");
- return;
- }
-
- for (int i = 0; i < menu.ExtendedMenuItems.Length; i++)
- {
- var menuItem = menu.ExtendedMenuItems[i];
-
- builder.AppendLine($"{padding}Menu item {i}");
- if (menuItem == null)
- {
- builder.AppendLine($"{padding} [NULL]");
- continue;
- }
-
- builder.AppendLine($"{padding} Item type: {menuItem.ItemType} (0x{menuItem.ItemType:X})");
- builder.AppendLine($"{padding} State: {menuItem.State} (0x{menuItem.State:X})");
- builder.AppendLine(menuItem.ID, $"{padding} ID");
- builder.AppendLine($"{padding} Flags: {menuItem.Flags} (0x{menuItem.Flags:X})");
- builder.AppendLine(menuItem.MenuText, $"{padding} Menu text");
- }
+ builder.AppendLine($"{padding}No menu items");
+ return;
}
- else
+
+ for (int i = 0; i < menu.MenuItems.Length; i++)
{
- builder.AppendLine($"{padding}Menu resource found, but malformed");
+ var menuItem = menu.MenuItems[i];
+ builder.AppendLine($"{padding}Menu item {i}");
+ if (menuItem == null)
+ {
+ builder.AppendLine($"{padding} [NULL]");
+ continue;
+ }
+
+ if (menuItem is NormalMenuItem normalMenuItem)
+ {
+ builder.AppendLine($"{padding} Resource info: {normalMenuItem.NormalResInfo} (0x{normalMenuItem.NormalResInfo:X})");
+ builder.AppendLine(normalMenuItem.NormalMenuText, $"{padding} Menu text");
+ }
+ else if (menuItem is PopupMenuItem popupMenuItem)
+ {
+ builder.AppendLine($"{padding} Item type: {popupMenuItem.PopupItemType} (0x{popupMenuItem.PopupItemType:X})");
+ builder.AppendLine($"{padding} State: {popupMenuItem.PopupState} (0x{popupMenuItem.PopupState:X})");
+ builder.AppendLine(popupMenuItem.PopupID, $"{padding} ID");
+ builder.AppendLine($"{padding} Resource info: {popupMenuItem.PopupResInfo} (0x{popupMenuItem.PopupResInfo:X})");
+ builder.AppendLine(popupMenuItem.PopupMenuText, $"{padding} Menu text");
+ }
+ else if (menuItem is MenuItemExtended menuItemExtended)
+ {
+ builder.AppendLine($"{padding} Item type: {menuItemExtended.ItemType} (0x{menuItemExtended.ItemType:X})");
+ builder.AppendLine($"{padding} State: {menuItemExtended.State} (0x{menuItemExtended.State:X})");
+ builder.AppendLine(menuItemExtended.ID, $"{padding} ID");
+ builder.AppendLine($"{padding} Flags: {menuItemExtended.Flags} (0x{menuItemExtended.Flags:X})");
+ builder.AppendLine(menuItemExtended.MenuText, $"{padding} Menu text");
+ }
+ else
+ {
+ builder.AppendLine($"{padding} Menu item found, but malformed");
+ }
}
}
diff --git a/SabreTools.Serialization/SabreTools.Serialization.csproj b/SabreTools.Serialization/SabreTools.Serialization.csproj
index 507aa832..a3d14218 100644
--- a/SabreTools.Serialization/SabreTools.Serialization.csproj
+++ b/SabreTools.Serialization/SabreTools.Serialization.csproj
@@ -31,7 +31,7 @@
-
+
diff --git a/SabreTools.Serialization/Wrappers/PortableExecutable.cs b/SabreTools.Serialization/Wrappers/PortableExecutable.cs
index 955a5b78..fb82a1f3 100644
--- a/SabreTools.Serialization/Wrappers/PortableExecutable.cs
+++ b/SabreTools.Serialization/Wrappers/PortableExecutable.cs
@@ -1188,68 +1188,68 @@ namespace SabreTools.Serialization.Wrappers
{
switch ((Models.PortableExecutable.ResourceType)resourceType)
{
- case SabreTools.Models.PortableExecutable.ResourceType.RT_CURSOR:
+ case Models.PortableExecutable.ResourceType.RT_CURSOR:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_BITMAP:
+ case Models.PortableExecutable.ResourceType.RT_BITMAP:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_ICON:
+ case Models.PortableExecutable.ResourceType.RT_ICON:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_MENU:
+ case Models.PortableExecutable.ResourceType.RT_MENU:
value = entry.AsMenu();
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_DIALOG:
+ case Models.PortableExecutable.ResourceType.RT_DIALOG:
value = entry.AsDialogBox();
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_STRING:
+ case Models.PortableExecutable.ResourceType.RT_STRING:
value = entry.AsStringTable();
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_FONTDIR:
+ case Models.PortableExecutable.ResourceType.RT_FONTDIR:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_FONT:
+ case Models.PortableExecutable.ResourceType.RT_FONT:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_ACCELERATOR:
+ case Models.PortableExecutable.ResourceType.RT_ACCELERATOR:
value = entry.AsAcceleratorTableResource();
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_RCDATA:
+ case Models.PortableExecutable.ResourceType.RT_RCDATA:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_MESSAGETABLE:
+ case Models.PortableExecutable.ResourceType.RT_MESSAGETABLE:
value = entry.AsMessageResourceData();
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_GROUP_CURSOR:
+ case Models.PortableExecutable.ResourceType.RT_GROUP_CURSOR:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_GROUP_ICON:
+ case Models.PortableExecutable.ResourceType.RT_GROUP_ICON:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_VERSION:
+ case Models.PortableExecutable.ResourceType.RT_VERSION:
_versionInfo = entry.AsVersionInfo();
value = _versionInfo;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_DLGINCLUDE:
+ case Models.PortableExecutable.ResourceType.RT_DLGINCLUDE:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_PLUGPLAY:
+ case Models.PortableExecutable.ResourceType.RT_PLUGPLAY:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_VXD:
+ case Models.PortableExecutable.ResourceType.RT_VXD:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_ANICURSOR:
+ case Models.PortableExecutable.ResourceType.RT_ANICURSOR:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_ANIICON:
+ case Models.PortableExecutable.ResourceType.RT_ANIICON:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_HTML:
+ case Models.PortableExecutable.ResourceType.RT_HTML:
value = entry.Data;
break;
- case SabreTools.Models.PortableExecutable.ResourceType.RT_MANIFEST:
+ case Models.PortableExecutable.ResourceType.RT_MANIFEST:
_assemblyManifest = entry.AsAssemblyManifest();
value = _versionInfo;
break;
@@ -1335,7 +1335,7 @@ namespace SabreTools.Serialization.Wrappers
/// Name of the section to check for
/// True to enable exact matching of names, false for starts-with
/// Section data on success, null on error
- public SabreTools.Models.PortableExecutable.SectionHeader? GetFirstSection(string? name, bool exact = false)
+ public Models.PortableExecutable.SectionHeader? GetFirstSection(string? name, bool exact = false)
{
// If we have no sections
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
@@ -1360,7 +1360,7 @@ namespace SabreTools.Serialization.Wrappers
/// Name of the section to check for
/// True to enable exact matching of names, false for starts-with
/// Section data on success, null on error
- public SabreTools.Models.PortableExecutable.SectionHeader? GetLastSection(string? name, bool exact = false)
+ public Models.PortableExecutable.SectionHeader? GetLastSection(string? name, bool exact = false)
{
// If we have no sections
if (SectionNames == null || !SectionNames.Any() || this.Model.SectionTable == null || !this.Model.SectionTable.Any())
@@ -1384,7 +1384,7 @@ namespace SabreTools.Serialization.Wrappers
///
/// Index of the section to check for
/// Section data on success, null on error
- public SabreTools.Models.PortableExecutable.SectionHeader? GetSection(int index)
+ public Models.PortableExecutable.SectionHeader? GetSection(int index)
{
// If we have no sections
if (this.Model.SectionTable == null || !this.Model.SectionTable.Any())