1010 lines
23 KiB
C
1010 lines
23 KiB
C
// SPDX-FileCopyrightText: 2019 GustavoLCR <gugulcr@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#ifndef WINDOWS_HEAP_H
|
|
#define WINDOWS_HEAP_H
|
|
|
|
#include <windows.h>
|
|
#include <winternl.h>
|
|
|
|
/*
|
|
Defines most of heap related structures on Windows (some still missing)
|
|
Tested only on Windows 10 1809 x64
|
|
TODO:
|
|
Clean/organize this: Order and Style
|
|
-Can this be useful in unix? does mdmp even have a heap? remote dbg session?
|
|
x86 vs x64 Struct Differences:
|
|
-Structs definetly unaligned, check pdb
|
|
-Do something like the the linux_heap that includes itself but with another bitness
|
|
-Define macros to prefix structs to W32 or W64
|
|
|
|
Some structs are different based on the Windows version (XP, Vista, 7, Server, 8, 8.1, 10)
|
|
and updates (Service Packs, Windows 10 Seasonal Updates)
|
|
-Maybe use offsets instead of depending on structs
|
|
-Create structs for each windows version (ie post-fix XP_SP2, 7, 10_1703)?
|
|
-What about the parsing functions? Alter its behaviour depending on version or create
|
|
one function for each version
|
|
*/
|
|
#define EXTRA_FLAG (1ULL << (sizeof(size_t) * 8 - 1))
|
|
|
|
#define SHIFT 16
|
|
#define LFH_BLOCK (1 << (SHIFT))
|
|
#define LARGE_BLOCK (1 << (SHIFT + 1))
|
|
#define NT_BLOCK (1 << (SHIFT + 2))
|
|
#define SEGMENT_HEAP_BLOCK (1 << (SHIFT + 3))
|
|
#define VS_BLOCK (1 << (SHIFT + 4))
|
|
#define BACKEND_BLOCK (1 << (SHIFT + 5))
|
|
|
|
typedef struct _HEAP_LOCAL_DATA *PHEAP_LOCAL_DATA;
|
|
typedef struct _HEAP_SUBSEGMENT *PHEAP_SUBSEGMENT;
|
|
typedef struct _LFH_HEAP *PLFH_HEAP;
|
|
typedef struct _HEAP *PHEAP;
|
|
|
|
typedef struct _RTL_BALANCED_NODE *PRTL_BALANCED_NODE;
|
|
typedef struct _RTL_BALANCED_NODE {
|
|
union {
|
|
PRTL_BALANCED_NODE Children[2];
|
|
struct {
|
|
PRTL_BALANCED_NODE Left;
|
|
PRTL_BALANCED_NODE Right;
|
|
};
|
|
};
|
|
union {
|
|
BYTE Red : 1;
|
|
BYTE Balance : 2;
|
|
WPARAM ParentValue;
|
|
};
|
|
} RTL_BALANCED_NODE, *PRTL_BALANCED_NODE;
|
|
|
|
typedef struct _RTL_RB_TREE {
|
|
PRTL_BALANCED_NODE Root;
|
|
union {
|
|
BOOL Encoded : 1;
|
|
PRTL_BALANCED_NODE Min;
|
|
};
|
|
} RTL_RB_TREE, *PRTL_RB_TREE;
|
|
|
|
typedef struct _HEAP_COUNTERS {
|
|
WPARAM TotalMemoryReserved;
|
|
WPARAM TotalMemoryCommitted;
|
|
WPARAM TotalMemoryLargeUCR;
|
|
WPARAM TotalSizeInVirtualBlocks;
|
|
ULONG32 TotalSegments;
|
|
ULONG32 TotalUCRs;
|
|
ULONG32 CommittOps;
|
|
ULONG32 DeCommitOps;
|
|
ULONG32 LockAcquires;
|
|
ULONG32 LockCollisions;
|
|
ULONG32 CommitRate;
|
|
ULONG32 DecommittRate;
|
|
ULONG32 CommitFailures;
|
|
ULONG32 InBlockCommitFailures;
|
|
ULONG32 PollIntervalCounter;
|
|
ULONG32 DecommitsSinceLastCheck;
|
|
ULONG32 HeapPollInterval;
|
|
ULONG32 AllocAndFreeOps;
|
|
ULONG32 AllocationIndicesActive;
|
|
ULONG32 InBlockDeccommits;
|
|
WPARAM InBlockDeccomitSize;
|
|
WPARAM HighWatermarkSize;
|
|
WPARAM LastPolledSize;
|
|
} HEAP_COUNTERS, *PHEAP_COUNTERS;
|
|
|
|
typedef struct _HEAP_BUCKET_COUNTERS {
|
|
union {
|
|
struct {
|
|
ULONG TotalBlocks;
|
|
ULONG SubSegmentCounts;
|
|
};
|
|
UINT64 Aggregate64;
|
|
};
|
|
} HEAP_BUCKET_COUNTERS, *PHEAP_BUCKET_COUNTERS;
|
|
|
|
typedef struct _INTERLOCK_SEQ { // Is this right? NO!
|
|
union {
|
|
WORD Depth;
|
|
union {
|
|
union {
|
|
WORD Hint : 15;
|
|
WORD Lock : 1;
|
|
};
|
|
WORD Hint16;
|
|
};
|
|
INT32 Exchg;
|
|
};
|
|
} INTERLOCK_SEQ, *PINTERLOCK_SEQ;
|
|
|
|
typedef struct _HEAP_UNPACKED_ENTRY {
|
|
#if defined(_M_X64)
|
|
PVOID PreviousBlockPrivateData;
|
|
#endif
|
|
union {
|
|
struct {
|
|
UINT16 Size;
|
|
UINT8 Flags;
|
|
UINT8 SmallTagIndex;
|
|
};
|
|
#if defined(_M_X64)
|
|
struct {
|
|
ULONG32 SubSegmentCode;
|
|
UINT16 PreviousSize;
|
|
union {
|
|
UINT8 SegmentOffset;
|
|
UINT8 LFHFlags;
|
|
};
|
|
UINT8 UnusedBytes;
|
|
};
|
|
UINT64 CompactHeader;
|
|
#else
|
|
ULONG32 SubSegmentCode;
|
|
#endif
|
|
};
|
|
#if !defined(_M_X64)
|
|
UINT16 PreviousSize;
|
|
union {
|
|
UINT8 SegmentOffset;
|
|
UINT8 LFHFlags;
|
|
};
|
|
UINT8 UnusedBytes;
|
|
#endif
|
|
} HEAP_UNPACKED_ENTRY, *PHEAP_UNPACKED_ENTRY;
|
|
|
|
typedef struct _HEAP_EXTENDED_ENTRY {
|
|
#if defined(_M_X64)
|
|
PVOID Reserved;
|
|
#endif
|
|
union {
|
|
struct {
|
|
UINT16 FunctionIndex;
|
|
UINT16 ContextValue;
|
|
};
|
|
ULONG32 InterceptorValue;
|
|
};
|
|
UINT16 UnusedBytesLength;
|
|
UINT8 EntryOffset;
|
|
UINT8 ExtendedBlockSignature;
|
|
} HEAP_EXTENDED_ENTRY, *PHEAP_EXTENDED_ENTRY;
|
|
|
|
typedef struct _HEAP_ENTRY {
|
|
union {
|
|
HEAP_UNPACKED_ENTRY UnpackedEntry;
|
|
struct {
|
|
#if defined(_M_X64)
|
|
PVOID PreviousBlockPrivateData;
|
|
union {
|
|
struct {
|
|
UINT16 Size;
|
|
UINT8 Flags;
|
|
UINT8 SmallTagIndex;
|
|
};
|
|
struct {
|
|
ULONG32 SubSegmentCode;
|
|
UINT16 PreviousSize;
|
|
union {
|
|
UINT8 SegmentOffset;
|
|
UINT8 LFHFlags;
|
|
};
|
|
UINT8 UnusedBytes;
|
|
};
|
|
UINT64 CompactHeader;
|
|
};
|
|
#else
|
|
UINT16 Size;
|
|
UINT8 Flags;
|
|
UINT8 SmallTagIndex;
|
|
#endif
|
|
};
|
|
#if !defined(_M_X64)
|
|
struct {
|
|
ULONG32 SubSegmentCode;
|
|
UINT16 PreviousSize;
|
|
union {
|
|
UINT8 SegmentOffset;
|
|
UINT8 LFHFlags;
|
|
};
|
|
UINT8 UnusedBytes;
|
|
};
|
|
#endif
|
|
HEAP_EXTENDED_ENTRY ExtendedEntry;
|
|
struct {
|
|
#if defined(_M_X64)
|
|
PVOID Reserved;
|
|
union {
|
|
struct {
|
|
UINT16 FunctionIndex;
|
|
UINT16 ContextValue;
|
|
};
|
|
ULONG32 InterceptorValue;
|
|
};
|
|
UINT16 UnusedBytesLength;
|
|
UINT8 EntryOffset;
|
|
UINT8 ExtendedBlockSignature;
|
|
#else
|
|
UINT16 FunctionIndex;
|
|
UINT16 ContextValue;
|
|
#endif
|
|
};
|
|
struct {
|
|
#if defined(_M_X64)
|
|
PVOID ReservedForAlignment;
|
|
union {
|
|
struct {
|
|
ULONG32 Code1;
|
|
union {
|
|
struct {
|
|
UINT16 Code2;
|
|
UINT8 Code3;
|
|
UINT8 Code4;
|
|
};
|
|
ULONG32 Code234;
|
|
};
|
|
};
|
|
UINT64 AgregateCode;
|
|
};
|
|
#else
|
|
ULONG32 InterceptorValue;
|
|
UINT16 UnusedBytesLength;
|
|
UINT8 EntryOffset;
|
|
UINT8 ExtendedBlockSignature;
|
|
#endif
|
|
};
|
|
#if !defined(_M_X64)
|
|
struct {
|
|
ULONG32 Code1;
|
|
union {
|
|
struct {
|
|
UINT16 Code2;
|
|
UINT8 Code3;
|
|
UINT8 Code4;
|
|
};
|
|
ULONG32 Code234;
|
|
};
|
|
};
|
|
UINT64 AgregateCode;
|
|
#endif
|
|
};
|
|
} HEAP_ENTRY, *PHEAP_ENTRY;
|
|
|
|
typedef struct _HEAP_LOCK {
|
|
union {
|
|
RTL_CRITICAL_SECTION CriticalSection;
|
|
PVOID /*(ERESOURCE)*/ Resource;
|
|
} Lock;
|
|
} HEAP_LOCK, *PHEAP_LOCK;
|
|
|
|
typedef struct _HEAP_TAG_ENTRY {
|
|
ULONG32 Allocs;
|
|
ULONG32 Frees;
|
|
WPARAM Size;
|
|
UINT16 TagIndex;
|
|
UINT16 CreatorBackTraceIndex;
|
|
WCHAR TagName[24];
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING0_[4];
|
|
#endif
|
|
} HEAP_TAG_ENTRY, *PHEAP_TAG_ENTRY;
|
|
|
|
typedef struct _HEAP_PSEUDO_TAG_ENTRY {
|
|
ULONG32 Allocs;
|
|
ULONG32 Frees;
|
|
WPARAM Size;
|
|
} HEAP_PSEUDO_TAG_ENTRY, *PHEAP_PSEUDO_TAG_ENTRY;
|
|
|
|
typedef struct _HEAP_TUNING_PARAMETERS {
|
|
ULONG32 CommittThresholdShift;
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING0_[4];
|
|
#endif
|
|
WPARAM MaxPreCommittThreshold;
|
|
} HEAP_TUNING_PARAMETERS, *PHEAP_TUNING_PARAMETERS;
|
|
|
|
typedef struct _RTL_HEAP_MEMORY_LIMIT_DATA {
|
|
WPARAM CommitLimitBytes;
|
|
WPARAM CommitLimitFailureCode;
|
|
WPARAM MaxAllocationSizeBytes;
|
|
WPARAM AllocationLimitFailureCode;
|
|
} RTL_HEAP_MEMORY_LIMIT_DATA, *PRTL_HEAP_MEMORY_LIMIT_DATA;
|
|
|
|
typedef struct _RTL_HP_ENV_HANDLE {
|
|
PVOID h[2];
|
|
} RTL_HP_ENV_HANDLE, *PRTL_HP_ENV_HANDLE;
|
|
|
|
typedef struct _RTL_HP_SEG_ALLOC_POLICY {
|
|
WPARAM MinLargePages;
|
|
WPARAM MaxLargePages;
|
|
UINT8 MinUtilization;
|
|
} RTL_HP_SEG_ALLOC_POLICY, *PRTL_HP_SEG_ALLOC_POLICY;
|
|
|
|
typedef enum _RTLP_HP_LOCK_TYPE {
|
|
HeapLockPaged,
|
|
HeapLockNonPaged,
|
|
HeapLockTypeMax
|
|
} RTLP_HP_LOCK_TYPE;
|
|
|
|
typedef struct _HEAP_SUBALLOCATOR_CALLBACKS {
|
|
PVOID Allocate;
|
|
PVOID Free;
|
|
PVOID Commit;
|
|
PVOID Decommit;
|
|
PVOID ExtendContext;
|
|
} HEAP_SUBALLOCATOR_CALLBACKS, *PHEAP_SUBALLOCATOR_CALLBACKS;
|
|
|
|
typedef struct _RTL_HP_VS_CONFIG {
|
|
struct {
|
|
ULONG PageAlignLargeAllocs : 1;
|
|
ULONG FullDecommit : 1;
|
|
} Flags;
|
|
} RTL_HP_VS_CONFIG, *PRTL_HP_VS_CONFIG;
|
|
|
|
typedef struct _HEAP_VS_SUBSEGMENT {
|
|
LIST_ENTRY ListEntry;
|
|
WPARAM CommitBitmap;
|
|
WPARAM CommitLock;
|
|
UINT16 Size;
|
|
UINT16 Signature : 15;
|
|
bool FullCommit : 1;
|
|
WPARAM Spare;
|
|
} HEAP_VS_SUBSEGMENT, *PHEAP_VS_SUBSEGMENT;
|
|
|
|
typedef struct _HEAP_VS_CONTEXT {
|
|
RTL_SRWLOCK Lock;
|
|
WPARAM /*RTLP_HP_LOCK_TYPE*/ LockType;
|
|
RTL_RB_TREE FreeChunkTree;
|
|
LIST_ENTRY SubsegmentList;
|
|
WPARAM TotalCommittedUnits;
|
|
WPARAM FreeCommittedUnits;
|
|
WPARAM /*HEAP_VS_DELAY_FREE_CONTEXT*/ DelayFreeContext[8]; // 0x40 Bytes
|
|
PVOID BackendCtx;
|
|
HEAP_SUBALLOCATOR_CALLBACKS Callbacks;
|
|
RTL_HP_VS_CONFIG Config;
|
|
UINT Flags;
|
|
WPARAM Padding;
|
|
} HEAP_VS_CONTEXT, *PHEAP_VS_CONTEXT;
|
|
|
|
typedef struct _HEAP_VS_CHUNK_HEADER_SIZE {
|
|
union {
|
|
WPARAM HeaderBits;
|
|
USHORT KeyUShort;
|
|
ULONG KeyULong;
|
|
struct {
|
|
USHORT MemoryCost;
|
|
USHORT UnsafeSize;
|
|
USHORT UnsafePrevSize;
|
|
UINT8 Allocated;
|
|
};
|
|
};
|
|
} HEAP_VS_CHUNK_HEADER_SIZE, *PHEAP_VS_CHUNK_HEADER_SIZE;
|
|
|
|
typedef struct _HEAP_VS_CHUNK_HEADER {
|
|
HEAP_VS_CHUNK_HEADER_SIZE Sizes;
|
|
union {
|
|
ULONG EncodedSegmentPageOffset : 8;
|
|
ULONG UnusedBytes : 1;
|
|
ULONG SkipDuringWalk : 1;
|
|
ULONG Spare : 22;
|
|
ULONG AllocatedChunkBits;
|
|
};
|
|
} HEAP_VS_CHUNK_HEADER, *PHEAP_VS_CHUNK_HEADER;
|
|
|
|
enum {
|
|
PAGE_RANGE_FLAGS_LFH_SUBSEGMENT = 0x01,
|
|
PAGE_RANGE_FLAGS_COMMITED = 0x02,
|
|
PAGE_RANGE_FLAGS_ALLOCATED = 0x04,
|
|
PAGE_RANGE_FLAGS_FIRST = 0x08,
|
|
PAGE_RANGE_FLAGS_VS_SUBSEGMENT = 0x20 // LIES
|
|
};
|
|
|
|
typedef struct _HEAP_PAGE_RANGE_DESCRIPTOR {
|
|
union {
|
|
RTL_BALANCED_NODE TreeNode;
|
|
struct {
|
|
ULONG TreeSignature;
|
|
ULONG UnusedBytes;
|
|
};
|
|
union {
|
|
bool ExtraPresent;
|
|
UINT16 Spare0 : 15;
|
|
};
|
|
};
|
|
UCHAR RangeFlags;
|
|
UCHAR CommittedPageCount;
|
|
USHORT Spare;
|
|
union {
|
|
//_HEAP_DESCRIPTOR_KEY Key;
|
|
UCHAR Align[3];
|
|
};
|
|
union {
|
|
UCHAR UnitOffset;
|
|
UCHAR UnitSize;
|
|
};
|
|
} HEAP_PAGE_RANGE_DESCRIPTOR, *PHEAP_PAGE_RANGE_DESCRIPTOR;
|
|
|
|
typedef struct _HEAP_PAGE_SEGMENT {
|
|
union {
|
|
struct {
|
|
LIST_ENTRY ListEntry;
|
|
WPARAM Signature;
|
|
PVOID SegmentCommitState;
|
|
UCHAR UnusedWatermark;
|
|
};
|
|
HEAP_PAGE_RANGE_DESCRIPTOR DescArray[256];
|
|
};
|
|
} HEAP_PAGE_SEGMENT, *PHEAP_PAGE_SEGMENT;
|
|
|
|
typedef struct _RTL_HP_LFH_CONFIG {
|
|
USHORT MaxBlockSize;
|
|
BYTE WitholdPageCrossingBlocks : 1;
|
|
} RTL_HP_LFH_CONFIG, *PRTL_HP_LFH_CONFIG;
|
|
|
|
typedef struct _HEAP_LFH_SUBSEGMENT_STAT {
|
|
BYTE Index;
|
|
BYTE Count;
|
|
} HEAP_LFH_SUBSEGMENT_STAT, *PHEAP_LFH_SUBSEGMENT_STAT;
|
|
|
|
typedef struct _HEAP_LFH_SUBSEGMENT_STATS {
|
|
union {
|
|
HEAP_LFH_SUBSEGMENT_STAT Buckets[4];
|
|
UINT64 Stats;
|
|
};
|
|
} HEAP_LFH_SUBSEGMENT_STATS, *PHEAP_LFH_SUBSEGMENT_STATS;
|
|
|
|
typedef struct _HEAP_LFH_SUBSEGMENT_OWNER {
|
|
struct {
|
|
BYTE IsBucket : 1;
|
|
BYTE Spare0 : 7;
|
|
};
|
|
BYTE BucketIndex;
|
|
union {
|
|
BYTE SlotCount;
|
|
BYTE SlotIndex;
|
|
};
|
|
BYTE Spare1;
|
|
WPARAM AvailableSubsegmentCount;
|
|
RTL_SRWLOCK Lock;
|
|
LIST_ENTRY AvailableSubsegmentList;
|
|
LIST_ENTRY FullSubsegmentList;
|
|
} HEAP_LFH_SUBSEGMENT_OWNER, *PHEAP_LFH_SUBSEGMENT_OWNER;
|
|
|
|
typedef struct _HEAP_LFH_FAST_REF {
|
|
union {
|
|
PVOID Target;
|
|
WPARAM Value;
|
|
UINT16 RefCount : 12;
|
|
};
|
|
} HEAP_LFH_FAST_REF, *PHEAP_LFH_FAST_REF;
|
|
|
|
typedef struct _HEAP_LFH_AFFINITY_SLOT {
|
|
HEAP_LFH_SUBSEGMENT_OWNER State;
|
|
HEAP_LFH_FAST_REF ActiveSubsegment;
|
|
} HEAP_LFH_AFFINITY_SLOT, *PHEAP_LFH_AFFINITY_SLOT;
|
|
|
|
typedef struct _HEAP_LFH_BUCKET {
|
|
HEAP_LFH_SUBSEGMENT_OWNER State;
|
|
WPARAM TotalBlockCount;
|
|
WPARAM TotalSubsegmentCount;
|
|
UINT ReciprocalBlockSize;
|
|
UINT8 Shift;
|
|
UINT8 ContentionCount;
|
|
WPARAM AffinityMappingLock;
|
|
PUINT8 ProcAffinityMapping;
|
|
PHEAP_LFH_AFFINITY_SLOT *AffinitySlots;
|
|
} HEAP_LFH_BUCKET, *PHEAP_LFH_BUCKET;
|
|
|
|
typedef struct _HEAP_LFH_CONTEXT {
|
|
PVOID BackendCtx;
|
|
HEAP_SUBALLOCATOR_CALLBACKS Callbacks;
|
|
PUINT8 AffinityModArray;
|
|
UINT8 MaxAffinity;
|
|
UINT8 LockType;
|
|
USHORT MemStatsOffset;
|
|
RTL_HP_LFH_CONFIG Config;
|
|
HEAP_LFH_SUBSEGMENT_STATS BucketStats;
|
|
WPARAM SubsegmentCreationLock;
|
|
WPARAM Padding[6];
|
|
PHEAP_LFH_BUCKET Buckets[129];
|
|
} HEAP_LFH_CONTEXT, *PHEAP_LFH_CONTEXT;
|
|
|
|
typedef struct _HEAP_LFH_SUBSEGMENT_ENCODED_OFFSETS {
|
|
union {
|
|
UINT32 EncodedData;
|
|
struct {
|
|
UINT16 BlockSize;
|
|
UINT16 FirstBlockOffset;
|
|
};
|
|
};
|
|
} HEAP_LFH_SUBSEGMENT_ENCODED_OFFSETS, *PHEAP_LFH_SUBSEGMENT_ENCODED_OFFSETS;
|
|
|
|
typedef struct _HEAP_LFH_SUBSEGMENT {
|
|
LIST_ENTRY ListEntry;
|
|
union {
|
|
PHEAP_LFH_SUBSEGMENT_OWNER Owner;
|
|
WPARAM /*HEAP_LFH_SUBSEGMENT_DELAY_FREE*/ DelayFree;
|
|
};
|
|
WPARAM CommitLock;
|
|
union {
|
|
struct {
|
|
UINT16 FreeCount;
|
|
UINT16 BlockCount;
|
|
};
|
|
union {
|
|
SHORT InterlockedShort;
|
|
LONG InterlockedLong;
|
|
};
|
|
};
|
|
UINT16 FreeHint;
|
|
BYTE Location;
|
|
BYTE WitheldBlockCount;
|
|
HEAP_LFH_SUBSEGMENT_ENCODED_OFFSETS BlockOffsets;
|
|
BYTE CommitUnitShift;
|
|
BYTE CommitUnitCount;
|
|
UINT16 CommitStateOffset;
|
|
WPARAM BlockBitmap[1];
|
|
} HEAP_LFH_SUBSEGMENT, *PHEAP_LFH_SUBSEGMENT;
|
|
|
|
typedef struct _HEAP_LARGE_ALLOC_DATA {
|
|
RTL_BALANCED_NODE TreeNode;
|
|
union {
|
|
WPARAM VirtualAddess;
|
|
UINT16 UnusedBytes;
|
|
};
|
|
union {
|
|
UINT64 BitMask;
|
|
union {
|
|
bool ExtraPresent : 1;
|
|
bool GuardPageCount : 1;
|
|
UINT8 GuardPageAlignment : 6;
|
|
UINT8 Spare : 4;
|
|
UINT64 AllocatedPages : 52;
|
|
};
|
|
};
|
|
} HEAP_LARGE_ALLOC_DATA, *PHEAP_LARGE_ALLOC_DATA;
|
|
|
|
typedef struct _HEAP_OPPORTUNISTIC_LARGE_PAGE_STATS {
|
|
WPARAM SmallPagesInUseWithinLarge;
|
|
WPARAM OpportunisticLargePageCount;
|
|
} HEAP_OPPORTUNISTIC_LARGE_PAGE_STATS, *PHEAP_OPPORTUNISTIC_LARGE_PAGE_STATS;
|
|
|
|
typedef struct _HEAP_RUNTIME_MEMORY_STATS {
|
|
WPARAM TotalReservedPages;
|
|
WPARAM TotalCommittedPages;
|
|
WPARAM FreeCommittedPages;
|
|
WPARAM LfhFreeCommittedPages;
|
|
HEAP_OPPORTUNISTIC_LARGE_PAGE_STATS LargePageStats[2];
|
|
RTL_HP_SEG_ALLOC_POLICY LargePageUtilizationPolicy;
|
|
} HEAP_RUNTIME_MEMORY_STATS, *PHEAP_RUNTIME_MEMORY_STATS;
|
|
|
|
typedef struct _HEAP_SEG_CONTEXT {
|
|
UINT64 SegmentMask;
|
|
BYTE UnitShift;
|
|
BYTE PagesPerUnitShift;
|
|
BYTE FirstDescriptorIndex;
|
|
BYTE CachedCommitSoftShift;
|
|
BYTE CachedCommitHighShift;
|
|
UINT16 Flags;
|
|
UINT MaxAllocationSize;
|
|
UINT16 OlpStatsOffset;
|
|
UINT16 MemStatsOffset;
|
|
PVOID LfhContext;
|
|
PVOID VsContext;
|
|
RTL_HP_ENV_HANDLE EnvHandle;
|
|
PVOID Heap;
|
|
WPARAM SegmentLock;
|
|
LIST_ENTRY SegmentListHead;
|
|
WPARAM SegmentCount;
|
|
RTL_RB_TREE FreePageRanges;
|
|
WPARAM FreeSegmentListLock;
|
|
SINGLE_LIST_ENTRY FreeSegmentList[2];
|
|
WPARAM Padding[7];
|
|
} HEAP_SEG_CONTEXT, *PHEAP_SEG_CONTEXT;
|
|
|
|
typedef struct _SEGMENT_HEAP {
|
|
RTL_HP_ENV_HANDLE EnvHandle;
|
|
ULONG Signature;
|
|
ULONG GlobalFlags;
|
|
ULONG Interceptor;
|
|
USHORT ProcessHeapListIndex;
|
|
USHORT AllocatedFromMetadata : 1;
|
|
union {
|
|
RTL_HEAP_MEMORY_LIMIT_DATA CommitLimitData;
|
|
struct {
|
|
UINT64 ReservedMustBeZero1;
|
|
PVOID UserContext;
|
|
PVOID ReservedMustBeZero2;
|
|
PVOID Spare;
|
|
};
|
|
};
|
|
RTL_SRWLOCK LargeMetadataLock;
|
|
RTL_RB_TREE LargeAllocMetadata; // Tree of HEAP_LARGE_ALLOC_DATA
|
|
WPARAM LargeReservedPages;
|
|
WPARAM LargeCommittedPages;
|
|
RTL_RUN_ONCE StackTraceInitVar;
|
|
WPARAM Padding[2];
|
|
HEAP_RUNTIME_MEMORY_STATS MemStats;
|
|
UINT16 GlobalLockCount;
|
|
ULONG GlobalLockOwner;
|
|
RTL_SRWLOCK ContextExtendLock;
|
|
PUINT8 AllocatedBase;
|
|
PUINT8 UncommittedBase;
|
|
PUINT8 ReservedLimit;
|
|
HEAP_SEG_CONTEXT SegContexts[2];
|
|
HEAP_VS_CONTEXT VsContext;
|
|
HEAP_LFH_CONTEXT LfhContext;
|
|
} SEGMENT_HEAP, *PSEGMENT_HEAP;
|
|
|
|
typedef struct _HEAP_SEGMENT {
|
|
HEAP_ENTRY Entry;
|
|
ULONG32 SegmentSignature;
|
|
ULONG32 SegmentFlags;
|
|
LIST_ENTRY SegmentListEntry;
|
|
PHEAP Heap;
|
|
PVOID BaseAddress;
|
|
ULONG32 NumberOfPages;
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING0_[4];
|
|
#endif
|
|
PHEAP_ENTRY FirstEntry;
|
|
PHEAP_ENTRY LastValidEntry;
|
|
ULONG32 NumberOfUnCommittedPages;
|
|
ULONG32 NumberOfUnCommittedRanges;
|
|
UINT16 SegmentAllocatorBackTraceIndex;
|
|
UINT16 Reserved;
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING1_[4];
|
|
#endif
|
|
LIST_ENTRY UCRSegmentList;
|
|
} HEAP_SEGMENT, *PHEAP_SEGMENT;
|
|
|
|
typedef struct _HEAP {
|
|
union {
|
|
HEAP_SEGMENT Segment;
|
|
struct {
|
|
HEAP_ENTRY Entry;
|
|
ULONG32 SegmentSignature;
|
|
ULONG32 SegmentFlags;
|
|
LIST_ENTRY SegmentListEntry;
|
|
PHEAP Heap;
|
|
PVOID BaseAddress;
|
|
ULONG32 NumberOfPages;
|
|
PHEAP_ENTRY FirstEntry;
|
|
PHEAP_ENTRY LastValidEntry;
|
|
ULONG32 NumberOfUnCommittedPages;
|
|
ULONG32 NumberOfUnCommittedRanges;
|
|
UINT16 SegmentAllocatorBackTraceIndex;
|
|
UINT16 Reserved;
|
|
LIST_ENTRY UCRSegmentList;
|
|
};
|
|
};
|
|
ULONG32 Flags;
|
|
ULONG32 ForceFlags;
|
|
ULONG32 CompatibilityFlags;
|
|
ULONG32 EncodeFlagMask;
|
|
HEAP_ENTRY Encoding;
|
|
ULONG32 Interceptor;
|
|
ULONG32 VirtualMemoryThreshold;
|
|
ULONG32 Signature;
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING0_[4];
|
|
#endif
|
|
WPARAM SegmentReserve;
|
|
WPARAM SegmentCommit;
|
|
WPARAM DeCommitFreeBlockThreshold;
|
|
WPARAM DeCommitTotalFreeThreshold;
|
|
WPARAM TotalFreeSize;
|
|
WPARAM MaximumAllocationSize;
|
|
UINT16 ProcessHeapsListIndex;
|
|
UINT16 HeaderValidateLength;
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING1_[4];
|
|
#endif
|
|
PVOID HeaderValidateCopy;
|
|
UINT16 NextAvailableTagIndex;
|
|
UINT16 MaximumTagIndex;
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING2_[4];
|
|
#endif
|
|
PHEAP_TAG_ENTRY TagEntries;
|
|
LIST_ENTRY UCRzList;
|
|
WPARAM AlignRound;
|
|
WPARAM AlignMask;
|
|
LIST_ENTRY VirtualAllocdBlocks;
|
|
LIST_ENTRY SegmentList;
|
|
UINT16 AllocatorBackTraceIndex;
|
|
UINT8 _PADDING03_[2];
|
|
ULONG32 NonDedicatedListLength;
|
|
PVOID BlocksIndex;
|
|
PVOID UCRIndex;
|
|
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries;
|
|
LIST_ENTRY FreeLists;
|
|
PHEAP_LOCK LockVariable;
|
|
LONG32(WINAPI *CommitRoutine)(PVOID, PVOID *, WPARAM *);
|
|
RTL_RUN_ONCE StackTraceInitVar;
|
|
RTL_HEAP_MEMORY_LIMIT_DATA CommitLimitData;
|
|
PVOID FrontEndHeap;
|
|
UINT16 FrontHeapLockCount;
|
|
UINT8 FrontEndHeapType;
|
|
UINT8 RequestedFrontEndHeapType;
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING4_[4];
|
|
#endif
|
|
PUINT16 FrontEndHeapUsageData;
|
|
UINT16 FrontEndHeapMaximumIndex;
|
|
#if defined(_M_X64)
|
|
UINT8 FrontEndHeapStatusBitmap[129];
|
|
#else
|
|
UINT8 FrontEndHeapStatusBitmap[257];
|
|
#endif
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING5_[5];
|
|
#else
|
|
UINT8 _PADDING1_[1];
|
|
#endif
|
|
HEAP_COUNTERS Counters;
|
|
HEAP_TUNING_PARAMETERS TuningParameters;
|
|
} HEAP, *PHEAP;
|
|
|
|
typedef struct _HEAP_ENTRY_EXTRA {
|
|
union {
|
|
struct {
|
|
UINT16 AllocatorBackTraceIndex;
|
|
UINT16 TagIndex;
|
|
#if defined(_M_X64)
|
|
UINT8 _PADDING0_[4];
|
|
#endif
|
|
WPARAM Settable;
|
|
};
|
|
#if defined(_M_X64)
|
|
struct {
|
|
UINT64 ZeroInit;
|
|
UINT64 ZeroInit1;
|
|
};
|
|
#else
|
|
UINT64 ZeroInit;
|
|
#endif
|
|
};
|
|
} HEAP_ENTRY_EXTRA, *PHEAP_ENTRY_EXTRA;
|
|
|
|
typedef struct _HEAP_VIRTUAL_ALLOC_ENTRY {
|
|
LIST_ENTRY Entry;
|
|
HEAP_ENTRY_EXTRA ExtraStuff;
|
|
WPARAM CommitSize;
|
|
WPARAM ReserveSize;
|
|
HEAP_ENTRY BusyBlock;
|
|
} HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY;
|
|
|
|
typedef struct _LFH_BLOCK_ZONE {
|
|
LIST_ENTRY ListEntry;
|
|
LONG NextIndex;
|
|
/* // Win 7
|
|
PVOID FreePointer;
|
|
PVOID Limit;
|
|
*/
|
|
} LFH_BLOCK_ZONE, *PLFH_BLOCK_ZONE;
|
|
|
|
typedef struct _HEAP_USERDATA_OFFSETS {
|
|
union {
|
|
UINT32 StrideAndOffset;
|
|
struct {
|
|
UINT16 FirstAllocationOffset;
|
|
UINT16 BlockStride;
|
|
};
|
|
};
|
|
} HEAP_USERDATA_OFFSETS, *PHEAP_USERDATA_OFFSETS;
|
|
|
|
typedef struct _RTL_BITMAP_EX {
|
|
WPARAM SizeOfBitMap;
|
|
WPARAM *Buffer;
|
|
} RTL_BITMAP_EX, *PRTL_BITMAP_EX;
|
|
|
|
typedef struct _HEAP_USERDATA_HEADER {
|
|
union {
|
|
SINGLE_LIST_ENTRY SFreeListEntry;
|
|
PHEAP_SUBSEGMENT SubSegment;
|
|
};
|
|
PVOID Reserved;
|
|
union {
|
|
UINT32 SizeIndexAndPadding;
|
|
struct {
|
|
UCHAR SizeIndex;
|
|
UCHAR GuardPagePresent;
|
|
UINT16 PaddingBytes;
|
|
};
|
|
};
|
|
ULONG Signature;
|
|
HEAP_USERDATA_OFFSETS EncodedOffsets;
|
|
RTL_BITMAP_EX BusyBitmap;
|
|
WPARAM BitmapData;
|
|
} HEAP_USERDATA_HEADER, *PHEAP_USERDATA_HEADER;
|
|
|
|
typedef struct _HEAP_SUBSEGMENT *PHEAP_SUBSEGMENT;
|
|
typedef struct _HEAP_LOCAL_SEGMENT_INFO {
|
|
PHEAP_LOCAL_DATA LocalData;
|
|
PHEAP_SUBSEGMENT ActiveSubsegment;
|
|
PHEAP_SUBSEGMENT CachedItems[16];
|
|
SLIST_HEADER SListHeader;
|
|
HEAP_BUCKET_COUNTERS Counters;
|
|
ULONG LastOpSequence;
|
|
UINT16 BucketIndex;
|
|
UINT16 LastUsed;
|
|
UINT16 NoThrashCount;
|
|
} HEAP_LOCAL_SEGMENT_INFO, *PHEAP_LOCAL_SEGMENT_INFO;
|
|
|
|
typedef struct _HEAP_SUBSEGMENT {
|
|
PHEAP_LOCAL_SEGMENT_INFO LocalInfo;
|
|
PHEAP_USERDATA_HEADER UserBlocks;
|
|
SLIST_HEADER DelayFreeList;
|
|
INTERLOCK_SEQ AggregateExchg;
|
|
union {
|
|
struct {
|
|
WORD BlockSize;
|
|
WORD Flags;
|
|
WORD BlockCount;
|
|
UINT8 SizeIndex;
|
|
UINT8 AffinityIndex;
|
|
};
|
|
ULONG Alignment[2];
|
|
};
|
|
ULONG Lock;
|
|
SINGLE_LIST_ENTRY SFreeListEntry;
|
|
} HEAP_SUBSEGMENT, *PHEAP_SUBSEGMENT;
|
|
|
|
typedef struct _HEAP_LFH_MEM_POLICIES {
|
|
union {
|
|
ULONG AllPolicies;
|
|
union {
|
|
UINT8 DisableAffinity : 1;
|
|
UINT8 SlowSubsegmentGrowth : 1;
|
|
ULONG Spare : 30;
|
|
};
|
|
};
|
|
} HEAP_LFH_MEM_POLICIES, *PHEAP_LFH_MEM_POLICIES;
|
|
|
|
typedef struct _HEAP_LOCAL_DATA {
|
|
SLIST_HEADER DeletedSubSegments;
|
|
PLFH_BLOCK_ZONE CrtZone;
|
|
PLFH_HEAP LowFragHeap;
|
|
ULONG Sequence;
|
|
// HEAP_LOCAL_SEGMENT_INFO SegmentInfo[128]; // Only on Win7
|
|
} HEAP_LOCAL_DATA, *PHEAP_LOCAL_DATA;
|
|
|
|
typedef struct _HEAP_BUCKET {
|
|
WORD BlockUnits;
|
|
UINT8 SizeIndex;
|
|
union {
|
|
BYTE Flags;
|
|
union {
|
|
BYTE UseAffinity : 1;
|
|
BYTE DebugFlags : 2;
|
|
};
|
|
};
|
|
} HEAP_BUCKET, *PHEAP_BUCKET;
|
|
|
|
typedef struct _HEAP_BUCKET_RUN_INFO {
|
|
union {
|
|
struct {
|
|
ULONG Bucket;
|
|
ULONG RunLength;
|
|
};
|
|
UINT64 Aggregate64;
|
|
};
|
|
} HEAP_BUCKET_RUN_INFO, *PHEAP_BUCKET_RUN_INFO;
|
|
|
|
typedef struct _USER_MEMORY_CACHE_ENTRY {
|
|
SLIST_HEADER UserBlocks;
|
|
ULONG AvailableBlocks;
|
|
ULONG MinimumDepth;
|
|
ULONG CacheShiftThreshold;
|
|
USHORT Allocations;
|
|
USHORT Frees;
|
|
USHORT CacheHits;
|
|
} USER_MEMORY_CACHE_ENTRY, *PUSER_MEMORY_CACHE_ENTRY;
|
|
|
|
typedef struct _LFH_HEAP {
|
|
RTL_SRWLOCK Lock;
|
|
LIST_ENTRY SubSegmentZones;
|
|
PVOID Heap;
|
|
PVOID NextSegmentInfoArrayAddress;
|
|
PVOID FirstUncommittedAddress;
|
|
PVOID ReservedAddressLimit;
|
|
ULONG SegmentCreate;
|
|
ULONG SegmentDelete;
|
|
ULONG MinimumCacheDepth;
|
|
ULONG CacheShiftThreshold;
|
|
WPARAM SizeInCache;
|
|
HEAP_BUCKET_RUN_INFO RunInfo;
|
|
USER_MEMORY_CACHE_ENTRY UserBlockCache[12];
|
|
HEAP_LFH_MEM_POLICIES MemoryPolicies;
|
|
HEAP_BUCKET Buckets[129];
|
|
PHEAP_LOCAL_SEGMENT_INFO SegmentInfoArrays[129];
|
|
PHEAP_LOCAL_SEGMENT_INFO AffinitizedInfoArrays[129];
|
|
PSEGMENT_HEAP SegmentAllocator;
|
|
HEAP_LOCAL_DATA LocalData[1];
|
|
} LFH_HEAP, *PLFH_HEAP;
|
|
|
|
typedef struct _HeapBlockBasicInfo {
|
|
WPARAM size;
|
|
WPARAM flags;
|
|
WPARAM extra;
|
|
WPARAM address;
|
|
} HeapBlockBasicInfo, *PHeapBlockBasicInfo;
|
|
|
|
typedef struct _HeapBlockExtraInfo { // think of extra stuff to put here
|
|
WPARAM heap;
|
|
WPARAM segment;
|
|
WPARAM unusedBytes;
|
|
USHORT granularity;
|
|
} HeapBlockExtraInfo, *PHeapBlockExtraInfo;
|
|
|
|
typedef struct _HeapBlock {
|
|
ULONG_PTR dwAddress;
|
|
SIZE_T dwSize;
|
|
DWORD dwFlags;
|
|
SIZE_T index;
|
|
PHeapBlockExtraInfo extraInfo;
|
|
} HeapBlock, *PHeapBlock;
|
|
|
|
typedef struct _DEBUG_BUFFER {
|
|
HANDLE SectionHandle;
|
|
PVOID SectionBase;
|
|
PVOID RemoteSectionBase;
|
|
WPARAM SectionBaseDelta;
|
|
HANDLE EventPairHandle;
|
|
HANDLE RemoteEventPairHandle;
|
|
HANDLE RemoteProcessId;
|
|
HANDLE RemoteThreadHandle;
|
|
ULONG InfoClassMask;
|
|
SIZE_T SizeOfInfo;
|
|
SIZE_T AllocatedSize;
|
|
SIZE_T SectionSize;
|
|
PVOID ModuleInformation;
|
|
PVOID BackTraceInformation;
|
|
PVOID HeapInformation;
|
|
PVOID LockInformation;
|
|
PVOID SpecificHeap;
|
|
HANDLE RemoteProcessHandle;
|
|
PVOID VerifierOptions;
|
|
PVOID ProcessHeap;
|
|
HANDLE CriticalSectionHandle;
|
|
HANDLE CriticalSectionOwnerThread;
|
|
PVOID Reserved[4];
|
|
} DEBUG_BUFFER, *PDEBUG_BUFFER;
|
|
|
|
typedef struct _DEBUG_HEAP_INFORMATION {
|
|
PVOID Base;
|
|
DWORD Flags;
|
|
USHORT Granularity;
|
|
USHORT CreatorBackTraceIndex;
|
|
SIZE_T Allocated;
|
|
SIZE_T Committed;
|
|
DWORD TagCount;
|
|
DWORD BlockCount;
|
|
DWORD PseudoTagCount;
|
|
DWORD PseudoTagGranularity;
|
|
DWORD Reserved[5];
|
|
PVOID Tags;
|
|
PVOID Blocks;
|
|
} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;
|
|
|
|
typedef struct _HeapInformation {
|
|
DWORD count;
|
|
DEBUG_HEAP_INFORMATION heaps[/* count */];
|
|
} HeapInformation, *PHeapInformation;
|
|
|
|
PDEBUG_BUFFER(NTAPI *RtlCreateQueryDebugBuffer)(
|
|
IN DWORD Size,
|
|
IN BOOLEAN EventPair);
|
|
|
|
NTSTATUS(NTAPI *RtlQueryProcessDebugInformation)(
|
|
IN DWORD ProcessId,
|
|
IN DWORD DebugInfoClassMask,
|
|
IN OUT PDEBUG_BUFFER DebugBuffer);
|
|
|
|
NTSTATUS(NTAPI *RtlDestroyQueryDebugBuffer)(
|
|
IN PDEBUG_BUFFER DebugBuffer);
|
|
|
|
__kernel_entry NTSTATUS(NTAPI *w32_NtQueryInformationProcess)(
|
|
IN HANDLE ProcessHandle,
|
|
IN PROCESSINFOCLASS ProcessInformationClass,
|
|
OUT PVOID ProcessInformation,
|
|
IN ULONG ProcessInformationLength,
|
|
OUT PULONG ReturnLength);
|
|
#endif
|