Libraries

This change looks dramatic, but it's just separating out the already-split namespaces into separate top-level folders. In theory, every single one could be built into their own Nuget package. `SabreTools.Serialization` still builds the normal Nuget package that is used by all other projects and includes all namespaces.
This commit is contained in:
Matt Nadareski
2026-03-21 16:26:56 -04:00
parent bec0aeb04c
commit 7689c6dd07
1495 changed files with 841 additions and 338 deletions

View File

@@ -0,0 +1,63 @@
namespace SabreTools.Data.Models.PortableExecutable.AttributeCertificate
{
/// <summary>
/// Attribute certificates can be associated with an image by adding an attribute
/// certificate table. The attribute certificate table is composed of a set of
/// contiguous, quadword-aligned attribute certificate entries. Zero padding is
/// inserted between the original end of the file and the beginning of the attribute
/// certificate table to achieve this alignment.
///
/// The virtual address value from the Certificate Table entry in the Optional
/// Header Data Directory is a file offset to the first attribute certificate
/// entry. Subsequent entries are accessed by advancing that entry's dwLength
/// bytes, rounded up to an 8-byte multiple, from the start of the current
/// attribute certificate entry. This continues until the sum of the rounded dwLength
/// values equals the Size value from the Certificates Table entry in the Optional
/// Header Data Directory. If the sum of the rounded dwLength values does not equal
/// the Size value, then either the attribute certificate table or the Size field
/// is corrupted.
///
/// The first certificate starts at offset 0x5000 from the start of the file on disk.
/// To advance through all the attribute certificate entries:
///
/// 1. Add the first attribute certificate's dwLength value to the starting offset.
/// 2. Round the value from step 1 up to the nearest 8-byte multiple to find the offset
/// of the second attribute certificate entry.
/// 3. Add the offset value from step 2 to the second attribute certificate entry's
/// dwLength value and round up to the nearest 8-byte multiple to determine the offset
/// of the third attribute certificate entry.
/// 4. Repeat step 3 for each successive certificate until the calculated offset equals
/// 0x6000 (0x5000 start + 0x1000 total size), which indicates that you've walked
/// the entire table.
///
/// Attribute certificate table entries can contain any certificate type, as long as
/// the entry has the correct dwLength value, a unique wRevision value, and a unique
/// wCertificateType value. The most common type of certificate table entry is a
/// WIN_CERTIFICATE structure, which is documented in Wintrust.h and discussed in
/// the remainder of this section.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class Entry
{
/// <summary>
/// Specifies the length of the attribute certificate entry.
/// </summary>
public uint Length { get; set; }
/// <summary>
/// Contains the certificate version number.
/// </summary>
public WindowsCertificateRevision Revision { get; set; }
/// <summary>
/// Specifies the type of content in Certificate.
/// </summary>
public WindowsCertificateType CertificateType { get; set; }
/// <summary>
/// Contains a certificate, such as an Authenticode signature.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#certificate-data"/>
public byte[] Certificate { get; set; } = [];
}
}

View File

@@ -0,0 +1,51 @@
namespace SabreTools.Data.Models.PortableExecutable.BaseRelocation
{
/// <summary>
/// The base relocation table contains entries for all base relocations in
/// the image. The Base Relocation Table field in the optional header data
/// directories gives the number of bytes in the base relocation table. For
/// more information, see Optional Header Data Directories (Image Only).
/// The base relocation table is divided into blocks. Each block represents
/// the base relocations for a 4K page. Each block must start on a 32-bit boundary.
///
/// The loader is not required to process base relocations that are resolved by
/// the linker, unless the load image cannot be loaded at the image base that is
/// specified in the PE header.
///
/// To apply a base relocation, the difference is calculated between the preferred
/// base address and the base where the image is actually loaded. If the image is
/// loaded at its preferred base, the difference is zero and thus the base
/// relocations do not have to be applied.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class Block
{
/// <summary>
/// The image base plus the page RVA is added to each offset to create
/// the VA where the base relocation must be applied.
/// </summary>
public uint PageRVA { get; set; }
/// <summary>
/// The total number of bytes in the base relocation block, including
/// the Page RVA and Block Size fields and the Type/Offset fields that
/// follow.
/// </summary>
public uint BlockSize { get; set; }
/// <summary>
/// The Block Size field is then followed by any number of Type or Offset
/// field entries. Each entry is a WORD (2 bytes) and has the following
/// structure:
///
/// 4 bits - Type - Stored in the high 4 bits of the WORD, a value
/// that indicates the type of base relocation to be
/// applied. For more information, see <see cref="BaseRelocationTypes"/>
/// 12 bits - Offset - Stored in the remaining 12 bits of the WORD, an
/// offset from the starting address that was specified
/// in the Page RVA field for the block. This offset
/// specifies where the base relocation is to be applied.
/// </summary>
public TypeOffsetFieldEntry[] TypeOffsetFieldEntries { get; set; } = [];
}
}

View File

@@ -0,0 +1,22 @@
namespace SabreTools.Data.Models.PortableExecutable.BaseRelocation
{
/// <summary>
/// Type or Offset field entry is a WORD (2 bytes).
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class TypeOffsetFieldEntry
{
/// <summary>
/// Stored in the high 4 bits of the WORD, a value that indicates the type
/// of base relocation to be applied. For more information, see <see cref="BaseRelocationTypes"/>
/// </summary>
public BaseRelocationTypes BaseRelocationType { get; set; }
/// <summary>
/// Stored in the remaining 12 bits of the WORD, an offset from the starting
/// address that was specified in the Page RVA field for the block. This
/// offset specifies where the base relocation is to be applied.
/// </summary>
public ushort Offset { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
namespace SabreTools.Data.Models.PortableExecutable
{
// TODO: Add more constants around sizes
// - Debug Directory entry size is a constant value of 28 (0x1C)
public static class Constants
{
public static readonly byte[] SignatureBytes = [0x50, 0x45, 0x00, 0x00];
public const string SignatureString = "PE\0\0";
public const uint SignatureUInt32 = 0x00004550;
}
}

View File

@@ -0,0 +1,29 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable
{
/// <summary>
/// Each data directory gives the address and size of a table or string that Windows uses.
/// These data directory entries are all loaded into memory so that the system can use them
/// at run time.
///
/// Also, do not assume that the RVAs in this table point to the beginning of a section or
/// that the sections that contain specific tables have specific names.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class DataDirectory
{
/// <summary>
/// The first field, VirtualAddress, is actually the RVA of the table. The RVA
/// is the address of the table relative to the base address of the image when
/// the table is loaded.
/// </summary>
public uint VirtualAddress;
/// <summary>
/// The second field gives the size in bytes.
/// </summary>
public uint Size;
}
}

View File

@@ -0,0 +1,67 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.DebugData
{
/// <summary>
/// Image files contain an optional debug directory that indicates what form
/// of debug information is present and where it is. This directory consists
/// of an array of debug directory entries whose location and size are indicated
/// in the image optional header.
///
/// The debug directory can be in a discardable .debug section (if one exists),
/// or it can be included in any other section in the image file, or not be in
/// a section at all.
///
/// Each debug directory entry identifies the location and size of a block of
/// debug information. The specified RVA can be zero if the debug information
/// is not covered by a section header (that is, it resides in the image file
/// and is not mapped into the run-time address space). If it is mapped, the
/// RVA is its address.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Entry
{
/// <summary>
/// Reserved, must be zero.
/// </summary>
public uint Characteristics;
/// <summary>
/// The time and date that the debug data was created.
/// </summary>
public uint TimeDateStamp;
/// <summary>
/// The major version number of the debug data format.
/// </summary>
public ushort MajorVersion;
/// <summary>
/// The minor version number of the debug data format.
/// </summary>
public ushort MinorVersion;
/// <summary>
/// The format of debugging information. This field enables support
/// of multiple debuggers.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public DebugType DebugType;
/// <summary>
/// The size of the debug data (not including the debug directory itself).
/// </summary>
public uint SizeOfData;
/// <summary>
/// The address of the debug data when loaded, relative to the image base.
/// </summary>
public uint AddressOfRawData;
/// <summary>
/// The file pointer to the debug data.
/// </summary>
public uint PointerToRawData;
}
}

View File

@@ -0,0 +1,44 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.DebugData
{
/// <summary>
/// PDB 2.0 files
/// </summary>
/// <see href="https://www.debuginfo.com/articles/debuginfomatch.html"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class NB10ProgramDatabase
{
/// <summary>
/// "CodeView signature, equal to “NB10”
/// </summary>
public uint Signature;
/// <summary>
/// CodeView offset. Set to 0, because debug information
/// is stored in a separate file.
/// </summary>
public uint Offset;
/// <summary>
/// The time when debug information was created (in seconds
/// since 01.01.1970)
/// </summary>
public uint Timestamp;
/// <summary>
/// Ever-incrementing value, which is initially set to 1 and
/// incremented every time when a part of the PDB file is updated
/// without rewriting the whole file.
/// </summary>
public uint Age;
/// <summary>
/// Null-terminated name of the PDB file. It can also contain full
/// or partial path to the file.
/// </summary>
/// <remarks>Is this Unicode?</remarks>
[MarshalAs(UnmanagedType.LPStr)]
public string PdbFileName = string.Empty;
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.DebugData
{
/// <summary>
/// This file describes the format of the pdb (Program Database) files of the "RSDS"
/// or "DS" type which are emitted by Miscrosoft's link.exe from version 7 and above.
/// </summary>
/// <see href="http://www.godevtool.com/Other/pdb.htm"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class RSDSProgramDatabase
{
/// <summary>
/// "RSDS" signature
/// </summary>
public uint Signature;
/// <summary>
/// 16-byte Globally Unique Identifier
/// </summary>
public Guid GUID;
/// <summary>
/// Ever-incrementing value, which is initially set to 1 and
/// incremented every time when a part of the PDB file is updated
/// without rewriting the whole file.
/// </summary>
public uint Age;
/// <summary>
/// zero terminated UTF8 path and file name
/// </summary>
#if NET472_OR_GREATER || NETCOREAPP
[MarshalAs(UnmanagedType.LPUTF8Str)]
#else
[MarshalAs(UnmanagedType.LPStr)]
#endif
public string PathAndFileName = string.Empty;
}
}

View File

@@ -0,0 +1,38 @@
namespace SabreTools.Data.Models.PortableExecutable.DebugData
{
/// <summary>
/// The .debug section is used in object files to contain compiler-generated debug
/// information and in image files to contain all of the debug information that is
/// generated. This section describes the packaging of debug information in object
/// and image files.
///
/// The next section describes the format of the debug directory, which can be
/// anywhere in the image. Subsequent sections describe the "groups" in object
/// files that contain debug information.
///
/// The default for the linker is that debug information is not mapped into the
/// address space of the image. A .debug section exists only when debug information
/// is mapped in the address space.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class Table
{
/// <summary>
/// Image files contain an optional debug directory that indicates what form
/// of debug information is present and where it is. This directory consists
/// of an array of debug directory entries whose location and size are
/// indicated in the image optional header.
///
/// The debug directory can be in a discardable .debug section (if one exists),
/// or it can be included in any other section in the image file, or not be
/// in a section at all.
///
/// Each debug directory entry identifies the location and size of a block of
/// debug information. The specified RVA can be zero if the debug information
/// is not covered by a section header (that is, it resides in the image
/// file and is not mapped into the run-time address space). If it is mapped,
/// the RVA is its address.
/// </summary>
public Entry[] DebugDirectoryTable { get; set; } = [];
}
}

View File

@@ -0,0 +1,107 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.DelayLoad
{
/// <summary>
/// The delay-load directory table is the counterpart to the import directory
/// table. It can be retrieved through the Delay Import Descriptor entry in
/// the optional header data directories list (offset 200).
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class DirectoryTable
{
/// <summary>
/// Must be zero.
/// </summary>
/// <remarks>
/// As yet, no attribute flags are defined. The linker sets this field to
/// zero in the image. This field can be used to extend the record by
/// indicating the presence of new fields, or it can be used to indicate
/// behaviors to the delay or unload helper functions.
/// </remarks>
public uint Attributes;
/// <summary>
/// The RVA of the name of the DLL to be loaded. The name resides in the
/// read-only data section of the image.
/// </summary>
/// <remarks>
/// The name of the DLL to be delay-loaded resides in the read-only data
/// section of the image. It is referenced through the szName field.
/// </remarks>
public uint NameRVA;
/// <summary>
/// The RVA of the module handle (in the data section of the image) of the DLL
/// to be delay-loaded. It is used for storage by the routine that is supplied
/// to manage delay-loading.
/// </summary>
/// <remarks>
/// The handle of the DLL to be delay-loaded is in the data section of the image.
/// The phmod field points to the handle. The supplied delay-load helper uses
/// this location to store the handle to the loaded DLL.
/// </remarks>
public uint ModuleHandle;
/// <summary>
/// The RVA of the delay-load import address table.
/// </summary>
/// <remarks>
/// The delay import address table (IAT) is referenced by the delay import
/// descriptor through the pIAT field. The delay-load helper updates these
/// pointers with the real entry points so that the thunks are no longer in
/// the calling loop. The function pointers are accessed by using the expression
/// pINT->u1.Function.
/// </remarks>
public uint DelayImportAddressTable;
/// <summary>
/// The RVA of the delay-load name table, which contains the names of the imports
/// that might need to be loaded. This matches the layout of the import name table.
/// </summary>
/// <remarks>
/// The delay import name table (INT) contains the names of the imports that might
/// require loading. They are ordered in the same fashion as the function pointers
/// in the IAT. They consist of the same structures as the standard INT and are
/// accessed by using the expression pINT->u1.AddressOfData->Name[0].
/// </remarks>
public uint DelayImportNameTable;
/// <summary>
/// The RVA of the bound delay-load address table, if it exists.
/// </summary>
/// <remarks>
/// The delay bound import address table (BIAT) is an optional table of
/// IMAGE_THUNK_DATA items that is used along with the timestamp field of the
/// delay-load directory table by a post-process binding phase.
/// </remarks>
public uint BoundDelayImportTable;
/// <summary>
/// The RVA of the unload delay-load address table, if it exists. This is an exact
/// copy of the delay import address table. If the caller unloads the DLL, this
/// table should be copied back over the delay import address table so that
/// subsequent calls to the DLL continue to use the thunking mechanism correctly.
/// </summary>
/// <remarks>
/// The delay unload import address table (UIAT) is an optional table of
/// IMAGE_THUNK_DATA items that the unload code uses to handle an explicit unload
/// request. It consists of initialized data in the read-only section that is an
/// exact copy of the original IAT that referred the code to the delay-load thunks.
/// On the unload request, the library can be freed, the *phmod cleared, and the
/// UIAT written over the IAT to restore everything to its preload state.
/// </remarks>
public uint UnloadDelayImportTable;
/// <summary>
/// The timestamp of the DLL to which this image has been bound.
/// </summary>
/// <remarks>
/// The delay bound import address table (BIAT) is an optional table of
/// IMAGE_THUNK_DATA items that is used along with the timestamp field of the
/// delay-load directory table by a post-process binding phase.
/// </remarks>
public uint TimeStamp;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,250 @@
using System.Collections.Generic;
namespace SabreTools.Data.Models.PortableExecutable
{
/// <summary>
/// The following list describes the Microsoft PE executable format, with the
/// base of the image header at the top. The section from the MS-DOS 2.0
/// Compatible EXE Header through to the unused section just before the PE header
/// is the MS-DOS 2.0 Section, and is used for MS-DOS compatibility only.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class Executable
{
/// <summary>
/// MS-DOS executable stub
/// </summary>
public MSDOS.Executable Stub { get; set; } = new();
/// <summary>
/// After the MS-DOS stub, at the file offset specified at offset 0x3c, is a 4-byte
/// signature that identifies the file as a PE format image file. This signature is "PE\0\0"
/// (the letters "P" and "E" followed by two null bytes).
/// </summary>
public string Signature { get; set; } = string.Empty;
/// <summary>
/// File header
/// </summary>
public COFF.FileHeader FileHeader { get; set; } = new();
/// <summary>
/// Microsoft extended optional header
/// </summary>
public OptionalHeader OptionalHeader { get; set; } = new();
/// <summary>
/// Section table
/// </summary>
public COFF.SectionHeader[] SectionTable { get; set; } = [];
/// <summary>
/// Symbol table
/// </summary>
public COFF.SymbolTableEntries.BaseEntry[]? SymbolTable { get; set; }
/// <summary>
/// String table
/// </summary>
public COFF.StringTable? StringTable { get; set; }
#region Data Directories
/// <summary>
/// The export data section, named .edata, contains information about symbols that other images
/// can access through dynamic linking. Exported symbols are generally found in DLLs, but DLLs
/// can also import symbols.
///
/// An overview of the general structure of the export section is described below. The tables
/// described are usually contiguous in the file in the order shown (though this is not
/// required). Only the export directory table and export address table are required to export
/// symbols as ordinals. (An ordinal is an export that is accessed directly by its export
/// address table index.) The name pointer table, ordinal table, and export name table all
/// exist to support use of export names.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
#region Export Table (.edata)
/// <summary>
/// A table with just one row (unlike the debug directory). This table indicates the
/// locations and sizes of the other export tables.
/// </summary>
public Export.DirectoryTable? ExportDirectoryTable { get; set; }
/// <summary>
/// An array of RVAs of exported symbols. These are the actual addresses of the exported
/// functions and data within the executable code and data sections. Other image files
/// can import a symbol by using an index to this table (an ordinal) or, optionally, by
/// using the public name that corresponds to the ordinal if a public name is defined.
/// </summary>
public Export.AddressTableEntry[]? ExportAddressTable { get; set; }
/// <summary>
/// An array of pointers to the public export names, sorted in ascending order.
/// </summary>
public Export.NamePointerTable? NamePointerTable { get; set; }
/// <summary>
/// An array of the ordinals that correspond to members of the name pointer table. The
/// correspondence is by position; therefore, the name pointer table and the ordinal table
/// must have the same number of members. Each ordinal is an index into the export address
/// table.
/// </summary>
public Export.OrdinalTable? OrdinalTable { get; set; }
/// <summary>
/// A series of null-terminated ASCII strings. Members of the name pointer table point into
/// this area. These names are the public names through which the symbols are imported and
/// exported; they are not necessarily the same as the private names that are used within
/// the image file.
/// </summary>
public Export.NameTable? ExportNameTable { get; set; }
#endregion
/// <summary>
/// All image files that import symbols, including virtually all executable (EXE) files,
/// have an .idata section. A typical file layout for the import information follows:
///
/// - Directory Table
/// Null Directory Entry
/// - DLL1 Import Lookup Table
/// Null
/// - DLL2 Import Lookup Table
/// Null
/// - DLL3 Import Lookup Table
/// Null
/// - Hint-Name Table
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
#region Import Table (.idata) and Import Address Table
/// <summary>
/// The import information begins with the import directory table, which describes the
/// remainder of the import information.
/// </summary>
public Import.DirectoryTableEntry[]? ImportDirectoryTable { get; set; }
/// <summary>
/// An import lookup table is an array of 32-bit numbers for PE32 or an array of 64-bit
/// numbers for PE32+.
/// </summary>
public Dictionary<int, Import.LookupTableEntry[]?>? ImportLookupTables { get; set; }
/// <summary>
/// These addresses are the actual memory addresses of the symbols, although technically
/// they are still called "virtual addresses".
/// </summary>
public Dictionary<int, Import.AddressTableEntry[]?>? ImportAddressTables { get; set; }
/// <summary>
/// One hint/name table suffices for the entire import section.
/// </summary>
public Import.HintNameTableEntry[]? HintNameTable { get; set; }
#endregion
#region Resource Table (.rsrc)
/// <summary>
/// Resource directory table (.rsrc)
/// </summary>
public Resource.DirectoryTable? ResourceDirectoryTable { get; set; }
#endregion
// TODO: Handle Exception Table
#region Certificate Table
/// <summary>
/// Attribute certificate table
/// </summary>
public AttributeCertificate.Entry[]? AttributeCertificateTable { get; set; }
#endregion
#region Base Relocation Table (.reloc)
/// <summary>
/// Base relocation table
/// </summary>
public BaseRelocation.Block[]? BaseRelocationTable { get; set; }
#endregion
#region Debug Data (.debug*)
/// <summary>
/// Debug table
/// </summary>
public DebugData.Table? DebugTable { get; set; }
#endregion
// TODO: Handle Architecture
// TODO: Handle Global Ptr
// TODO: Thread Local Storage (.tls)
// TODO: Load Configuration Table
// TODO: Bound Import Table
#region Delay Load Table
/// <summary>
/// Delay-load directory table
/// </summary>
public DelayLoad.DirectoryTable? DelayLoadDirectoryTable { get; set; }
#endregion
// TODO: CLR Runtime Header (.cormeta)
// TODO: Reserved
#endregion
#region Named Sections
// TODO: Support grouped sections in section reading and parsing
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#grouped-sections-object-only
// Grouped sections are ordered and mean that the data in the sections contributes
// to the "base" section (the one without the "$X" suffix). This may negatively impact
// the use of some of the different types of executables.
// .cormeta - CLR metadata is stored in this section. It is used to indicate that
// the object file contains managed code. The format of the metadata is not
// documented, but can be handed to the CLR interfaces for handling metadata.
// .drectve - A section is a directive section if it has the IMAGE_SCN_LNK_INFO
// flag set in the section header and has the .drectve section name. The linker
// removes a .drectve section after processing the information, so the section
// does not appear in the image file that is being linked.
//
// A .drectve section consists of a string of text that can be encoded as ANSI
// or UTF-8. If the UTF-8 byte order marker (BOM, a three-byte prefix that
// consists of 0xEF, 0xBB, and 0xBF) is not present, the directive string is
// interpreted as ANSI. The directive string is a series of linker options that
// are separated by spaces. Each option contains a hyphen, the option name, and
// any appropriate attribute. If an option contains spaces, the option must be
// enclosed in quotes. The .drectve section must not have relocations or line
// numbers.
//
// TODO: Can we implement reading/parsing the .drectve section?
// .pdata Section - Multiple formats per entry
// .sxdata - The valid exception handlers of an object are listed in the .sxdata
// section of that object. The section is marked IMAGE_SCN_LNK_INFO. It contains
// the COFF symbol index of each valid handler, using 4 bytes per index.
//
// Additionally, the compiler marks a COFF object as registered SEH by emitting
// the absolute symbol "@feat.00" with the LSB of the value field set to 1. A
// COFF object with no registered SEH handlers would have the "@feat.00" symbol,
// but no .sxdata section.
//
// TODO: Can we implement reading/parsing the .sxdata section?
#endregion
// TODO: Determine if "Archive (Library) File Format" is worth modelling
}
}

View File

@@ -0,0 +1,37 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Export
{
/// <summary>
/// The export address table contains the address of exported entry points
/// and exported data and absolutes. An ordinal number is used as an index
/// into the export address table.
///
/// Each entry in the export address table is a field that uses one of two
/// formats in the following table. If the address specified is not within
/// the export section (as defined by the address and length that are
/// indicated in the optional header), the field is an export RVA, which is
/// an actual address in code or data. Otherwise, the field is a forwarder RVA,
/// which names a symbol in another DLL.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
[StructLayout(LayoutKind.Explicit)]
public sealed class AddressTableEntry
{
/// <summary>
/// The address of the exported symbol when loaded into memory, relative to
/// the image base. For example, the address of an exported function.
/// </summary>
[FieldOffset(0)] public uint ExportRVA;
/// <summary>
/// The pointer to a null-terminated ASCII string in the export section. This
/// string must be within the range that is given by the export table data
/// directory entry. See Optional Header Data Directories (Image Only). This
/// string gives the DLL name and the name of the export (for example,
/// "MYDLL.expfunc") or the DLL name and the ordinal number of the export
/// (for example, "MYDLL.#27").
/// </summary>
[FieldOffset(0)] public uint ForwarderRVA;
}
}

View File

@@ -0,0 +1,78 @@
namespace SabreTools.Data.Models.PortableExecutable.Export
{
/// <summary>
/// The export symbol information begins with the export directory table,
/// which describes the remainder of the export symbol information. The
/// export directory table contains address information that is used to resolve
/// imports to the entry points within this image.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class DirectoryTable
{
/// <summary>
/// Reserved, must be 0.
/// </summary>
public uint ExportFlags { get; set; }
/// <summary>
/// The time and date that the export data was created.
/// </summary>
public uint TimeDateStamp { get; set; }
/// <summary>
/// The major version number. The major and minor version numbers can be set
/// by the user.
/// </summary>
public ushort MajorVersion { get; set; }
/// <summary>
/// The minor version number.
/// </summary>
public ushort MinorVersion { get; set; }
/// <summary>
/// The address of the ASCII string that contains the name of the DLL. This
/// address is relative to the image base.
/// </summary>
public uint NameRVA { get; set; }
/// <summary>
/// ASCII string that contains the name of the DLL.
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// The starting ordinal number for exports in this image. This field specifies
/// the starting ordinal number for the export address table. It is usually set
/// to 1.
/// </summary>
public uint OrdinalBase { get; set; }
/// <summary>
/// The number of entries in the export address table.
/// </summary>
public uint AddressTableEntries { get; set; }
/// <summary>
/// The number of entries in the name pointer table. This is also the number of
/// entries in the ordinal table.
/// </summary>
public uint NumberOfNamePointers { get; set; }
/// <summary>
/// The address of the export address table, relative to the image base.
/// </summary>
public uint ExportAddressTableRVA { get; set; }
/// <summary>
/// The address of the export name pointer table, relative to the image base.
/// The table size is given by the Number of Name Pointers field.
/// </summary>
public uint NamePointerRVA { get; set; }
/// <summary>
/// The address of the ordinal table, relative to the image base.
/// </summary>
public uint OrdinalTableRVA { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
namespace SabreTools.Data.Models.PortableExecutable.Export
{
/// <summary>
/// The export name pointer table is an array of addresses (RVAs) into the export name table.
/// The pointers are 32 bits each and are relative to the image base. The pointers are ordered
/// lexically to allow binary searches.
///
/// An export name is defined only if the export name pointer table contains a pointer to it.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class NamePointerTable
{
/// <summary>
/// The pointers are 32 bits each and are relative to the image base.
/// </summary>
public uint[] Pointers { get; set; } = [];
}
}

View File

@@ -0,0 +1,27 @@
namespace SabreTools.Data.Models.PortableExecutable.Export
{
/// <summary>
/// The export name table contains the actual string data that was pointed to by the export
/// name pointer table. The strings in this table are public names that other images can use
/// to import the symbols. These public export names are not necessarily the same as the
/// private symbol names that the symbols have in their own image file and source code,
/// although they can be.
///
/// Every exported symbol has an ordinal value, which is just the index into the export
/// address table. Use of export names, however, is optional. Some, all, or none of the
/// exported symbols can have export names. For exported symbols that do have export names,
/// corresponding entries in the export name pointer table and export ordinal table work
/// together to associate each name with an ordinal.
///
/// The structure of the export name table is a series of null-terminated ASCII strings
/// of variable length.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class NameTable
{
/// <summary>
/// A series of null-terminated ASCII strings of variable length.
/// </summary>
public string[] Strings { get; set; } = [];
}
}

View File

@@ -0,0 +1,42 @@
namespace SabreTools.Data.Models.PortableExecutable.Export
{
/// <summary>
/// The export ordinal table is an array of 16-bit unbiased indexes into the export address table.
/// Ordinals are biased by the Ordinal Base field of the export directory table. In other words,
/// the ordinal base must be subtracted from the ordinals to obtain true indexes into the export
/// address table.
///
/// The export name pointer table and the export ordinal table form two parallel arrays that are
/// separated to allow natural field alignment. These two tables, in effect, operate as one table,
/// in which the Export Name Pointer column points to a public (exported) name and the Export
/// Ordinal column gives the corresponding ordinal for that public name. A member of the export
/// name pointer table and a member of the export ordinal table are associated by having the same
/// position (index) in their respective arrays.
///
/// Thus, when the export name pointer table is searched and a matching string is found at position
/// i, the algorithm for finding the symbol's RVA and biased ordinal is:
///
/// i = Search_ExportNamePointerTable(name);
/// ordinal = ExportOrdinalTable[i];
///
/// rva = ExportAddressTable[ordinal];
/// biased_ordinal = ordinal + OrdinalBase;
///
/// When searching for a symbol by(biased) ordinal, the algorithm for finding the symbol's RVA
/// and name is:
///
/// ordinal = biased_ordinal - OrdinalBase;
/// i = Search_ExportOrdinalTable(ordinal);
///
/// rva = ExportAddressTable[ordinal];
/// name = ExportNameTable[i];
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class OrdinalTable
{
/// <summary>
/// An array of 16-bit unbiased indexes into the export address table
/// </summary>
public ushort[] Indexes { get; set; } = [];
}
}

View File

@@ -0,0 +1,36 @@
namespace SabreTools.Data.Models.PortableExecutable.Import
{
/// <summary>
/// The structure and content of the import address table are identical to those of
/// the import lookup table, until the file is bound. During binding, the entries in
/// the import address table are overwritten with the 32-bit (for PE32) or 64-bit
/// (for PE32+) addresses of the symbols that are being imported. These addresses are
/// the actual memory addresses of the symbols, although technically they are still
/// called "virtual addresses." The loader typically processes the binding.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class AddressTableEntry
{
/// <summary>
/// If this bit is set, import by ordinal. Otherwise, import by name. Bit is
/// masked as 0x80000000 for PE32, 0x8000000000000000 for PE32+.
/// </summary>
/// <remarks>Bit 31/63</remarks>
public bool OrdinalNameFlag { get; set; }
/// <summary>
/// A 16-bit ordinal number. This field is used only if the Ordinal/Name Flag
/// bit field is 1 (import by ordinal). Bits 30-15 or 62-15 must be 0.
/// </summary>
/// <remarks>Bits 15-0</remarks>
public ushort OrdinalNumber { get; set; }
/// <summary>
/// A 31-bit RVA of a hint/name table entry. This field is used only if the
/// Ordinal/Name Flag bit field is 0 (import by name). For PE32+ bits 62-31
/// must be zero.
/// </summary>
/// <remarks>Bits 30-0</remarks>
public uint HintNameTableRVA { get; set; }
}
}

View File

@@ -0,0 +1,50 @@
namespace SabreTools.Data.Models.PortableExecutable.Import
{
/// <summary>
/// The import information begins with the import directory table, which
/// describes the remainder of the import information. The import directory
/// table contains address information that is used to resolve fixup references
/// to the entry points within a DLL image. The import directory table consists
/// of an array of import directory entries, one entry for each DLL to which
/// the image refers. The last directory entry is empty (filled with null values),
/// which indicates the end of the directory table.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class DirectoryTableEntry
{
/// <summary>
/// The RVA of the import lookup table. This table contains a name or ordinal
/// for each import. (The name "Characteristics" is used in Winnt.h, but no
/// longer describes this field.)
/// </summary>
public uint ImportLookupTableRVA { get; set; }
/// <summary>
/// The stamp that is set to zero until the image is bound. After the image is
/// bound, this field is set to the time/data stamp of the DLL.
/// </summary>
public uint TimeDateStamp { get; set; }
/// <summary>
/// The index of the first forwarder reference.
/// </summary>
public uint ForwarderChain { get; set; }
/// <summary>
/// The address of an ASCII string that contains the name of the DLL. This address
/// is relative to the image base.
/// </summary>
public uint NameRVA { get; set; }
/// <summary>
/// ASCII string that contains the name of the DLL.
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// The RVA of the import address table. The contents of this table are identical
/// to the contents of the import lookup table until the image is bound.
/// </summary>
public uint ImportAddressTableRVA { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Import
{
/// <summary>
/// One hint/name table suffices for the entire import section.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class HintNameTableEntry
{
/// <summary>
/// An index into the export name pointer table. A match is attempted first
/// with this value. If it fails, a binary search is performed on the DLL's
/// export name pointer table.
/// </summary>
public ushort Hint;
/// <summary>
/// An ASCII string that contains the name to import. This is the string that
/// must be matched to the public name in the DLL. This string is case sensitive
/// and terminated by a null byte.
/// </summary>
[MarshalAs(UnmanagedType.LPStr)]
public string Name = string.Empty;
}
}

View File

@@ -0,0 +1,36 @@
namespace SabreTools.Data.Models.PortableExecutable.Import
{
/// <summary>
/// An import lookup table is an array of 32-bit numbers for PE32 or an array of
/// 64-bit numbers for PE32+. Each entry uses the bit-field format that is described
/// in the following table. In this format, bit 31 is the most significant bit for
/// PE32 and bit 63 is the most significant bit for PE32+. The collection of these
/// entries describes all imports from a given DLL. The last entry is set to zero
/// (NULL) to indicate the end of the table.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class LookupTableEntry
{
/// <summary>
/// If this bit is set, import by ordinal. Otherwise, import by name. Bit is
/// masked as 0x80000000 for PE32, 0x8000000000000000 for PE32+.
/// </summary>
/// <remarks>Bit 31/63</remarks>
public bool OrdinalNameFlag { get; set; }
/// <summary>
/// A 16-bit ordinal number. This field is used only if the Ordinal/Name Flag
/// bit field is 1 (import by ordinal). Bits 30-15 or 62-15 must be 0.
/// </summary>
/// <remarks>Bits 15-0</remarks>
public ushort OrdinalNumber { get; set; }
/// <summary>
/// A 31-bit RVA of a hint/name table entry. This field is used only if the
/// Ordinal/Name Flag bit field is 0 (import by name). For PE32+ bits 62-31
/// must be zero.
/// </summary>
/// <remarks>Bits 30-0</remarks>
public uint HintNameTableRVA { get; set; }
}
}

View File

@@ -0,0 +1,189 @@
namespace SabreTools.Data.Models.PortableExecutable.LoadConfiguration
{
/// <summary>
/// The data directory entry for a pre-reserved SEH load configuration
/// structure must specify a particular size of the load configuration
/// structure because the operating system loader always expects it to
/// be a certain value. In that regard, the size is really only a
/// version check. For compatibility with Windows XP and earlier versions
/// of Windows, the size must be 64 for x86 images.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class Directory
{
/// <summary>
/// Flags that indicate attributes of the file, currently unused.
/// </summary>
public uint Characteristics { get; set; }
/// <summary>
/// Date and time stamp value. The value is represented in the number of
/// seconds that have elapsed since midnight (00:00:00), January 1, 1970,
/// Universal Coordinated Time, according to the system clock. The time
/// stamp can be printed by using the C runtime (CRT) time function.
/// </summary>
public uint TimeDateStamp { get; set; }
/// <summary>
/// Major version number.
/// </summary>
public ushort MajorVersion { get; set; }
/// <summary>
/// Minor version number.
/// </summary>
public ushort MinorVersion { get; set; }
/// <summary>
/// The global loader flags to clear for this process as the loader starts
/// the process.
/// </summary>
public uint GlobalFlagsClear { get; set; }
/// <summary>
/// The global loader flags to set for this process as the loader starts
/// the process.
/// </summary>
public uint GlobalFlagsSet { get; set; }
/// <summary>
/// Memory that must be freed before it is returned to the system, in bytes.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong DeCommitFreeBlockThreshold { get; set; }
/// <summary>
/// Total amount of free memory, in bytes.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong DeCommitTotalFreeThreshold { get; set; }
/// <summary>
/// [x86 only] The VA of a list of addresses where the LOCK prefix is used so
/// that they can be replaced with NOP on single processor machines.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong LockPrefixTable { get; set; }
/// <summary>
/// Maximum allocation size, in bytes.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong MaximumAllocationSize { get; set; }
/// <summary>
/// Maximum virtual memory size, in bytes.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong VirtualMemoryThreshold { get; set; }
/// <summary>
/// Setting this field to a non-zero value is equivalent to calling
/// SetProcessAffinityMask with this value during process startup (.exe only)
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong ProcessAffinityMask { get; set; }
/// <summary>
/// Process heap flags that correspond to the first argument of the
/// HeapCreate function. These flags apply to the process heap that
/// is created during process startup.
/// </summary>
public uint ProcessHeapFlags { get; set; }
/// <summary>
/// The service pack version identifier.
/// </summary>
public ushort CSDVersion { get; set; }
/// <summary>
/// Must be zero.
/// </summary>
public ushort Reserved { get; set; }
/// <summary>
/// Reserved for use by the system.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong EditList { get; set; }
// <summary>
/// A pointer to a cookie that is used by Visual C++ or GS implementation.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong SecurityCookie { get; set; }
/// <summary>
/// [x86 only] The VA of the sorted table of RVAs of each valid, unique
/// SE handler in the image.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong SEHandlerTable { get; set; }
/// <summary>
/// [x86 only] The count of unique handlers in the table.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong SEHandlerCount { get; set; }
/// <summary>
/// The VA where Control Flow Guard check-function pointer is stored.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong GuardCFCheckFunctionPointer { get; set; }
/// <summary>
/// The VA where Control Flow Guard dispatch-function pointer is stored.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong GuardCFDispatchFunctionPointer { get; set; }
/// <summary>
/// The VA of the sorted table of RVAs of each Control Flow Guard
/// function in the image.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong GuardCFFunctionTable { get; set; }
/// <summary>
/// The count of unique RVAs in the above table.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong GuardCFFunctionCount { get; set; }
/// <summary>
/// Control Flow Guard related flags.
/// </summary>
public GuardFlags GuardFlags { get; set; }
/// <summary>
/// Code integrity information.
/// </summary>
/// <remarks>12 bytes</remarks>
public byte[] CodeIntegrity { get; set; } = new byte[12];
/// <summary>
/// The VA where Control Flow Guard address taken IAT table is stored.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong GuardAddressTakenIatEntryTable { get; set; }
/// <summary>
/// The count of unique RVAs in the above table.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong GuardAddressTakenIatEntryCount { get; set; }
/// <summary>
/// The VA where Control Flow Guard long jump target table is stored.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong GuardLongJumpTargetTable { get; set; }
/// <summary>
/// The count of unique RVAs in the above table.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong GuardLongJumpTargetCount { get; set; }
}
}

View File

@@ -0,0 +1,245 @@
namespace SabreTools.Data.Models.PortableExecutable
{
/// <summary>
/// Every image file has an optional header that provides information to the loader.
/// This header is optional in the sense that some files (specifically, object files)
/// do not have it. For image files, this header is required. An object file can have
/// an optional header, but generally this header has no function in an object file
/// except to increase its size.
///
/// Note that the size of the optional header is not fixed. The SizeOfOptionalHeader
/// field in the COFF header must be used to validate that a probe into the file for
/// a particular data directory does not go beyond SizeOfOptionalHeader.
///
/// The NumberOfRvaAndSizes field of the optional header should also be used to ensure
/// that no probe for a particular data directory entry goes beyond the optional header.
/// In addition, it is important to validate the optional header magic number for format
/// compatibility.
///
/// The optional header magic number determines whether an image is a PE32 or
/// PE32+ executable.
///
/// PE32+ images allow for a 64-bit address space while limiting the image size to
/// 2 gigabytes. Other PE32+ modifications are addressed in their respective sections.
///
/// The first eight fields of the optional header are standard fields that are defined
/// for every implementation of COFF. These fields contain general information that is
/// useful for loading and running an executable file. They are unchanged for the
/// PE32+ format.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class OptionalHeader : COFF.OptionalHeader
{
/// <summary>
/// The preferred address of the first byte of image when loaded into memory { get; set; }
/// must be a multiple of 64 K. The default for DLLs is 0x10000000. The default
/// for Windows CE EXEs is 0x00010000. The default for Windows NT, Windows 2000,
/// Windows XP, Windows 95, Windows 98, and Windows Me is 0x00400000.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong ImageBase { get; set; }
/// <summary>
/// The alignment (in bytes) of sections when they are loaded into memory. It must
/// be greater than or equal to FileAlignment. The default is the page size for
/// the architecture.
/// </summary>
public uint SectionAlignment { get; set; }
/// <summary>
/// The alignment factor (in bytes) that is used to align the raw data of sections
/// in the image file. The value should be a power of 2 between 512 and 64 K,
/// inclusive. The default is 512. If the SectionAlignment is less than the
/// architecture's page size, then FileAlignment must match SectionAlignment.
/// </summary>
public uint FileAlignment { get; set; }
/// <summary>
/// The major version number of the required operating system.
/// </summary>
public ushort MajorOperatingSystemVersion { get; set; }
/// <summary>
/// The minor version number of the required operating system.
/// </summary>
public ushort MinorOperatingSystemVersion { get; set; }
/// <summary>
/// The major version number of the image.
/// </summary>
public ushort MajorImageVersion { get; set; }
/// <summary>
/// The minor version number of the image.
/// </summary>
public ushort MinorImageVersion { get; set; }
/// <summary>
/// The major version number of the subsystem.
/// </summary>
public ushort MajorSubsystemVersion { get; set; }
/// <summary>
/// The minor version number of the subsystem.
/// </summary>
public ushort MinorSubsystemVersion { get; set; }
/// <summary>
/// Reserved, must be zero.
/// </summary>
public uint Win32VersionValue { get; set; }
/// <summary>
/// The size (in bytes) of the image, including all headers, as the image
/// is loaded in memory. It must be a multiple of SectionAlignment.
/// </summary>
public uint SizeOfImage { get; set; }
/// <summary>
/// The combined size of an MS-DOS stub, PE header, and section headers rounded
/// up to a multiple of FileAlignment.
/// </summary>
public uint SizeOfHeaders { get; set; }
/// <summary>
/// The image file checksum. The algorithm for computing the checksum is
/// incorporated into IMAGHELP.DLL. The following are checked for validation at
/// load time: all drivers, any DLL loaded at boot time, and any DLL that is
/// loaded into a critical Windows process.
/// </summary>
public uint CheckSum { get; set; }
/// <summary>
/// The subsystem that is required to run this image.
/// </summary>
public WindowsSubsystem Subsystem { get; set; }
/// <summary>
/// DLL characteristics
/// </summary>
public DllCharacteristics DllCharacteristics { get; set; }
/// <summary>
/// The size of the stack to reserve. Only SizeOfStackCommit is committed; the rest
/// is made available one page at a time until the reserve size is reached.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong SizeOfStackReserve { get; set; }
/// <summary>
/// The size of the stack to commit.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong SizeOfStackCommit { get; set; }
/// <summary>
/// The size of the local heap space to reserve. Only SizeOfHeapCommit is
/// committed; the rest is made available one page at a time until the reserve
/// size is reached.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong SizeOfHeapReserve { get; set; }
/// <summary>
/// The size of the local heap space to commit.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong SizeOfHeapCommit { get; set; }
/// <summary>
/// Reserved, must be zero.
/// </summary>
public uint LoaderFlags { get; set; }
/// <summary>
/// The number of data-directory entries in the remainder of the optional header.
/// Each describes a location and size.
/// </summary>
public uint NumberOfRvaAndSizes { get; set; }
#region Data Directories (Image Only)
/// <summary>
/// The export table address and size.
/// </summary>
public DataDirectory? ExportTable { get; set; }
/// <summary>
/// The import table address and size.
/// </summary>
public DataDirectory? ImportTable { get; set; }
/// <summary>
/// The resource table address and size.
/// </summary>
public DataDirectory? ResourceTable { get; set; }
/// <summary>
/// The exception table address and size.
/// </summary>
public DataDirectory? ExceptionTable { get; set; }
/// <summary>
/// The attribute certificate table address and size.
/// </summary>
public DataDirectory? CertificateTable { get; set; }
/// <summary>
/// The base relocation table address and size.
/// </summary>
public DataDirectory? BaseRelocationTable { get; set; }
/// <summary>
/// The debug data starting address and size.
/// </summary>
public DataDirectory? Debug { get; set; }
/// <summary>
/// Reserved, must be 0
/// </summary>
public ulong Architecture { get; set; }
/// <summary>
/// The RVA of the value to be stored in the global pointer register.
/// The size member of this structure must be set to zero.
/// </summary>
public DataDirectory? GlobalPtr { get; set; }
/// <summary>
/// The thread local storage (TLS) table address and size.
/// </summary>
public DataDirectory? ThreadLocalStorageTable { get; set; }
/// <summary>
/// The load configuration table address and size.
/// </summary>
public DataDirectory? LoadConfigTable { get; set; }
/// <summary>
/// The bound import table address and size.
/// </summary>
public DataDirectory? BoundImport { get; set; }
/// <summary>
/// The import address table address and size
/// </summary>
public DataDirectory? ImportAddressTable { get; set; }
/// <summary>
/// The delay import descriptor address and size.
/// </summary>
public DataDirectory? DelayImportDescriptor { get; set; }
/// <summary>
/// The CLR runtime header address and size.
/// </summary>
public DataDirectory? CLRRuntimeHeader { get; set; }
/// <summary>
/// Reserved, must be zero
/// </summary>
public ulong Reserved { get; set; }
#endregion
}
}

View File

@@ -0,0 +1,40 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource
{
/// <summary>
/// The resource directory string area consists of Unicode strings, which
/// are word-aligned. These strings are stored together after the last
/// Resource Directory entry and before the first Resource Data entry.
/// This minimizes the impact of these variable-length strings on the
/// alignment of the fixed-size directory entries.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class DataEntry
{
/// <summary>
/// The address of a unit of resource data in the Resource Data area.
/// </summary>
public uint DataRVA { get; set; }
/// <summary>
/// The size, in bytes, of the resource data that is pointed to by the
/// Data RVA field.
/// </summary>
public uint Size { get; set; }
/// <summary>
/// The resource data that is pointed to by the Data RVA field.
/// </summary>
public byte[] Data { get; set; } = [];
/// <summary>
/// The code page that is used to decode code point values within the
/// resource data. Typically, the code page would be the Unicode code page.
/// </summary>
public uint Codepage { get; set; }
/// <summary>
/// Reserved, must be 0.
/// </summary>
public uint Reserved { get; set; }
}
}

View File

@@ -0,0 +1,76 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource
{
/// <summary>
/// A leaf's Type, Name, and Language IDs are determined by the path that is
/// taken through directory tables to reach the leaf. The first table
/// determines Type ID, the second table (pointed to by the directory entry
/// in the first table) determines Name ID, and the third table determines
/// Language ID.
///
/// The directory entries make up the rows of a table. Each resource directory
/// entry has the following format. Whether the entry is a Name or ID entry
/// is indicated by the resource directory table, which indicates how many
/// Name and ID entries follow it (remember that all the Name entries precede
/// all the ID entries for the table). All entries for the table are sorted
/// in ascending order: the Name entries by case-sensitive string and the ID
/// entries by numeric value. Offsets are relative to the address in the
/// IMAGE_DIRECTORY_ENTRY_RESOURCE DataDirectory.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
/// <see href="https://learn.microsoft.com/en-us/previous-versions/ms809762(v=msdn.10)#pe-file-resources"/>
public sealed class DirectoryEntry
{
#region Offset 0x00
/// <summary>
/// The offset of a string that gives the Type, Name, or Language ID entry,
/// depending on level of table.
/// </summary>
/// <remarks>Must be unset if <see cref="IntegerID"/> is set</remarks>
public uint NameOffset { get; set; }
/// <summary>
/// A string that gives the Type, Name, or Language ID entry, depending on
/// level of table.
/// </summary>
/// <remarks>Only has a value if <see cref="NameOffset"/> is set</remarks>
public DirectoryString? Name { get; set; }
/// <summary>
/// A 32-bit integer that identifies the Type, Name, or Language ID entry.
/// </summary>
/// <remarks>Must be unset if <see cref="NameOffset"/> is set</remarks>
public uint IntegerID { get; set; }
#endregion
#region Offset 0x04
/// <summary>
/// High bit 0. Address of a Resource Data entry (a leaf).
/// </summary>
/// <remarks>Must be unset if <see cref="SubdirectoryOffset"/> is set</remarks>
public uint DataEntryOffset { get; set; }
/// <summary>
/// High bit 1. The lower 31 bits are the address of another resource
/// directory table (the next level down).
/// </summary>
/// <remarks>Must be unset if <see cref="DataEntryOffset"/> is set</remarks>
public uint SubdirectoryOffset { get; set; }
#endregion
/// <summary>
/// Resource data entry (a leaf).
/// </summary>
/// <remarks>Must be null if <see cref="Subdirectory"/> is set</remarks>
public DataEntry? DataEntry { get; set; }
/// <summary>
/// Another resource directory table (the next level down).
/// </summary>
/// <remarks>Must be null if <see cref="DataEntry"/> is set</remarks>
public DirectoryTable? Subdirectory { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource
{
/// <summary>
/// The resource directory string area consists of Unicode strings, which
/// are word-aligned. These strings are stored together after the last
/// Resource Directory entry and before the first Resource Data entry.
/// This minimizes the impact of these variable-length strings on the
/// alignment of the fixed-size directory entries.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class DirectoryString
{
/// <summary>
/// The size of the string, not including length field itself.
/// </summary>
public ushort Length { get; set; } // TODO: Remove in lieu of BStr
/// <summary>
/// The variable-length Unicode string data, word-aligned.
/// </summary>
public byte[] UnicodeString { get; set; } = [];
}
}

View File

@@ -0,0 +1,59 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource
{
/// <summary>
/// Each directory table is followed by a series of directory entries that
/// give the name or identifier (ID) for that level (Type, Name, or Language
/// level) and an address of either a data description or another directory
/// table. If the address points to a data description, then the data is a
/// leaf in the tree. If the address points to another directory table,
/// then that table lists directory entries at the next level down.
///
/// Each resource directory table has the following format. This data
/// structure should be considered the heading of a table because the table
/// actually consists of directory entries.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class DirectoryTable
{
/// <summary>
/// Resource flags. This field is reserved for future use. It is currently
/// set to zero.
/// </summary>
public uint Characteristics { get; set; }
/// <summary>
/// The time that the resource data was created by the resource compiler.
/// </summary>
public uint TimeDateStamp { get; set; }
/// <summary>
/// The major version number, set by the user.
/// </summary>
public ushort MajorVersion { get; set; }
/// <summary>
/// The minor version number, set by the user.
/// </summary>
public ushort MinorVersion { get; set; }
/// <summary>
/// The number of directory entries immediately following the table that use
/// strings to identify Type, Name, or Language entries (depending on the
/// level of the table).
/// </summary>
public ushort NumberOfNameEntries { get; set; }
/// <summary>
/// The number of directory entries immediately following the Name entries that
/// use numeric IDs for Type, Name, or Language entries.
/// </summary>
public ushort NumberOfIDEntries { get; set; }
/// <summary>
/// Directory entries immediately following the table that use
/// strings to identify Type, Name, or Language entries (depending on the
/// level of the table).
/// </summary>
public DirectoryEntry[] Entries { get; set; } = [];
}
}

View File

@@ -0,0 +1,19 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// The ACCELTABLEENTRY structure is repeated for all accelerator table entries in the resource.
/// The last entry in the table is flagged with the value 0x0080.
///
/// You can compute the number of elements in the table if you divide the length of the resource
/// by eight. Then your application can randomly access the individual fixed-length entries.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/acceltableentry"/>
public sealed class AcceleratorTable : ResourceDataType
{
/// <summary>
/// Accelerator table entries
/// </summary>
public AcceleratorTableEntry[] Entries { get; set; } = [];
}
}

View File

@@ -0,0 +1,35 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Describes the data in an individual accelerator table resource. The structure definition
/// provided here is for explanation only; it is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/acceltableentry"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class AcceleratorTableEntry
{
/// <summary>
/// Describes keyboard accelerator characteristics.
/// </summary>
[MarshalAs(UnmanagedType.U2)]
public AcceleratorTableFlags Flags;
/// <summary>
/// An ANSI character value or a virtual-key code that identifies the accelerator key.
/// </summary>
public ushort Ansi;
/// <summary>
/// An identifier for the keyboard accelerator. This is the value passed to the window
/// procedure when the user presses the specified key.
/// </summary>
public ushort Id;
/// <summary>
/// The number of bytes inserted to ensure that the structure is aligned on a DWORD boundary.
/// </summary>
public ushort Padding;
}
}

View File

@@ -0,0 +1,390 @@
using System.Xml.Serialization;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
[XmlRoot(ElementName = "assembly", Namespace = "urn:schemas-microsoft-com:asm.v1")]
public sealed class AssemblyManifest : ResourceDataType
{
[XmlAttribute("manifestVersion")]
public string? ManifestVersion { get; set; }
#region Group
[XmlElement("assemblyIdentity")]
public AssemblyIdentity[]? AssemblyIdentities { get; set; }
[XmlElement("noInheritable")]
public AssemblyNoInheritable[]? NoInheritables { get; set; }
#endregion
#region Group
[XmlElement("description")]
public AssemblyDescription? Description { get; set; }
[XmlElement("noInherit")]
public AssemblyNoInherit? NoInherit { get; set; }
//[XmlElement("noInheritable")]
//public AssemblyNoInheritable NoInheritable { get; set; }
[XmlElement("comInterfaceExternalProxyStub")]
public AssemblyCOMInterfaceExternalProxyStub[]? COMInterfaceExternalProxyStub { get; set; }
[XmlElement("dependency")]
public AssemblyDependency[]? Dependency { get; set; }
[XmlElement("file")]
public AssemblyFile[]? File { get; set; }
[XmlElement("clrClass")]
public AssemblyCommonLanguageRuntimeClass[]? CLRClass { get; set; }
[XmlElement("clrSurrogate")]
public AssemblyCommonLanguageSurrogateClass[]? CLRSurrogate { get; set; }
#endregion
[XmlAnyElement]
public object[]? EverythingElse { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyActiveCodePage
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyAutoElevate
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyBindingRedirect
{
[XmlAttribute("oldVersion")]
public string? OldVersion { get; set; }
[XmlAttribute("newVersion")]
public string? NewVersion { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyCOMClass
{
[XmlAttribute("clsid")]
public string? CLSID { get; set; }
[XmlAttribute("threadingModel")]
public string? ThreadingModel { get; set; }
[XmlAttribute("progid")]
public string? ProgID { get; set; }
[XmlAttribute("tlbid")]
public string? TLBID { get; set; }
[XmlAttribute("description")]
public string? Description { get; set; }
[XmlElement("progid")]
public AssemblyProgID[]? ProgIDs { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyCOMInterfaceExternalProxyStub
{
[XmlAttribute("iid")]
public string? IID { get; set; }
[XmlAttribute("name")]
public string? Name { get; set; }
[XmlAttribute("tlbid")]
public string? TLBID { get; set; }
[XmlAttribute("numMethods")]
public string? NumMethods { get; set; }
[XmlAttribute("proxyStubClsid32")]
public string? ProxyStubClsid32 { get; set; }
[XmlAttribute("baseInterface")]
public string? BaseInterface { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyCOMInterfaceProxyStub
{
[XmlAttribute("iid")]
public string? IID { get; set; }
[XmlAttribute("name")]
public string? Name { get; set; }
[XmlAttribute("tlbid")]
public string? TLBID { get; set; }
[XmlAttribute("numMethods")]
public string? NumMethods { get; set; }
[XmlAttribute("proxyStubClsid32")]
public string? ProxyStubClsid32 { get; set; }
[XmlAttribute("baseInterface")]
public string? BaseInterface { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyCommonLanguageRuntimeClass
{
[XmlAttribute("name")]
public string? Name { get; set; }
[XmlAttribute("clsid")]
public string? CLSID { get; set; }
[XmlAttribute("progid")]
public string? ProgID { get; set; }
[XmlAttribute("tlbid")]
public string? TLBID { get; set; }
[XmlAttribute("description")]
public string? Description { get; set; }
[XmlAttribute("runtimeVersion")]
public string? RuntimeVersion { get; set; }
[XmlAttribute("threadingModel")]
public string? ThreadingModel { get; set; }
[XmlElement("progid")]
public AssemblyProgID[]? ProgIDs { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyCommonLanguageSurrogateClass
{
[XmlAttribute("clsid")]
public string? CLSID { get; set; }
[XmlAttribute("name")]
public string? Name { get; set; }
[XmlAttribute("runtimeVersion")]
public string? RuntimeVersion { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyDependency
{
[XmlElement("dependentAssembly")]
public AssemblyDependentAssembly? DependentAssembly { get; set; }
[XmlAttribute("optional")]
public string? Optional { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyDependentAssembly
{
[XmlElement("assemblyIdentity")]
public AssemblyIdentity? AssemblyIdentity { get; set; }
[XmlElement("bindingRedirect")]
public AssemblyBindingRedirect[]? BindingRedirect { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyDescription
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyDisableTheming
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyDisableWindowFiltering
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyDPIAware
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyDPIAwareness
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyFile
{
[XmlAttribute("name")]
public string? Name { get; set; }
[XmlAttribute("hash")]
public string? Hash { get; set; }
[XmlAttribute("hashalg")]
public string? HashAlgorithm { get; set; }
[XmlAttribute("size")]
public string? Size { get; set; }
#region Group
[XmlElement("comClass")]
public AssemblyCOMClass[]? COMClass { get; set; }
[XmlElement("comInterfaceProxyStub")]
public AssemblyCOMInterfaceProxyStub[]? COMInterfaceProxyStub { get; set; }
[XmlElement("typelib")]
public AssemblyTypeLib[]? Typelib { get; set; }
[XmlElement("windowClass")]
public AssemblyWindowClass[]? WindowClass { get; set; }
#endregion
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyGDIScaling
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyHeapType
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyHighResolutionScrollingAware
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyIdentity
{
[XmlAttribute("name")]
public string? Name { get; set; }
[XmlAttribute("version")]
public string? Version { get; set; }
[XmlAttribute("type")]
public string? Type { get; set; }
[XmlAttribute("processorArchitecture")]
public string? ProcessorArchitecture { get; set; }
[XmlAttribute("publicKeyToken")]
public string? PublicKeyToken { get; set; }
[XmlAttribute("language")]
public string? Language { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyLongPathAware
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyNoInherit
{
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyNoInheritable
{
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyPrinterDriverIsolation
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyProgID
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblySupportedOS
{
[XmlAttribute("Id")]
public string? Id { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyTypeLib
{
[XmlElement("tlbid")]
public string? TLBID { get; set; }
[XmlElement("version")]
public string? Version { get; set; }
[XmlElement("helpdir")]
public string? HelpDir { get; set; }
[XmlElement("resourceid")]
public string? ResourceID { get; set; }
[XmlElement("flags")]
public string? Flags { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyUltraHighResolutionScrollingAware
{
[XmlText]
public string? Value { get; set; }
}
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
public sealed class AssemblyWindowClass
{
[XmlAttribute("versioned")]
public string? Versioned { get; set; }
[XmlText]
public string? Value { get; set; }
}
// TODO: Left off at <ElementType name="progid" />
}

View File

@@ -0,0 +1,40 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// The system handles each icon and cursor as a single file. However, these are stored in
/// .res files and in executable files as a group of icon resources or a group of cursor
/// resources. The file formats of icon and cursor resources are similar. In the .res file
/// a resource group header follows all of the individual icon or cursor group components.
///
/// The format of each icon component closely resembles the format of the .ico file. Each
/// icon image is stored in a BITMAPINFO structure followed by the color device-independent
/// bitmap (DIB) bits of the icon's XOR mask. The monochrome DIB bits of the icon's AND
/// mask follow the color DIB bits.
///
/// The format of each cursor component resembles the format of the .cur file. Each cursor
/// image is stored in a BITMAPINFO structure followed by the monochrome DIB bits of the
/// cursor's XOR mask, and then by the monochrome DIB bits of the cursor's AND mask. Note
/// that there is a difference in the bitmaps of the two resources: Unlike icons, cursor
/// XOR masks do not have color DIB bits. Although the bitmaps of the cursor masks are
/// monochrome and do not have DIB headers or color tables, the bits are still in DIB
/// format with respect to alignment and direction. Another significant difference
/// between cursors and icons is that cursors have a hotspot and icons do not.
///
/// The group header for both icon and cursor resources consists of a NEWHEADER structure
/// plus one or more RESDIR structures. There is one RESDIR structure for each icon or
/// cursor. The group header contains the information an application needs to select the
/// correct icon or cursor to display. Both the group header and the data that repeats for
/// each icon or cursor in the group have a fixed length. This allows the application to
/// randomly access the information.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/resource-file-formats"/>
public sealed class CursorAndIconResource
{
/// <summary>
/// Describes keyboard accelerator characteristics.
/// </summary>
public NewHeader NEWHEADER { get; set; } = new();
// TODO: Add array of entries in the resource
}
}

View File

@@ -0,0 +1,46 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// A dialog box is also one resource entry in the resource file. It consists of one
/// DLGTEMPLATE dialog box header structure plus one DLGITEMTEMPLATE structure for each
/// control in the dialog box. The DLGTEMPLATEEX and the DLGITEMTEMPLATEEX structures
/// describe the format of extended dialog box resources.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/resource-file-formats"/>
public sealed class DialogBoxResource : ResourceDataType
{
#region Dialog template
/// <summary>
/// Dialog box header structure
/// </summary>
public DialogTemplate? DialogTemplate { get; set; }
/// <summary>
/// Dialog box extended header structure
/// </summary>
public DialogTemplateExtended? ExtendedDialogTemplate { get; set; }
#endregion
#region Dialog item templates
/// <summary>
/// Following the DLGTEMPLATE header in a standard dialog box template are one or more
/// DLGITEMTEMPLATE structures that define the dimensions and style of the controls in the dialog
/// box. The cdit member specifies the number of DLGITEMTEMPLATE structures in the template.
/// These DLGITEMTEMPLATE structures must be aligned on DWORD boundaries.
/// </summary>
public DialogItemTemplate[]? DialogItemTemplates { get; set; }
/// <summary>
/// Following the DLGTEMPLATEEX header in an extended dialog box template is one or more
/// DLGITEMTEMPLATEEX structures that describe the controls of the dialog box. The cDlgItems
/// member of the DLGITEMTEMPLATEEX structure specifies the number of DLGITEMTEMPLATEEX
/// structures that follow in the template.
/// </summary>
public DialogItemTemplateExtended[]? ExtendedDialogItemTemplates { get; set; }
#endregion
}
}

View File

@@ -0,0 +1,130 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Defines the dimensions and style of a control in a dialog box. One or more of these
/// structures are combined with a DLGTEMPLATE structure to form a standard template
/// for a dialog box.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgitemtemplate"/>
public sealed class DialogItemTemplate
{
/// <summary>
/// The style of the control. This member can be a combination of window style values
/// (such as WS_BORDER) and one or more of the control style values (such as
/// BS_PUSHBUTTON and ES_LEFT).
/// </summary>
public WindowStyles Style { get; set; }
/// <summary>
/// The extended styles for a window. This member is not used to create dialog boxes,
/// but applications that use dialog box templates can use it to create other types
/// of windows.
/// </summary>
public ExtendedWindowStyles ExtendedStyle { get; set; }
/// <summary>
/// The x-coordinate, in dialog box units, of the upper-left corner of the control.
/// This coordinate is always relative to the upper-left corner of the dialog box's
/// client area.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
/// units (pixels) by using the MapDialogRect function.
/// </remarks>
public short PositionX { get; set; }
/// <summary>
/// The y-coordinate, in dialog box units, of the upper-left corner of the control.
/// This coordinate is always relative to the upper-left corner of the dialog box's
/// client area.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
/// units (pixels) by using the MapDialogRect function.
/// </remarks>
public short PositionY { get; set; }
/// <summary>
/// The width, in dialog box units, of the control.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
/// units (pixels) by using the MapDialogRect function.
/// </remarks>
public short WidthX { get; set; }
/// <summary>
/// The height, in dialog box units, of the control.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
/// units (pixels) by using the MapDialogRect function.
/// </remarks>
public short HeightY { get; set; }
/// <summary>
/// The control identifier.
/// </summary>
public ushort ID { get; set; }
// In a standard template for a dialog box, the DLGITEMTEMPLATE structure is always immediately
// followed by three variable-length arrays specifying the class, title, and creation data for
// the control. Each array consists of one or more 16-bit elements.
//
// Each DLGITEMTEMPLATE structure in the template must be aligned on a DWORD boundary. The class
// and title arrays must be aligned on WORD boundaries. The creation data array must be aligned
// on a WORD boundary.
/// <summary>
/// Immediately following each DLGITEMTEMPLATE structure is a class array that specifies the window
/// class of the control. If the first element of this array is any value other than 0xFFFF, the
/// system treats the array as a null-terminated Unicode string that specifies the name of a
/// registered window class. If the first element is 0xFFFF, the array has one additional element
/// that specifies the ordinal value of a predefined system class.
/// </summary>
/// <remarks>
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
/// </remarks>
public string ClassResource { get; set; } = string.Empty;
/// <summary>
/// The ordinal value of a predefined system class.
/// </summary>
public DialogItemTemplateOrdinal ClassResourceOrdinal { get; set; }
/// <summary>
/// Following the class array is a title array that contains the initial text or resource identifier
/// of the control. If the first element of this array is 0xFFFF, the array has one additional element
/// that specifies an ordinal value of a resource, such as an icon, in an executable file. You can use
/// a resource identifier for controls, such as static icon controls, that load and display an icon
/// or other resource rather than text. If the first element is any value other than 0xFFFF, the system
/// treats the array as a null-terminated Unicode string that specifies the initial text.
/// </summary>
/// <remarks>
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
/// </remarks>
public string TitleResource { get; set; } = string.Empty;
/// <summary>
/// An ordinal value of a resource, such as an icon, in an executable file
/// </summary>
public ushort TitleResourceOrdinal { get; set; }
/// <summary>
/// The creation data array begins at the next WORD boundary after the title array. This creation data
/// can be of any size and format. If the first word of the creation data array is nonzero, it indicates
/// the size, in bytes, of the creation data (including the size word).
/// </summary>
public ushort CreationDataSize { get; set; }
/// <summary>
/// The creation data array begins at the next WORD boundary after the title array. This creation data
/// can be of any size and format. The control's window procedure must be able to interpret the data.
/// When the system creates the control, it passes a pointer to this data in the lParam parameter of the
/// WM_CREATE message that it sends to the control.
/// </summary>
public byte[] CreationData { get; set; } = [];
}
}

View File

@@ -0,0 +1,128 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// A block of text used by an extended dialog box template to describe the extended dialog box.
/// For a description of the format of an extended dialog box template, see DLGTEMPLATEEX.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/dlgbox/dlgitemtemplateex"/>
public sealed class DialogItemTemplateExtended
{
/// <summary>
/// The help context identifier for the control. When the system sends a WM_HELP message,
/// it passes the helpID value in the dwContextId member of the HELPINFO structure.
/// </summary>
public uint HelpID { get; set; }
/// <summary>
/// The extended styles for a window. This member is not used to create controls in dialog
/// boxes, but applications that use dialog box templates can use it to create other types
/// of windows.
/// </summary>
public ExtendedWindowStyles ExtendedStyle { get; set; }
/// <summary>
/// The style of the control. This member can be a combination of window style values
/// (such as WS_BORDER) and one or more of the control style values (such as
/// BS_PUSHBUTTON and ES_LEFT).
/// </summary>
public WindowStyles Style { get; set; }
/// <summary>
/// The x-coordinate, in dialog box units, of the upper-left corner of the control.
/// This coordinate is always relative to the upper-left corner of the dialog box's
/// client area.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
/// units (pixels) by using the MapDialogRect function.
/// </remarks>
public short PositionX { get; set; }
/// <summary>
/// The y-coordinate, in dialog box units, of the upper-left corner of the control.
/// This coordinate is always relative to the upper-left corner of the dialog box's
/// client area.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
/// units (pixels) by using the MapDialogRect function.
/// </remarks>
public short PositionY { get; set; }
/// <summary>
/// The width, in dialog box units, of the control.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
/// units (pixels) by using the MapDialogRect function.
/// </remarks>
public short WidthX { get; set; }
/// <summary>
/// The height, in dialog box units, of the control.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
/// units (pixels) by using the MapDialogRect function.
/// </remarks>
public short HeightY { get; set; }
/// <summary>
/// The control identifier.
/// </summary>
public uint ID { get; set; }
/// <summary>
/// A variable-length array of 16-bit elements that specifies the window class of the control. If
/// the first element of this array is any value other than 0xFFFF, the system treats the array as
/// a null-terminated Unicode string that specifies the name of a registered window class.
///
/// If the first element is 0xFFFF, the array has one additional element that specifies the ordinal
/// value of a predefined system class.
/// </summary>
/// <remarks>
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
/// </remarks>
public string ClassResource { get; set; } = string.Empty;
/// <summary>
/// The ordinal value of a predefined system class.
/// </summary>
public DialogItemTemplateOrdinal ClassResourceOrdinal { get; set; }
/// <summary>
/// A variable-length array of 16-bit elements that contains the initial text or resource identifier of the
/// control. If the first element of this array is 0xFFFF, the array has one additional element that
/// specifies the ordinal value of a resource, such as an icon, in an executable file. You can use a
/// resource identifier for controls, such as static icon controls, that load and display an icon or other
/// resource rather than text. If the first element is any value other than 0xFFFF, the system treats the
/// array as a null-terminated Unicode string that specifies the initial text.
/// </summary>
/// <remarks>
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
/// </remarks>
public string TitleResource { get; set; } = string.Empty;
/// <summary>
/// An ordinal value of a resource, such as an icon, in an executable file
/// </summary>
public ushort TitleResourceOrdinal { get; set; }
/// <summary>
/// The creation data array begins at the next WORD boundary after the title array. This creation data
/// can be of any size and format. If the first word of the creation data array is nonzero, it indicates
/// the size, in bytes, of the creation data (including the size word).
/// </summary>
public ushort CreationDataSize { get; set; }
/// <summary>
/// The creation data array begins at the next WORD boundary after the title array. This creation data
/// can be of any size and format. The control's window procedure must be able to interpret the data.
/// When the system creates the control, it passes a pointer to this data in the lParam parameter of the
/// WM_CREATE message that it sends to the control.
/// </summary>
public byte[] CreationData { get; set; } = [];
}
}

View File

@@ -0,0 +1,160 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Defines the dimensions and style of a dialog box. This structure, always the first
/// in a standard template for a dialog box, also specifies the number of controls in
/// the dialog box and therefore specifies the number of subsequent DLGITEMTEMPLATE
/// structures in the template.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgtemplate"/>
public sealed class DialogTemplate
{
/// <summary>
/// The style of the dialog box. This member can be a combination of window style
/// values (such as WS_CAPTION and WS_SYSMENU) and dialog box style values (such
/// as DS_CENTER).
///
/// If the style member includes the DS_SETFONT style, the header of the dialog box
/// template contains additional data specifying the font to use for text in the
/// client area and controls of the dialog box. The font data begins on the WORD
/// boundary that follows the title array. The font data specifies a 16-bit point
/// size value and a Unicode font name string. If possible, the system creates a
/// font according to the specified values. Then the system sends a WM_SETFONT
/// message to the dialog box and to each control to provide a handle to the font.
/// If DS_SETFONT is not specified, the dialog box template does not include the
/// font data.
///
/// The DS_SHELLFONT style is not supported in the DLGTEMPLATE header.
/// </summary>
public WindowStyles Style { get; set; }
/// <summary>
/// The extended styles for a window. This member is not used to create dialog boxes,
/// but applications that use dialog box templates can use it to create other types
/// of windows.
/// </summary>
public ExtendedWindowStyles ExtendedStyle { get; set; }
/// <summary>
/// The number of items in the dialog box.
/// </summary>
public ushort ItemCount { get; set; }
/// <summary>
/// The x-coordinate, in dialog box units, of the upper-left corner of the dialog box.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
/// to screen units (pixels) by using the MapDialogRect function.
/// </remarks>
public short PositionX { get; set; }
/// <summary>
/// The y-coordinate, in dialog box units, of the upper-left corner of the dialog box.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
/// to screen units (pixels) by using the MapDialogRect function.
/// </remarks>
public short PositionY { get; set; }
/// <summary>
/// The width, in dialog box units, of the dialog box.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
/// to screen units (pixels) by using the MapDialogRect function.
/// </remarks>
public short WidthX { get; set; }
/// <summary>
/// The height, in dialog box units, of the dialog box.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
/// to screen units (pixels) by using the MapDialogRect function.
/// </remarks>
public short HeightY { get; set; }
// In a standard template for a dialog box, the DLGTEMPLATE structure is always immediately
// followed by three variable-length arrays that specify the menu, class, and title for the
// dialog box. When the DS_SETFONT style is specified, these arrays are also followed by a
// 16-bit value specifying point size and another variable-length array specifying a
// typeface name. Each array consists of one or more 16-bit elements. The menu, class, title,
// and font arrays must be aligned on WORD boundaries.
/// <summary>
/// Immediately following the DLGTEMPLATE structure is a menu array that identifies a menu
/// resource for the dialog box. If the first element of this array is 0x0000, the dialog box
/// has no menu and the array has no other elements. If the first element is 0xFFFF, the array
/// has one additional element that specifies the ordinal value of a menu resource in an
/// executable file. If the first element has any other value, the system treats the array as
/// a null-terminated Unicode string that specifies the name of a menu resource in an executable
/// file.
/// </summary>
/// <remarks>
/// If you specify character strings in the menu, class, title, or typeface arrays, you must use
/// Unicode strings.
/// </remarks>
public string MenuResource { get; set; } = string.Empty;
/// <summary>
/// The ordinal value of a menu resource in an executable file.
/// </summary>
public ushort MenuResourceOrdinal { get; set; }
/// <summary>
/// Following the menu array is a class array that identifies the window class of the dialog box.
/// If the first element of the array is 0x0000, the system uses the predefined dialog box class
/// for the dialog box and the array has no other elements. If the first element is 0xFFFF,
/// the array has one additional element that specifies the ordinal value of a predefined system
/// window class. If the first element has any other value, the system treats the array as a
/// null-terminated Unicode string that specifies the name of a registered window class.
/// </summary>
/// <remarks>
/// If you specify character strings in the menu, class, title, or typeface arrays, you must use
/// Unicode strings.
/// </remarks>
public string ClassResource { get; set; } = string.Empty;
/// <summary>
/// The ordinal value of a predefined system class.
/// </summary>
public ushort ClassResourceOrdinal { get; set; }
/// <summary>
/// Following the class array is a title array that specifies a null-terminated Unicode string
/// that contains the title of the dialog box. If the first element of this array is 0x0000,
/// the dialog box has no title and the array has no other elements.
/// </summary>
/// <remarks>
/// If you specify character strings in the menu, class, title, or typeface arrays, you must use
/// Unicode strings.
/// </remarks>
public string TitleResource { get; set; } = string.Empty;
/// <summary>
/// The 16-bit point size value and the typeface array follow the title array, but only if the
/// style member specifies the DS_SETFONT style. The point size value specifies the point size
/// of the font to use for the text in the dialog box and its controls. When these values are
/// specified, the system creates a font having the specified size and typeface (if possible)
/// and sends a WM_SETFONT message to the dialog box procedure and the control window
/// procedures as it creates the dialog box and controls.
/// </summary>
public ushort PointSizeValue { get; set; }
/// <summary>
/// The 16-bit point size value and the typeface array follow the title array, but only if the
/// style member specifies the DS_SETFONT style. The typeface array is a null-terminated Unicode
/// string specifying the name of the typeface for the font. When these values are specified,
/// the system creates a font having the specified size and typeface (if possible) and sends a
/// WM_SETFONT message to the dialog box procedure and the control window procedures as it
/// creates the dialog box and controls.
/// </summary>
/// <remarks>
/// If you specify character strings in the menu, class, title, or typeface arrays, you must use
/// Unicode strings.
/// </remarks>
public string Typeface { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,185 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// An extended dialog box template begins with a DLGTEMPLATEEX header that describes
/// the dialog box and specifies the number of controls in the dialog box. For each
/// control in a dialog box, an extended dialog box template has a block of data that
/// uses the DLGITEMTEMPLATEEX format to describe the control.
///
/// The DLGTEMPLATEEX structure is not defined in any standard header file. The
/// structure definition is provided here to explain the format of an extended template
/// for a dialog box.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/dlgbox/dlgtemplateex"/>
public sealed class DialogTemplateExtended
{
/// <summary>
/// The version number of the extended dialog box template. This member must be
/// set to 1.
/// </summary>
public ushort Version { get; set; }
/// <summary>
/// Indicates whether a template is an extended dialog box template. If signature
/// is 0xFFFF, this is an extended dialog box template. In this case, the dlgVer
/// member specifies the template version number. If signature is any value other
/// than 0xFFFF, this is a standard dialog box template that uses the DLGTEMPLATE
/// and DLGITEMTEMPLATE structures.
/// </summary>
public ushort Signature { get; set; }
/// <summary>
/// The help context identifier for the dialog box window. When the system sends a
/// WM_HELP message, it passes this value in the wContextId member of the HELPINFO
/// structure.
/// </summary>
public uint HelpID { get; set; }
/// <summary>
/// The extended windows styles. This member is not used when creating dialog boxes,
/// but applications that use dialog box templates can use it to create other types
/// of windows.
/// </summary>
public ExtendedWindowStyles ExtendedStyle { get; set; }
/// <summary>
/// The style of the dialog box.
///
/// If style includes the DS_SETFONT or DS_SHELLFONT dialog box style, the DLGTEMPLATEEX
/// header of the extended dialog box template contains four additional members (pointsize,
/// weight, italic, and typeface) that describe the font to use for the text in the client
/// area and controls of the dialog box. If possible, the system creates a font according
/// to the values specified in these members. Then the system sends a WM_SETFONT message
/// to the dialog box and to each control to provide a handle to the font.
/// </summary>
public WindowStyles Style { get; set; }
/// <summary>
/// The number of controls in the dialog box.
/// </summary>
public ushort DialogItems { get; set; }
/// <summary>
/// The x-coordinate, in dialog box units, of the upper-left corner of the dialog box.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
/// to screen units (pixels) by using the MapDialogRect function.
/// </remarks>
public short PositionX { get; set; }
/// <summary>
/// The y-coordinate, in dialog box units, of the upper-left corner of the dialog box.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
/// to screen units (pixels) by using the MapDialogRect function.
/// </remarks>
public short PositionY { get; set; }
/// <summary>
/// The width, in dialog box units, of the dialog box.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
/// to screen units (pixels) by using the MapDialogRect function.
/// </remarks>
public short WidthX { get; set; }
/// <summary>
/// The height, in dialog box units, of the dialog box.
/// </summary>
/// <remarks>
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
/// to screen units (pixels) by using the MapDialogRect function.
/// </remarks>
public short HeightY { get; set; }
/// <summary>
/// A variable-length array of 16-bit elements that identifies a menu resource for the dialog box.
/// If the first element of this array is 0x0000, the dialog box has no menu and the array has no
/// other elements. If the first element is 0xFFFF, the array has one additional element that
/// specifies the ordinal value of a menu resource in an executable file. If the first element has
/// any other value, the system treats the array as a null-terminated Unicode string that specifies
/// the name of a menu resource in an executable file.
/// </summary>
/// <remarks>
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
/// </remarks>
public string MenuResource { get; set; } = string.Empty;
/// <summary>
/// The ordinal value of a menu resource in an executable file.
/// </summary>
public ushort MenuResourceOrdinal { get; set; }
/// <summary>A variable-length array of 16-bit elements that identifies the window class of the
/// dialog box. If the first element of the array is 0x0000, the system uses the predefined dialog
/// box class for the dialog box and the array has no other elements. If the first element is 0xFFFF,
/// the array has one additional element that specifies the ordinal value of a predefined system
/// window class. If the first element has any other value, the system treats the array as a
/// null-terminated Unicode string that specifies the name of a registered window class.
/// </summary>
/// <remarks>
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
/// </remarks>
public string ClassResource { get; set; } = string.Empty;
/// <summary>
/// The ordinal value of a predefined system window class.
/// </summary>
public ushort ClassResourceOrdinal { get; set; }
/// <summary>
/// The title of the dialog box. If the first element of this array is 0x0000, the dialog box has no
/// title and the array has no other elements.
/// </summary>
/// <remarks>
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
/// </remarks>
public string TitleResource { get; set; } = string.Empty;
/// <summary>
/// The point size of the font to use for the text in the dialog box and its controls.
///
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
/// </summary>
public ushort PointSize { get; set; }
/// <summary>
/// The weight of the font. Note that, although this can be any of the values listed for the lfWeight
/// member of the LOGFONT structure, any value that is used will be automatically changed to FW_NORMAL.
///
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
/// </summary>
public ushort Weight { get; set; }
/// <summary>
/// Indicates whether the font is italic. If this value is TRUE, the font is italic.
///
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
/// </summary>
public byte Italic { get; set; }
/// <summary>
/// The character set to be used. For more information, see the lfcharset member of LOGFONT.
///
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
/// </summary>
public byte CharSet { get; set; }
/// <summary>
/// The name of the typeface for the font.
///
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
/// </summary>
/// <remarks>
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
/// </remarks>
public string Typeface { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,21 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains the information necessary for an application to access a specific font. The structure
/// definition provided here is for explanation only; it is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/direntry"/>
public sealed class DirEntry
{
/// <summary>
/// A unique ordinal identifier for an individual font in a font resource group.
/// </summary>
public ushort FontOrdinal { get; set; }
/// <summary>
/// The FONTDIRENTRY structure for the specified font directly follows the DIRENTRY structure
/// for that font.
/// </summary>
public FontDirEntry Entry { get; set; } = new();
}
}

View File

@@ -0,0 +1,92 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains version information for a file. This information is language and
/// code page independent.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class FixedFileInfo
{
/// <summary>
/// Contains the value 0xFEEF04BD. This is used with the szKey member of the VS_VERSIONINFO
/// structure when searching a file for the FixedFileInfo structure.
/// </summary>
public uint Signature;
/// <summary>
/// The binary version number of this structure. The high-order word of this member contains
/// the major version number, and the low-order word contains the minor version number.
/// </summary>
public uint StrucVersion;
/// <summary>
/// The most significant 32 bits of the file's binary version number. This member is used with
/// FileVersionLS to form a 64-bit value used for numeric comparisons.
/// </summary>
public uint FileVersionMS;
/// <summary>
/// The least significant 32 bits of the file's binary version number. This member is used with
/// FileVersionMS to form a 64-bit value used for numeric comparisons.
/// </summary>
public uint FileVersionLS;
/// <summary>
/// The most significant 32 bits of the binary version number of the product with which this file
/// was distributed. This member is used with ProductVersionLS to form a 64-bit value used for
/// numeric comparisons.
/// </summary>
public uint ProductVersionMS;
/// <summary>
/// The least significant 32 bits of the binary version number of the product with which this file
/// was distributed. This member is used with ProductVersionMS to form a 64-bit value used for
/// numeric comparisons.
/// </summary>
public uint ProductVersionLS;
/// <summary>
/// Contains a bitmask that specifies the valid bits in FileFlags. A bit is valid only if it was
/// defined when the file was created.
/// </summary>
public uint FileFlagsMask;
/// <summary>
/// Contains a bitmask that specifies the Boolean attributes of the file.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public FixedFileInfoFlags FileFlags;
/// <summary>
/// The operating system for which this file was designed.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public FixedFileInfoOS FileOS;
/// <summary>
/// The general type of file.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public FixedFileInfoFileType FileType;
/// <summary>
/// The function of the file. The possible values depend on the value of FileType. For all values
/// of FileType not described in the following list, FileSubtype is zero.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public FixedFileInfoFileSubtype FileSubtype;
/// <summary>
/// The most significant 32 bits of the file's 64-bit binary creation date and time stamp.
/// </summary>
public uint FileDateMS;
/// <summary>
/// The least significant 32 bits of the file's 64-bit binary creation date and time stamp.
/// </summary>
public uint FileDateLS;
}
}

View File

@@ -0,0 +1,174 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains information about an individual font in a font resource group. The structure definition
/// provided here is for explanation only; it is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/fontdirentry"/>
public sealed class FontDirEntry
{
/// <summary>
/// A user-defined version number for the resource data that tools can use to read and write
/// resource files.
/// </summary>
public ushort Version { get; set; }
/// <summary>
/// The size of the file, in bytes.
/// </summary>
public uint Size { get; set; }
/// <summary>
/// The font supplier's copyright information.
/// </summary>
/// <remarks>60 characters</remarks>
public byte[] Copyright { get; set; } = new byte[60];
/// <summary>
/// The type of font file.
/// </summary>
public ushort Type { get; set; }
/// <summary>
/// The point size at which this character set looks best.
/// </summary>
public ushort Points { get; set; }
/// <summary>
/// The vertical resolution, in dots per inch, at which this character set was digitized.
/// </summary>
public ushort VertRes { get; set; }
/// <summary>
/// The horizontal resolution, in dots per inch, at which this character set was digitized.
/// </summary>
public ushort HorizRes { get; set; }
/// <summary>
/// The distance from the top of a character definition cell to the baseline of the typographical
/// font.
/// </summary>
public ushort Ascent { get; set; }
/// <summary>
/// The amount of leading inside the bounds set by the PixHeight member. Accent marks and other
/// diacritical characters can occur in this area.
/// </summary>
public ushort InternalLeading { get; set; }
/// <summary>
/// The amount of extra leading that the application adds between rows.
/// </summary>
public ushort ExternalLeading { get; set; }
/// <summary>
/// An italic font if not equal to zero.
/// </summary>
public byte Italic { get; set; }
/// <summary>
/// An underlined font if not equal to zero.
/// </summary>
public byte Underline { get; set; }
/// <summary>
/// A strikeout font if not equal to zero.
/// </summary>
public byte StrikeOut { get; set; }
/// <summary>
/// The weight of the font in the range 0 through 1000. For example, 400 is roman and 700 is bold.
/// If this value is zero, a default weight is used. For additional defined values, see the
/// description of the LOGFONT structure.
/// </summary>
public ushort Weight { get; set; }
/// <summary>
/// The character set of the font. For predefined values, see the description of the LOGFONT
/// structure.
/// </summary>
public byte CharSet { get; set; }
/// <summary>
/// The width of the grid on which a vector font was digitized. For raster fonts, if the member
/// is not equal to zero, it represents the width for all the characters in the bitmap. If the
/// member is equal to zero, the font has variable-width characters.
/// </summary>
public ushort PixWidth { get; set; }
/// <summary>
/// The height of the character bitmap for raster fonts or the height of the grid on which a
/// vector font was digitized.
/// </summary>
public ushort PixHeight { get; set; }
/// <summary>
/// The pitch and the family of the font. For additional information, see the description of
/// the LOGFONT structure.
/// </summary>
public byte PitchAndFamily { get; set; }
/// <summary>
/// The average width of characters in the font (generally defined as the width of the letter x).
/// This value does not include the overhang required for bold or italic characters.
/// </summary>
public ushort AvgWidth { get; set; }
/// <summary>
/// The width of the widest character in the font.
/// </summary>
public ushort MaxWidth { get; set; }
/// <summary>
/// The first character code defined in the font.
/// </summary>
public byte FirstChar { get; set; }
/// <summary>
/// The last character code defined in the font.
/// </summary>
public byte LastChar { get; set; }
/// <summary>
/// The character to substitute for characters not in the font.
/// </summary>
public byte DefaultChar { get; set; }
/// <summary>
/// The character that will be used to define word breaks for text justification.
/// </summary>
public byte BreakChar { get; set; }
/// <summary>
/// The number of bytes in each row of the bitmap. This value is always even so that the rows
/// start on word boundaries. For vector fonts, this member has no meaning.
/// </summary>
public ushort WidthBytes { get; set; }
/// <summary>
/// The offset in the file to a null-terminated string that specifies a device name. For a
/// generic font, this value is zero.
/// </summary>
public uint Device { get; set; }
/// <summary>
/// The offset in the file to a null-terminated string that names the typeface.
/// </summary>
public uint Face { get; set; }
/// <summary>
/// This member is reserved.
/// </summary>
public uint Reserved { get; set; }
/// <summary>
/// The name of the device if this font file is designated for a specific device.
/// </summary>
public string DeviceName { get; set; } = string.Empty;
/// <summary>
/// The typeface name of the font.
/// </summary>
public string FaceName { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,21 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains the information necessary for an application to access a specific font. The structure
/// definition provided here is for explanation only; it is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/fontgrouphdr"/>
public sealed class FontGroupHeader : ResourceDataType
{
/// <summary>
/// The number of individual fonts associated with this resource.
/// </summary>
public ushort NumberOfFonts { get; set; }
/// <summary>
/// A structure that contains a unique ordinal identifier for each font in the resource. The DE
/// member is a placeholder for the variable-length array of DIRENTRY structures.
/// </summary>
public DirEntry[] DE { get; set; } = [];
}
}

View File

@@ -0,0 +1,13 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Generic or unparsed resource data
/// </summary>
public class GenericResourceEntry : ResourceDataType
{
/// <summary>
/// Unparsed byte data from the resource
/// </summary>
public byte[] Data { get; set; } = [];
}
}

View File

@@ -0,0 +1,12 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Common base class for menu item types
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/menuheader"/>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/menuex-template-header"/>
[StructLayout(LayoutKind.Sequential)]
public abstract class MenuHeader { }
}

View File

@@ -0,0 +1,30 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Defines the header for an extended menu template. This structure definition is for
/// explanation only; it is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/menuex-template-header"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class MenuHeaderExtended : MenuHeader
{
/// <summary>
/// The template version number. This member must be 1 for extended menu templates.
/// </summary>
public ushort Version;
/// <summary>
/// The offset to the first MENUEX_TEMPLATE_ITEM structure, relative to the end of
/// this structure member. If the first item definition immediately follows the
/// dwHelpId member, this member should be 4.
/// </summary>
public ushort Offset;
/// <summary>
/// The help identifier of menu bar.
/// </summary>
public uint HelpID;
}
}

View File

@@ -0,0 +1,12 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Common base class for menu item types
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/normalmenuitem"/>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/popupmenuitem"/>
[StructLayout(LayoutKind.Sequential)]
public abstract class MenuItem { }
}

View File

@@ -0,0 +1,44 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Defines a menu item in an extended menu template. This structure definition is for
/// explanation only; it is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/menuex-template-item"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class MenuItemExtended : MenuItem
{
/// <summary>
/// Describes the menu item.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public MenuFlags ItemType;
/// <summary>
/// Describes the menu item.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public MenuFlags State;
/// <summary>
/// A numeric expression that identifies the menu item that is passed in the
/// WM_COMMAND message.
/// </summary>
public uint ID;
/// <summary>
/// A set of bit flags that specify the type of menu item.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public MenuFlags Flags;
/// <summary>
/// A null-terminated Unicode string that contains the text for this menu item.
/// There is no fixed limit on the size of this string.
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string MenuText = string.Empty;
}
}

View File

@@ -0,0 +1,22 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// A menu resource consists of a MENUHEADER structure followed by one or more
/// NORMALMENUITEM or POPUPMENUITEM structures, one for each menu item in the menu
/// template. The MENUEX_TEMPLATE_HEADER and the MENUEX_TEMPLATE_ITEM structures
/// describe the format of extended menu resources.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/resource-file-formats"/>
public sealed class MenuResource : ResourceDataType
{
/// <summary>
/// Menu header structure
/// </summary>
public MenuHeader MenuHeader { get; set; } = new NormalMenuHeader();
/// <summary>
/// Menu items
/// </summary>
public MenuItem[] MenuItems { get; set; } = [];
}
}

View File

@@ -0,0 +1,30 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains information about message strings with identifiers in the range indicated
/// by the LowId and HighId members.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-message_resource_block"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class MessageResourceBlock
{
/// <summary>
/// The lowest message identifier contained within this structure.
/// </summary>
public uint LowId;
/// <summary>
/// The highest message identifier contained within this structure.
/// </summary>
public uint HighId;
/// <summary>
/// The offset, in bytes, from the beginning of the MESSAGE_RESOURCE_DATA structure to the
/// MESSAGE_RESOURCE_ENTRY structures in this MESSAGE_RESOURCE_BLOCK. The MESSAGE_RESOURCE_ENTRY
/// structures contain the message strings.
/// </summary>
public uint OffsetToEntries;
}
}

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains information about formatted text for display as an error message or in a message
/// box in a message table resource.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-message_resource_data"/>
public sealed class MessageResourceData : ResourceDataType
{
/// <summary>
/// The number of MESSAGE_RESOURCE_BLOCK structures.
/// </summary>
public uint NumberOfBlocks { get; set; }
/// <summary>
/// An array of structures. The array is the size indicated by the NumberOfBlocks member.
/// </summary>
public MessageResourceBlock[] Blocks { get; set; } = [];
/// <summary>
/// Message resource entries
/// </summary>
public Dictionary<uint, MessageResourceEntry?> Entries { get; set; } = [];
}
}

View File

@@ -0,0 +1,25 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains the error message or message box display text for a message table resource.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-message_resource_entry"/>
public sealed class MessageResourceEntry
{
/// <summary>
/// The length, in bytes, of the MESSAGE_RESOURCE_ENTRY structure.
/// </summary>
public ushort Length { get; set; }
/// <summary>
/// Indicates that the string is encoded in Unicode, if equal to the value 0x0001.
/// Indicates that the string is encoded in ANSI, if equal to the value 0x0000.
/// </summary>
public ushort Flags { get; set; }
/// <summary>
/// Pointer to an array that contains the error message or message box display text.
/// </summary>
public string Text { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,31 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains the number of icon or cursor components in a resource group. The
/// structure definition provided here is for explanation only; it is not present
/// in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/newheader"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class NewHeader
{
/// <summary>
/// Reserved; must be zero.
/// </summary>
public ushort Reserved;
/// <summary>
/// The resource type. This member must have one of the following values.
/// - RES_ICON (1): Icon resource type.
/// - RES_CURSOR (2): Cursor resource type.
/// </summary>
public ushort ResType;
/// <summary>
/// The number of icon or cursor components in the resource group.
/// </summary>
public ushort ResCount;
}
}

View File

@@ -0,0 +1,25 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains version information for the menu resource. The structure definition provided
/// here is for explanation only; it is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/menuheader"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class NormalMenuHeader : MenuHeader
{
/// <summary>
/// The version number of the menu template. This member must be equal to zero to indicate
/// that this is an RT_MENU created with a standard menu template.
/// </summary>
public ushort Version;
/// <summary>
/// The size of the menu template header. This value is zero for menus you create with a
/// standard menu template.
/// </summary>
public ushort HeaderSize;
}
}

View File

@@ -0,0 +1,27 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains information about each item in a menu resource that does not open a menu
/// or a submenu. The structure definition provided here is for explanation only; it
/// is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/normalmenuitem"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class NormalMenuItem : MenuItem
{
/// <summary>
/// The type of menu item.
/// </summary>
[MarshalAs(UnmanagedType.U2)]
public MenuFlags NormalResInfo;
/// <summary>
/// A null-terminated Unicode string that contains the text for this menu item.
/// There is no fixed limit on the size of this string.
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string NormalMenuText = string.Empty;
}
}

View File

@@ -0,0 +1,45 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Contains information about the menu items in a menu resource that open a menu
/// or a submenu. The structure definition provided here is for explanation only;
/// it is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/popupmenuitem"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class PopupMenuItem : MenuItem
{
/// <summary>
/// Describes the menu item.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public MenuFlags PopupItemType;
/// <summary>
/// Describes the menu item.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public MenuFlags PopupState;
/// <summary>
/// A numeric expression that identifies the menu item that is passed in the
/// WM_COMMAND message.
/// </summary>
public uint PopupID;
/// <summary>
/// A set of bit flags that specify the type of menu item.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public MenuFlags PopupResInfo;
/// <summary>
/// A null-terminated Unicode string that contains the text for this menu item.
/// There is no fixed limit on the size of this string.
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string PopupMenuText = string.Empty;
}
}

View File

@@ -0,0 +1,7 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Generic base class for resource data types
/// </summary>
public abstract class ResourceDataType { }
}

View File

@@ -0,0 +1,79 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Represents the organization of data in a file-version resource. It contains a string
/// that describes a specific aspect of a file, for example, a file's version, its
/// copyright notices, or its trademarks.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/string-str"/>
public sealed class StringData
{
/// <summary>
/// The length, in bytes, of this String structure.
/// </summary>
public ushort Length { get; set; }
/// <summary>
/// The size, in words, of the Value member.
/// </summary>
public ushort ValueLength { get; set; }
/// <summary>
/// The type of data in the version resource.
/// </summary>
public VersionResourceType ResourceType { get; set; }
/// <summary>
/// An arbitrary Unicode string. The Key member can be one or more of the following
/// values. These values are guidelines only.
/// - Comments: The Value member contains any additional information that should be
/// displayed for diagnostic purposes. This string can be an arbitrary length.
/// - CompanyName: The Value member identifies the company that produced the file.
/// For example, "Microsoft Corporation" or "Standard Microsystems Corporation, Inc."
/// - FileDescription: The Value member describes the file in such a way that it can be
/// presented to users. This string may be presented in a list box when the user is
/// choosing files to install. For example, "Keyboard driver for AT-style keyboards"
/// or "Microsoft Word for Windows".
/// - FileVersion: The Value member identifies the version of this file. For example,
/// Value could be "3.00A" or "5.00.RC2".
/// - InternalName: The Value member identifies the file's internal name, if one exists.
/// For example, this string could contain the module name for a DLL, a virtual device
/// name for a Windows virtual device, or a device name for a MS-DOS device driver.
/// - LegalCopyright: The Value member describes all copyright notices, trademarks, and
/// registered trademarks that apply to the file. This should include the full text of
/// all notices, legal symbols, copyright dates, trademark numbers, and so on. In
/// English, this string should be in the format "Copyright Microsoft Corp. 1990 1994".
/// - LegalTrademarks: The Value member describes all trademarks and registered trademarks
/// that apply to the file. This should include the full text of all notices, legal
/// symbols, trademark numbers, and so on. In English, this string should be in the
/// format "Windows is a trademark of Microsoft Corporation".
/// - OriginalFilename: The Value member identifies the original name of the file, not
/// including a path. This enables an application to determine whether a file has been
/// renamed by a user. This name may not be MS-DOS 8.3-format if the file is specific
/// to a non-FAT file system.
/// - PrivateBuild: The Value member describes by whom, where, and why this private version
/// of the file was built. This string should only be present if the VS_FF_PRIVATEBUILD
/// flag is set in the dwFileFlags member of the VS_FIXEDFILEINFO structure. For example,
/// Value could be "Built by OSCAR on \OSCAR2".
/// - ProductName: The Value member identifies the name of the product with which this file is
/// distributed. For example, this string could be "Microsoft Windows".
/// - ProductVersion: The Value member identifies the version of the product with which this
/// file is distributed. For example, Value could be "3.00A" or "5.00.RC2".
/// - SpecialBuild: The Value member describes how this version of the file differs from the
/// normal version. This entry should only be present if the VS_FF_SPECIALBUILD flag is
/// set in the dwFileFlags member of the VS_FIXEDFILEINFO structure. For example, Value
/// could be "Private build for Olivetti solving mouse problems on M250 and M250E computers".
/// </summary>
public string Key { get; set; } = string.Empty;
/// <summary>
/// As many zero words as necessary to align the Value member on a 32-bit boundary.
/// </summary>
public ushort Padding { get; set; }
/// <summary>
/// A zero-terminated string. See the szKey member description for more information.
/// </summary>
public string Value { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,43 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Represents the organization of data in a file-version resource. It contains version
/// information that can be displayed for a particular language and code page.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/stringfileinfo"/>
public sealed class StringFileInfo
{
/// <summary>
/// The length, in bytes, of the entire StringFileInfo block, including all
/// structures indicated by the Children member.
/// </summary>
public ushort Length { get; set; }
/// <summary>
/// This member is always equal to zero.
/// </summary>
public ushort ValueLength { get; set; }
/// <summary>
/// The type of data in the version resource.
/// </summary>
public VersionResourceType ResourceType { get; set; }
/// <summary>
/// The Unicode string L"StringFileInfo".
/// </summary>
public string Key { get; set; } = string.Empty;
/// <summary>
/// As many zero words as necessary to align the Children member on a 32-bit boundary.
/// </summary>
public ushort Padding { get; set; }
/// <summary>
/// An array of one or more StringTable structures. Each StringTable structure's Key
/// member indicates the appropriate language and code page for displaying the text in
/// that StringTable structure.
/// </summary>
public StringTable[] Children { get; set; } = [];
}
}

View File

@@ -0,0 +1,46 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Represents the organization of data in a file-version resource. It contains language
/// and code page formatting information for the strings specified by the Children member.
/// A code page is an ordered character set.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/stringtable"/>
public sealed class StringTable
{
/// <summary>
/// The length, in bytes, of this StringTable structure, including all structures
/// indicated by the Children member.
/// </summary>
public ushort Length { get; set; }
/// <summary>
/// This member is always equal to zero.
/// </summary>
public ushort ValueLength { get; set; }
/// <summary>
/// The type of data in the version resource.
/// </summary>
public VersionResourceType ResourceType { get; set; }
/// <summary>
/// An 8-digit hexadecimal number stored as a Unicode string. The four most significant
/// digits represent the language identifier. The four least significant digits represent
/// the code page for which the data is formatted. Each Microsoft Standard Language
/// identifier contains two parts: the low-order 10 bits specify the major language,
/// and the high-order 6 bits specify the sublanguage.
/// </summary>
public string Key { get; set; } = string.Empty;
/// <summary>
/// As many zero words as necessary to align the Children member on a 32-bit boundary.
/// </summary>
public ushort Padding { get; set; }
/// <summary>
/// An array of one or more StringData structures.
/// </summary>
public StringData[] Children { get; set; } = [];
}
}

View File

@@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Represents a string table resource
/// </summary>
public sealed class StringTableResource : ResourceDataType
{
/// <summary>
/// Set of integer-keyed values
/// </summary>
public Dictionary<int, string?> Data { get; set; } = [];
}
}

View File

@@ -0,0 +1,50 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Represents the organization of data in a file-version resource. It typically contains a
/// list of language and code page identifier pairs that the version of the application or
/// DLL supports.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/var-str"/>
public sealed class VarData
{
/// <summary>
/// The length, in bytes, of the Var structure.
/// </summary>
public ushort Length { get; set; }
/// <summary>
/// The size, in words, of the Value member.
/// </summary>
public ushort ValueLength { get; set; }
/// <summary>
/// The type of data in the version resource.
/// </summary>
public VersionResourceType ResourceType { get; set; }
/// <summary>
/// The Unicode string L"Translation".
/// </summary>
public string Key { get; set; } = string.Empty;
/// <summary>
/// As many zero words as necessary to align the Value member on a 32-bit boundary.
/// </summary>
public ushort Padding { get; set; }
/// <summary>
/// An array of one or more values that are language and code page identifier pairs.
///
/// If you use the Var structure to list the languages your application or DLL supports
/// instead of using multiple version resources, use the Value member to contain an array
/// of DWORD values indicating the language and code page combinations supported by this
/// file. The low-order word of each DWORD must contain a Microsoft language identifier,
/// and the high-order word must contain the IBM code page number. Either high-order or
/// low-order word can be zero, indicating that the file is language or code page
/// independent. If the Var structure is omitted, the file will be interpreted as both
/// language and code page independent.
/// </summary>
public uint[] Value { get; set; } = [];
}
}

View File

@@ -0,0 +1,41 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Represents the organization of data in a file-version resource. It contains version
/// information not dependent on a particular language and code page combination.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/varfileinfo"/>
public sealed class VarFileInfo
{
/// <summary>
/// The length, in bytes, of the entire VarFileInfo block, including all structures
/// indicated by the Children member.
/// </summary>
public ushort Length { get; set; }
/// <summary>
/// This member is always equal to zero.
/// </summary>
public ushort ValueLength { get; set; }
/// <summary>
/// The type of data in the version resource.
/// </summary>
public VersionResourceType ResourceType { get; set; }
/// <summary>
/// The Unicode string L"VarFileInfo".
/// </summary>
public string Key { get; set; } = string.Empty;
/// <summary>
/// As many zero words as necessary to align the Children member on a 32-bit boundary.
/// </summary>
public ushort Padding { get; set; }
/// <summary>
/// Typically contains a list of languages that the application or DLL supports.
/// </summary>
public VarData[] Children { get; set; } = [];
}
}

View File

@@ -0,0 +1,61 @@
namespace SabreTools.Data.Models.PortableExecutable.Resource.Entries
{
/// <summary>
/// Represents the organization of data in a file-version resource. It is the root
/// structure that contains all other file-version information structures.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/vs-versioninfo"/>
public sealed class VersionInfo : ResourceDataType
{
/// <summary>
/// The length, in bytes, of the VS_VERSIONINFO structure. This length does not
/// include any padding that aligns any subsequent version resource data on a
/// 32-bit boundary.
/// </summary>
public ushort Length { get; set; }
/// <summary>
/// The length, in bytes, of the Value member. This value is zero if there is no
/// Value member associated with the current version structure.
/// </summary>
public ushort ValueLength { get; set; }
/// <summary>
/// The type of data in the version resource. This member is 1 if the version resource
/// contains text data and 0 if the version resource contains binary data.
/// </summary>
public VersionResourceType ResourceType { get; set; }
/// <summary>
/// The Unicode string L"VS_VERSION_INFO".
/// </summary>
public string Key { get; set; } = string.Empty;
/// <summary>
/// Contains as many zero words as necessary to align the Value member on a 32-bit boundary.
/// </summary>
public ushort Padding1 { get; set; }
/// <summary>
/// Arbitrary data associated with this VS_VERSIONINFO structure. The ValueLength member
/// specifies the length of this member; if ValueLength is zero, this member does not exist.
/// </summary>
public FixedFileInfo? Value { get; set; }
/// <summary>
/// As many zero words as necessary to align the Children member on a 32-bit boundary.
/// These bytes are not included in wValueLength. This member is optional.
/// </summary>
public ushort Padding2 { get; set; }
/// <summary>
/// The StringFileInfo structure to store user-defined string information data.
/// </summary>
public StringFileInfo? StringFileInfo { get; set; }
/// <summary>
/// The VarFileInfo structure to store language information data.
/// </summary>
public VarFileInfo? VarFileInfo { get; set; }
}
}

View File

@@ -0,0 +1,99 @@
using System.Runtime.InteropServices;
namespace SabreTools.Data.Models.PortableExecutable.Resource
{
/// <summary>
/// Contains information about the resource header itself and the data specific to
/// this resource. This structure is not a true C-language structure, because it
/// contains variable-length members. The structure definition provided here is for
/// explanation only; it is not present in any standard header file.
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/resourceheader"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class ResourceHeader
{
/// <summary>
/// The size, in bytes, of the data that follows the resource header for this
/// particular resource. It does not include any file padding between this
/// resource and any resource that follows it in the resource file.
/// </summary>
public uint DataSize;
/// <summary>
/// The size, in bytes, of the resource header data that follows.
/// </summary>
public uint HeaderSize;
/// <summary>
/// The resource type. The TYPE member can either be a numeric value or a
/// null-terminated Unicode string that specifies the name of the type. See the
/// following Remarks section for a description of Name or Ordinal type members.
///
/// If the TYPE member is a numeric value, it can specify either a standard or a
/// user-defined resource type. If the member is a string, then it is a
/// user-defined resource type.
///
/// Values less than 256 are reserved for system use.
/// </summary>
[MarshalAs(UnmanagedType.U4)]
public ResourceType ResourceType;
/// <summary>
/// A name that identifies the particular resource. The NAME member, like the TYPE
/// member, can either be a numeric value or a null-terminated Unicode string.
/// See the following Remarks section for a description of Name or Ordinal type
/// members.
///
/// You do not need to add padding for DWORD alignment between the TYPE and NAME
/// members because they contain WORD data. However, you may need to add a WORD of
/// padding after the NAME member to align the rest of the header on DWORD boundaries.
/// </summary>
public uint Name;
/// <summary>
/// A predefined resource data version. This will determine which version of the
/// resource data the application should use.
/// </summary>
public uint DataVersion;
/// <summary>
/// A set of attribute flags that can describe the state of the resource. Modifiers
/// in the .RC script file assign these attributes to the resource. The script
/// identifiers can assign the following flag values.
///
/// Applications do not use any of these attributes. The attributes are permitted
/// in the script for backward compatibility with existing scripts, but they are
/// ignored. Resources are loaded when the corresponding module is loaded, and are
/// freed when the module is unloaded.
/// </summary>
[MarshalAs(UnmanagedType.U2)]
public MemoryFlags MemoryFlags;
/// <summary>
/// The language for the resource or set of resources. Set the value for this member
/// with the optional LANGUAGE resource definition statement. The parameters are
/// constants from the Winnt.h file.
///
/// Each resource includes a language identifier so the system or application can
/// select a language appropriate for the current locale of the system. If there are
/// multiple resources of the same type and name that differ only in the language of
/// the strings within the resources, you will need to specify a LanguageId for each
/// one.
/// </summary>
public ushort LanguageId;
/// <summary>
/// A user-defined version number for the resource data that tools can use to read and
/// write resource files. Set this value with the optional VERSION resource definition
/// statement.
/// </summary>
public uint Version;
/// <summary>
/// Specifies user-defined information about the resource that tools can use to read and
/// write resource files. Set this value with the optional CHARACTERISTICS resource
/// definition statement.
/// </summary>
public uint Characteristics;
}
}

View File

@@ -0,0 +1,55 @@
namespace SabreTools.Data.Models.PortableExecutable.TLS
{
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
public sealed class Directory
{
/// <summary>
/// The starting address of the TLS template. The template is a block of data
/// that is used to initialize TLS data. The system copies all of this data
/// each time a thread is created, so it must not be corrupted. Note that this
/// address is not an RVA; it is an address for which there should be a base
/// relocation in the .reloc section.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong RawDataStartVA { get; set; }
/// <summary>
/// The address of the last byte of the TLS, except for the zero fill. As
/// with the Raw Data Start VA field, this is a VA, not an RVA.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong RawDataEndVA { get; set; }
/// <summary>
/// The location to receive the TLS index, which the loader assigns. This
/// location is in an ordinary data section, so it can be given a symbolic
/// name that is accessible to the program.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong AddressOfIndex { get; set; }
/// <summary>
/// The pointer to an array of TLS callback functions. The array is
/// null-terminated, so if no callback function is supported, this field
/// points to 4 bytes set to zero.
/// </summary>
/// <remarks>This value is 32-bit if PE32 and 64-bit if PE32+</remarks>
public ulong AddressOfCallbacks { get; set; }
/// <summary>
/// The size in bytes of the template, beyond the initialized data delimited
/// by the Raw Data Start VA and Raw Data End VA fields. The total template
/// size should be the same as the total size of TLS data in the image file.
/// The zero fill is the amount of data that comes after the initialized
/// nonzero data.
/// </summary>
public uint SizeOfZeroFill { get; set; }
/// <summary>
/// The four bits [23:20] describe alignment info. Possible values are those
/// defined as IMAGE_SCN_ALIGN_*, which are also used to describe alignment
/// of section in object files. The other 28 bits are reserved for future use.
/// </summary>
public uint Characteristics { get; set; }
}
}