Add memory-region query, enumeration, and scoped protection

Implements VirtualQueryEx + MEMORY_BASIC_INFORMATION wrappers, the immutable MemoryRegion record, the ProtectionScope disposable helper, and MemoryBase.QueryRegion/EnumerateRegions/ChangeProtection. Closes section 1 of add-thread-region-finder.
This commit is contained in:
kbe
2026-07-22 16:04:15 +02:00
parent e8c84f0ba1
commit f0faca3112
7 changed files with 504 additions and 0 deletions
+58
View File
@@ -205,3 +205,61 @@ public unsafe struct Context64
/// <summary>The source RIP of the last exception.</summary>
public ulong LastExceptionFromRip;
}
/// <summary>
/// Layout matches <c>MEMORY_BASIC_INFORMATION</c>. Uses pointer-sized fields so the
/// structure is 28 bytes on x86 and 48 bytes on x64, matching the layout the OS expects
/// from a caller of those bitnesses.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct MemoryBasicInformation
{
/// <summary>A pointer to the base address of the region of pages.</summary>
public nint BaseAddress;
/// <summary>A pointer to the base address of a range of pages allocated by the VirtualAllocEx function.</summary>
public nint AllocationBase;
/// <summary>The memory protection option when the region was initially allocated.</summary>
public uint AllocationProtect;
/// <summary>The size of the region beginning at the base address, in bytes.</summary>
public nuint RegionSize;
/// <summary>The state of the pages in the region.</summary>
public uint State;
/// <summary>The access protection of the pages in the region.</summary>
public uint Protect;
/// <summary>The type of pages in the region.</summary>
public uint Type;
}
/// <summary>
/// Layout matches <c>THREADENTRY32</c> used by <c>Thread32First</c>/<c>Thread32Next</c>.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ThreadEntry32
{
/// <summary>The size of the structure, in bytes.</summary>
public uint dwSize;
/// <summary>This member is no longer used and is always zero.</summary>
public uint cntUsage;
/// <summary>The thread identifier.</summary>
public uint th32ThreadID;
/// <summary>The identifier of the process that owns the thread.</summary>
public uint th32OwnerProcessID;
/// <summary>The kernel base priority level assigned to the thread.</summary>
public int tpBasePri;
/// <summary>This member is no longer used.</summary>
public int tpDeltaPri;
/// <summary>This member is reserved.</summary>
public uint dwFlags;
}