Skip to content

Commit eb1982b

Browse files
committed
Extend PortableExecutableInfo parser with data directory parsing.
1 parent 8104fe1 commit eb1982b

46 files changed

Lines changed: 3669 additions & 9 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/copilot-instructions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ When working on the PowerShell module in VS Code:
144144
- **Comment-Based Help**: Required for all public functions with `.SYNOPSIS`, `.DESCRIPTION`, `.EXAMPLE`.
145145
- **Minimize Unnecessary Changes**: Preserve existing XML documentation comments when refactoring code. Don't strip them unnecessarily, as it makes git diffs noisy and loses valuable documentation. Only modify what's strictly necessary for the structural changes.
146146
- **Resource Management**: Use nested try/finally blocks for COM cleanup and resource management rather than flat structures with nullable checks, even if it results in deep indentation.
147+
- **Null Checks**: When checking if a method returns a non-null value and using it, prefer pattern matching with `is` to tightly scope the variable: `if (Method() is Type variable) { ... }` instead of `var variable = Method(); if (variable != null) { ... }`. This scopes the variable to the branch where it's needed and makes the code more robust.
148+
- **Inline Factory Method Usage**: When a factory method already provides context for what a value represents (e.g., `FromOrdinal()`), inline the expression directly rather than storing it in a temporary variable first. Example: prefer `entries.Add(DelayImportEntry.FromOrdinal((ushort)(thunkData & 0xFFFF)));` over creating a temporary `ushort ordinal = ...` variable.
147149
- **ThrowIfNullOrWhiteSpace Usage**: When using the `ThrowIfNullOrWhiteSpace` extension method, do not pass explicit `nameof()` arguments — rely on the `[CallerMemberName]` attribute to automatically populate the name parameter.
148150
- **SafeHandle Validation**: When validating SafeHandle parameters, avoid standalone `ThrowIfNullOrInvalid` or `ThrowIfNullOrClosed` calls that discard return values; inline the call into the subsequent usage (e.g., chain into `DangerousAddRef` or PInvoke argument).
149151
- **RemoveFontResource Input**: Do not pre-validate `RemoveFontResource` input with file existence checks; it can operate on file names and not necessarily full paths.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
3+
namespace PSADT.Interop
4+
{
5+
/// <summary>
6+
/// Specifies flags that define the characteristics and behavior of a Common Object Model (COM) image.
7+
/// </summary>
8+
/// <remarks>These flags indicate properties such as whether the image contains only Microsoft
9+
/// intermediate language (IL) code, requires a 32-bit process, is strong name signed, or has other specific
10+
/// requirements. They are typically used when working with managed assemblies to control how the image is loaded
11+
/// and executed by the runtime.</remarks>
12+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "These are as they're named in the Win32 API.")]
13+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1712:Do not prefix enum values with type name", Justification = "These are as they're named in the Win32 API.")]
14+
[Flags]
15+
public enum COMIMAGE_FLAGS
16+
{
17+
/// <summary>
18+
/// Specifies that the image contains only Microsoft intermediate language (MSIL) code and does not include any
19+
/// native code.
20+
/// </summary>
21+
/// <remarks>Use this flag to indicate that the image is intended to run exclusively in a managed
22+
/// execution environment. This ensures that the image can be loaded and executed by the common language runtime
23+
/// (CLR) without requiring native code support.</remarks>
24+
COMIMAGE_FLAGS_ILONLY = Windows.Win32.System.SystemServices.ReplacesCorHdrNumericDefines.COMIMAGE_FLAGS_ILONLY,
25+
26+
/// <summary>
27+
/// Specifies that the associated COM image requires execution in a 32-bit environment.
28+
/// </summary>
29+
/// <remarks>Use this flag to indicate that the COM image is not compatible with 64-bit processes
30+
/// and must be run in a 32-bit context. This is important for ensuring compatibility with 32-bit components or
31+
/// dependencies.</remarks>
32+
COMIMAGE_FLAGS_32BITREQUIRED = Windows.Win32.System.SystemServices.ReplacesCorHdrNumericDefines.COMIMAGE_FLAGS_32BITREQUIRED,
33+
34+
/// <summary>
35+
/// Specifies that the COM image is an Intermediate Language (IL) library.
36+
/// </summary>
37+
/// <remarks>This flag is part of the COMIMAGE_FLAGS enumeration and is used to indicate that the
38+
/// associated COM image represents an IL library rather than a native binary. It is relevant when processing or
39+
/// analyzing COM images to determine their type or intended usage.</remarks>
40+
COMIMAGE_FLAGS_IL_LIBRARY = Windows.Win32.System.SystemServices.ReplacesCorHdrNumericDefines.COMIMAGE_FLAGS_IL_LIBRARY,
41+
42+
/// <summary>
43+
/// Represents the flag that indicates a COM image is signed with a strong name.
44+
/// </summary>
45+
/// <remarks>This flag is used to identify assemblies that have been strong name signed, which
46+
/// provides identity and versioning guarantees. Strong name signing helps ensure the integrity and uniqueness
47+
/// of the assembly.</remarks>
48+
COMIMAGE_FLAGS_STRONGNAMESIGNED = Windows.Win32.System.SystemServices.ReplacesCorHdrNumericDefines.COMIMAGE_FLAGS_STRONGNAMESIGNED,
49+
50+
/// <summary>
51+
/// Specifies that the entry point of the COM image is a native entry point.
52+
/// </summary>
53+
/// <remarks>This flag is used in the COMIMAGE_FLAGS enumeration to indicate that the image's
54+
/// entry point is native code rather than managed code. It is relevant when working with COM image headers and
55+
/// can affect how the image is loaded and executed by the runtime.</remarks>
56+
COMIMAGE_FLAGS_NATIVE_ENTRYPOINT = Windows.Win32.System.SystemServices.ReplacesCorHdrNumericDefines.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT,
57+
58+
/// <summary>
59+
/// Specifies that debug data is tracked for the COM image.
60+
/// </summary>
61+
/// <remarks>This flag indicates that debug information should be included in the COM image, which
62+
/// can assist with debugging and diagnostics. Enabling this flag may increase the size of the image but
63+
/// provides additional information useful during development and troubleshooting.</remarks>
64+
COMIMAGE_FLAGS_TRACKDEBUGDATA = Windows.Win32.System.SystemServices.ReplacesCorHdrNumericDefines.COMIMAGE_FLAGS_TRACKDEBUGDATA,
65+
66+
/// <summary>
67+
/// Specifies that the COM image is preferred to be loaded as a 32-bit image when possible.
68+
/// </summary>
69+
/// <remarks>This flag is used in the context of COM image loading to indicate a preference for
70+
/// 32-bit architecture. It is part of the COMIMAGE_FLAGS enumeration and may affect how the image is loaded on
71+
/// systems that support both 32-bit and 64-bit execution.</remarks>
72+
COMIMAGE_FLAGS_32BITPREFERRED = Windows.Win32.System.SystemServices.ReplacesCorHdrNumericDefines.COMIMAGE_FLAGS_32BITPREFERRED,
73+
}
74+
}

src/PSADT/PSADT.Interop/Exceptions/NtStatusException.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
using Windows.Win32;
1313
using Windows.Win32.Foundation;
1414
using Windows.Win32.System.Diagnostics.Debug;
15-
using Windows.Win32.System.LibraryLoader;
1615

1716
namespace PSADT.Interop.Exceptions
1817
{
@@ -102,7 +101,7 @@ private static string GetMessageForNtStatus(NTSTATUS ntStatus)
102101
/// <summary>
103102
/// Cached handle to ntdll.dll for FormatMessage calls.
104103
/// </summary>
105-
private static readonly FreeLibrarySafeHandle NtDllHandle = NativeMethods.LoadLibraryEx("ntdll.dll", LOAD_LIBRARY_FLAGS.LOAD_LIBRARY_SEARCH_SYSTEM32);
104+
private static readonly FreeLibrarySafeHandle NtDllHandle = NativeMethods.LoadLibraryEx("ntdll.dll", Windows.Win32.System.LibraryLoader.LOAD_LIBRARY_FLAGS.LOAD_LIBRARY_SEARCH_SYSTEM32);
106105

107106
/// <summary>
108107
/// Provides a read-only mapping of NTSTATUS enumeration values to their corresponding field names.
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
using System;
2+
3+
namespace PSADT.Interop
4+
{
5+
/// <summary>
6+
/// Defines a set of flags that control the behavior of heap memory allocation in Windows.
7+
/// </summary>
8+
/// <remarks>These flags can be used when creating or managing heaps to specify options such as
9+
/// serialization, memory initialization, and error handling. Each flag modifies the behavior of the heap to suit
10+
/// different application needs, including performance optimizations and debugging support.</remarks>
11+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1008:Enums should have zero value", Justification = "This is how they're named within the Win32 API.")]
12+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "This is how it's named within the Win32 API.")]
13+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "This is how they're named within the Win32 API.")]
14+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2217:Do not mark enums with FlagsAttribute", Justification = "This is a bitfield, though...")]
15+
[Flags]
16+
public enum HEAP_FLAGS : uint
17+
{
18+
/// <summary>
19+
/// Represents a flag that indicates no special heap options are set.
20+
/// </summary>
21+
/// <remarks>Use this flag when allocating memory to specify that the default heap behavior should
22+
/// be applied without any additional options.</remarks>
23+
HEAP_NONE = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_NONE,
24+
25+
/// <summary>
26+
/// Specifies that the heap does not perform serialization, allowing for faster access in multithreaded
27+
/// scenarios when synchronization is managed externally.
28+
/// </summary>
29+
/// <remarks>Use this flag when creating a heap if you can guarantee that all access to the heap
30+
/// is properly synchronized by the application. Disabling serialization can improve performance, but it is the
31+
/// developer's responsibility to ensure thread safety when multiple threads access the heap
32+
/// concurrently.</remarks>
33+
HEAP_NO_SERIALIZE = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_NO_SERIALIZE,
34+
35+
/// <summary>
36+
/// Represents a flag that enables a heap to grow dynamically as additional memory is required.
37+
/// </summary>
38+
/// <remarks>Use this flag when creating a heap to allow it to increase in size during its
39+
/// lifetime. This provides more flexible memory management, especially for applications with unpredictable or
40+
/// variable memory usage patterns.</remarks>
41+
HEAP_GROWABLE = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_GROWABLE,
42+
43+
/// <summary>
44+
/// Specifies that the heap should generate exceptions on memory allocation failures.
45+
/// </summary>
46+
/// <remarks>This flag can be used when creating a heap to ensure that any allocation errors are
47+
/// reported via exceptions, allowing for better error handling in applications.</remarks>
48+
HEAP_GENERATE_EXCEPTIONS = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_GENERATE_EXCEPTIONS,
49+
50+
/// <summary>
51+
/// Specifies a flag that indicates the memory allocated by the heap should be initialized to zero.
52+
/// </summary>
53+
/// <remarks>This flag is used when allocating memory from the heap to ensure that the allocated
54+
/// memory is set to zero, which can help prevent uninitialized memory access issues.</remarks>
55+
HEAP_ZERO_MEMORY = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_ZERO_MEMORY,
56+
57+
/// <summary>
58+
/// Specifies that memory reallocation should occur only at the current memory block's address, without moving
59+
/// it to a new location.
60+
/// </summary>
61+
/// <remarks>Use this flag when pointer stability is required, as it prevents the memory block
62+
/// from being relocated during reallocation. If the memory cannot be expanded in place, the reallocation will
63+
/// fail rather than move the block.</remarks>
64+
HEAP_REALLOC_IN_PLACE_ONLY = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_REALLOC_IN_PLACE_ONLY,
65+
66+
/// <summary>
67+
/// Specifies that tail checking is enabled for heap memory allocations.
68+
/// </summary>
69+
/// <remarks>When this flag is set, the system adds a small signature to the end of each allocated
70+
/// heap block and verifies its integrity when the block is freed. This helps detect buffer overruns that write
71+
/// past the end of allocated memory. Enabling tail checking may impact performance and is typically used for
72+
/// debugging purposes.</remarks>
73+
HEAP_TAIL_CHECKING_ENABLED = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_TAIL_CHECKING_ENABLED,
74+
75+
/// <summary>
76+
/// Enables heap free checking to help detect memory corruption when managing heap memory.
77+
/// </summary>
78+
/// <remarks>This flag is primarily intended for debugging and development scenarios. When
79+
/// enabled, the heap manager performs additional checks on freed memory blocks to identify potential memory
80+
/// corruption issues. It may impact performance and should not be used in production environments.</remarks>
81+
HEAP_FREE_CHECKING_ENABLED = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_FREE_CHECKING_ENABLED,
82+
83+
/// <summary>
84+
/// Specifies that the heap should not coalesce adjacent free memory blocks when memory is freed.
85+
/// </summary>
86+
/// <remarks>Use this flag when creating a heap to control how free memory blocks are managed.
87+
/// Disabling coalescing can help reduce heap fragmentation in scenarios where frequent allocations and
88+
/// deallocations of similarly sized blocks occur. However, it may also increase the number of free blocks,
89+
/// potentially impacting overall memory usage.</remarks>
90+
HEAP_DISABLE_COALESCE_ON_FREE = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_DISABLE_COALESCE_ON_FREE,
91+
92+
/// <summary>
93+
/// Specifies the heap creation flag that aligns memory allocations to a 16-byte boundary.
94+
/// </summary>
95+
/// <remarks>This flag is used when creating a heap to ensure that all memory allocations are
96+
/// aligned to 16 bytes, which can improve performance on certain architectures.</remarks>
97+
HEAP_CREATE_ALIGN_16 = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_CREATE_ALIGN_16,
98+
99+
/// <summary>
100+
/// Specifies that heap tracing is enabled for the created heap.
101+
/// </summary>
102+
/// <remarks>This flag can be used when creating a heap to enable tracing for memory allocations,
103+
/// which can assist in debugging memory-related issues.</remarks>
104+
HEAP_CREATE_ENABLE_TRACING = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_CREATE_ENABLE_TRACING,
105+
106+
/// <summary>
107+
/// Specifies that the heap created with this flag allows executable memory to be allocated.
108+
/// </summary>
109+
/// <remarks>This flag is used when creating a heap to enable the allocation of executable memory,
110+
/// which can be necessary for certain applications that require dynamic code execution.</remarks>
111+
HEAP_CREATE_ENABLE_EXECUTE = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_CREATE_ENABLE_EXECUTE,
112+
113+
/// <summary>
114+
/// Specifies the maximum tag value that can be used for heap allocations in the Windows API.
115+
/// </summary>
116+
/// <remarks>This constant is used to identify the upper limit for tag values when working with
117+
/// heap memory management functions. It is relevant when tracking or categorizing heap allocations using tags,
118+
/// and exceeding this value may result in undefined behavior or errors.</remarks>
119+
HEAP_MAXIMUM_TAG = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_MAXIMUM_TAG,
120+
121+
/// <summary>
122+
/// Specifies the heap pseudo tag flag used to indicate special tagging behavior for heap allocations in Windows
123+
/// memory management.
124+
/// </summary>
125+
/// <remarks>This flag is part of the Windows heap management system and is typically used when
126+
/// working with low-level memory operations. It enables pseudo-tagging of heap allocations, which can assist in
127+
/// debugging and profiling memory usage. Use this flag only if you require detailed tracking of heap
128+
/// allocations for diagnostic purposes.</remarks>
129+
HEAP_PSEUDO_TAG_FLAG = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_PSEUDO_TAG_FLAG,
130+
131+
/// <summary>
132+
/// Specifies the bit position used for heap tagging in heap flag values.
133+
/// </summary>
134+
/// <remarks>This constant is used when working with heap management APIs to identify or
135+
/// manipulate the tag portion of heap flags. The value corresponds to the shift amount defined by the
136+
/// underlying Windows API.</remarks>
137+
HEAP_TAG_SHIFT = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_TAG_SHIFT,
138+
139+
/// <summary>
140+
/// Specifies that the heap to be created is a segment heap, which is optimized for scenarios involving large
141+
/// memory allocations and deallocations.
142+
/// </summary>
143+
/// <remarks>Use this flag when creating a heap to enable segment heap behavior. Segment heaps can
144+
/// provide improved performance and memory usage patterns for applications that frequently allocate and free
145+
/// large blocks of memory. This flag is supported on Windows 10, version 1703 and later.</remarks>
146+
HEAP_CREATE_SEGMENT_HEAP = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_CREATE_SEGMENT_HEAP,
147+
148+
/// <summary>
149+
/// Specifies the flag used to create a hardened heap, which provides additional protection against certain
150+
/// types of memory corruption attacks.
151+
/// </summary>
152+
/// <remarks>Use this flag when creating a heap to enhance security by enabling mitigations
153+
/// against common heap exploitation techniques. This flag is part of the Windows heap management system and can
154+
/// be combined with other heap creation flags as needed.</remarks>
155+
HEAP_CREATE_HARDENED = Windows.Win32.System.Memory.HEAP_FLAGS.HEAP_CREATE_HARDENED,
156+
}
157+
}

0 commit comments

Comments
 (0)