ReactOS 0.4.15-dev-7961-gdcf9eb0
heap.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _HEAP_COMMON_ENTRY
 
struct  _HEAP_FREE_ENTRY
 
struct  _HEAP_ENTRY
 
struct  _HEAP_TAG_ENTRY
 
struct  _HEAP_PSEUDO_TAG_ENTRY
 
struct  _HEAP_COUNTERS
 
struct  _HEAP_TUNING_PARAMETERS
 
struct  _HEAP_LIST_LOOKUP
 
struct  _HEAP
 
struct  _HEAP_SEGMENT
 
struct  _HEAP_UCR_DESCRIPTOR
 
struct  _HEAP_UCR_SEGMENT
 
struct  _HEAP_ENTRY_EXTRA
 
struct  _HEAP_VIRTUAL_ALLOC_ENTRY
 

Macros

#define HEAP_SEGMENTS   64
 
#define HEAP_ENTRY_SIZE   ((ULONG)sizeof(HEAP_ENTRY))
 
#define HEAP_ENTRY_SHIFT   3
 
#define HEAP_MAX_BLOCK_SIZE   ((0x80000 - PAGE_SIZE) >> HEAP_ENTRY_SHIFT)
 
#define ARENA_INUSE_FILLER   0xBAADF00D
 
#define ARENA_FREE_FILLER   0xFEEEFEEE
 
#define HEAP_TAIL_FILL   0xab
 
#define HEAP_GLOBAL_TAG   0x0800
 
#define HEAP_PSEUDO_TAG_FLAG   0x8000
 
#define HEAP_TAG_MASK   (HEAP_MAXIMUM_TAG << HEAP_TAG_SHIFT)
 
#define HEAP_TAGS_MASK   (HEAP_TAG_MASK ^ (0xFF << HEAP_TAG_SHIFT))
 
#define HEAP_EXTRA_FLAGS_MASK
 
#define HEAP_ENTRY_BUSY   0x01
 
#define HEAP_ENTRY_EXTRA_PRESENT   0x02
 
#define HEAP_ENTRY_FILL_PATTERN   0x04
 
#define HEAP_ENTRY_VIRTUAL_ALLOC   0x08
 
#define HEAP_ENTRY_LAST_ENTRY   0x10
 
#define HEAP_ENTRY_SETTABLE_FLAG1   0x20
 
#define HEAP_ENTRY_SETTABLE_FLAG2   0x40
 
#define HEAP_ENTRY_SETTABLE_FLAG3   0x80
 
#define HEAP_ENTRY_SETTABLE_FLAGS   (HEAP_ENTRY_SETTABLE_FLAG1 | HEAP_ENTRY_SETTABLE_FLAG2 | HEAP_ENTRY_SETTABLE_FLAG3)
 
#define HEAP_SIGNATURE   0xeefeeff
 
#define HEAP_SEGMENT_SIGNATURE   0xffeeffee
 
#define HEAP_USER_ALLOCATED   0x1
 
#define HEAP_SEGMENT_MEMBERS
 

Typedefs

typedef struct _HEAP_FREE_ENTRY HEAP_FREE_ENTRY
 
typedef struct _HEAP_FREE_ENTRYPHEAP_FREE_ENTRY
 
typedef struct _HEAP_ENTRY HEAP_ENTRY
 
typedef struct _HEAP_ENTRYPHEAP_ENTRY
 
typedef struct _HEAP_TAG_ENTRY HEAP_TAG_ENTRY
 
typedef struct _HEAP_TAG_ENTRYPHEAP_TAG_ENTRY
 
typedef struct _HEAP_PSEUDO_TAG_ENTRY HEAP_PSEUDO_TAG_ENTRY
 
typedef struct _HEAP_PSEUDO_TAG_ENTRYPHEAP_PSEUDO_TAG_ENTRY
 
typedef struct _HEAP_COUNTERS HEAP_COUNTERS
 
typedef struct _HEAP_COUNTERSPHEAP_COUNTERS
 
typedef struct _HEAP_TUNING_PARAMETERS HEAP_TUNING_PARAMETERS
 
typedef struct _HEAP_TUNING_PARAMETERSPHEAP_TUNING_PARAMETERS
 
typedef struct _HEAP_LIST_LOOKUP HEAP_LIST_LOOKUP
 
typedef struct _HEAP_LIST_LOOKUPPHEAP_LIST_LOOKUP
 
typedef struct _HEAP HEAP
 
typedef struct _HEAPPHEAP
 
typedef struct _HEAP_SEGMENT HEAP_SEGMENT
 
typedef struct _HEAP_SEGMENTPHEAP_SEGMENT
 
typedef struct _HEAP_UCR_DESCRIPTOR HEAP_UCR_DESCRIPTOR
 
typedef struct _HEAP_UCR_DESCRIPTORPHEAP_UCR_DESCRIPTOR
 
typedef struct _HEAP_UCR_SEGMENT HEAP_UCR_SEGMENT
 
typedef struct _HEAP_UCR_SEGMENTPHEAP_UCR_SEGMENT
 
typedef struct _HEAP_ENTRY_EXTRA HEAP_ENTRY_EXTRA
 
typedef struct _HEAP_ENTRY_EXTRAPHEAP_ENTRY_EXTRA
 
typedef HEAP_ENTRY_EXTRA HEAP_FREE_ENTRY_EXTRA
 
typedef HEAP_ENTRY_EXTRAPHEAP_FREE_ENTRY_EXTRA
 
typedef struct _HEAP_VIRTUAL_ALLOC_ENTRY HEAP_VIRTUAL_ALLOC_ENTRY
 
typedef struct _HEAP_VIRTUAL_ALLOC_ENTRYPHEAP_VIRTUAL_ALLOC_ENTRY
 

Functions

FORCEINLINE BOOLEAN RtlpHeapIsSpecial (ULONG Flags)
 
 C_ASSERT (sizeof(HEAP_ENTRY)==8)
 
 C_ASSERT ((1<< HEAP_ENTRY_SHIFT)==sizeof(HEAP_ENTRY))
 
 C_ASSERT ((2<< HEAP_ENTRY_SHIFT)==sizeof(HEAP_FREE_ENTRY))
 
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceFreeBlocks (PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, PSIZE_T FreeSize, BOOLEAN Remove)
 
PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer (PHEAP_ENTRY HeapEntry)
 
BOOLEAN NTAPI RtlpValidateHeap (PHEAP Heap, BOOLEAN ForceValidation)
 
BOOLEAN NTAPI RtlpValidateHeapEntry (PHEAP Heap, PHEAP_ENTRY HeapEntry)
 
BOOLEAN NTAPI RtlpValidateHeapHeaders (PHEAP Heap, BOOLEAN Recalculate)
 
NTSYSAPI HANDLE NTAPI RtlDebugCreateHeap (ULONG Flags, PVOID Addr, SIZE_T TotalSize, SIZE_T CommitSize, PVOID Lock, PRTL_HEAP_PARAMETERS Parameters)
 
BOOLEAN NTAPI RtlDebugDestroyHeap (HANDLE HeapPtr)
 
PVOID NTAPI RtlDebugAllocateHeap (PVOID HeapPtr, ULONG Flags, SIZE_T Size)
 
PVOID NTAPI RtlDebugReAllocateHeap (HANDLE HeapPtr, ULONG Flags, PVOID Ptr, SIZE_T Size)
 
BOOLEAN NTAPI RtlDebugFreeHeap (HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
 
BOOLEAN NTAPI RtlDebugGetUserInfoHeap (PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID *UserValue, PULONG UserFlags)
 
BOOLEAN NTAPI RtlDebugSetUserValueHeap (PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID UserValue)
 
BOOLEAN NTAPI RtlDebugSetUserFlagsHeap (PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, ULONG UserFlagsReset, ULONG UserFlagsSet)
 
SIZE_T NTAPI RtlDebugSizeHeap (HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
 
HANDLE NTAPI RtlpPageHeapCreate (ULONG Flags, PVOID Addr, SIZE_T TotalSize, SIZE_T CommitSize, PVOID Lock, PRTL_HEAP_PARAMETERS Parameters)
 
PVOID NTAPI RtlpPageHeapDestroy (HANDLE HeapPtr)
 
PVOID NTAPI RtlpPageHeapAllocate (IN PVOID HeapPtr, IN ULONG Flags, IN SIZE_T Size)
 
BOOLEAN NTAPI RtlpPageHeapFree (HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
 
PVOID NTAPI RtlpPageHeapReAllocate (HANDLE HeapPtr, ULONG Flags, PVOID Ptr, SIZE_T Size)
 
BOOLEAN NTAPI RtlpPageHeapLock (HANDLE HeapPtr)
 
BOOLEAN NTAPI RtlpPageHeapUnlock (HANDLE HeapPtr)
 
BOOLEAN NTAPI RtlpPageHeapGetUserInfo (PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID *UserValue, PULONG UserFlags)
 
BOOLEAN NTAPI RtlpPageHeapSetUserValue (PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID UserValue)
 
BOOLEAN NTAPI RtlpPageHeapSetUserFlags (PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, ULONG UserFlagsReset, ULONG UserFlagsSet)
 
BOOLEAN NTAPI RtlpDebugPageHeapValidate (PVOID HeapPtr, ULONG Flags, PVOID Block)
 
SIZE_T NTAPI RtlpPageHeapSize (HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
 
VOID NTAPI RtlpAddHeapToProcessList (PHEAP Heap)
 
VOID NTAPI RtlpRemoveHeapFromProcessList (PHEAP Heap)
 
VOID NTAPI RtlInitializeHeapManager (VOID)
 

Variables

RTL_CRITICAL_SECTION RtlpProcessHeapsListLock
 
BOOLEAN RtlpPageHeapEnabled
 

Macro Definition Documentation

◆ ARENA_FREE_FILLER

#define ARENA_FREE_FILLER   0xFEEEFEEE

Definition at line 26 of file heap.h.

◆ ARENA_INUSE_FILLER

#define ARENA_INUSE_FILLER   0xBAADF00D

Definition at line 25 of file heap.h.

◆ HEAP_ENTRY_BUSY

#define HEAP_ENTRY_BUSY   0x01

Definition at line 40 of file heap.h.

◆ HEAP_ENTRY_EXTRA_PRESENT

#define HEAP_ENTRY_EXTRA_PRESENT   0x02

Definition at line 41 of file heap.h.

◆ HEAP_ENTRY_FILL_PATTERN

#define HEAP_ENTRY_FILL_PATTERN   0x04

Definition at line 42 of file heap.h.

◆ HEAP_ENTRY_LAST_ENTRY

#define HEAP_ENTRY_LAST_ENTRY   0x10

Definition at line 44 of file heap.h.

◆ HEAP_ENTRY_SETTABLE_FLAG1

#define HEAP_ENTRY_SETTABLE_FLAG1   0x20

Definition at line 45 of file heap.h.

◆ HEAP_ENTRY_SETTABLE_FLAG2

#define HEAP_ENTRY_SETTABLE_FLAG2   0x40

Definition at line 46 of file heap.h.

◆ HEAP_ENTRY_SETTABLE_FLAG3

#define HEAP_ENTRY_SETTABLE_FLAG3   0x80

Definition at line 47 of file heap.h.

◆ HEAP_ENTRY_SETTABLE_FLAGS

Definition at line 48 of file heap.h.

◆ HEAP_ENTRY_SHIFT

#define HEAP_ENTRY_SHIFT   3

Definition at line 21 of file heap.h.

◆ HEAP_ENTRY_SIZE

#define HEAP_ENTRY_SIZE   ((ULONG)sizeof(HEAP_ENTRY))

Definition at line 17 of file heap.h.

◆ HEAP_ENTRY_VIRTUAL_ALLOC

#define HEAP_ENTRY_VIRTUAL_ALLOC   0x08

Definition at line 43 of file heap.h.

◆ HEAP_EXTRA_FLAGS_MASK

#define HEAP_EXTRA_FLAGS_MASK
Value:
#define HEAP_CAPTURE_STACK_BACKTRACES
Definition: rtltypes.h:164
#define HEAP_SETTABLE_USER_VALUE
Definition: nt_native.h:1704
#define HEAP_TAGS_MASK
Definition: heap.h:33

Definition at line 35 of file heap.h.

◆ HEAP_GLOBAL_TAG

#define HEAP_GLOBAL_TAG   0x0800

Definition at line 30 of file heap.h.

◆ HEAP_MAX_BLOCK_SIZE

#define HEAP_MAX_BLOCK_SIZE   ((0x80000 - PAGE_SIZE) >> HEAP_ENTRY_SHIFT)

Definition at line 23 of file heap.h.

◆ HEAP_PSEUDO_TAG_FLAG

#define HEAP_PSEUDO_TAG_FLAG   0x8000

Definition at line 31 of file heap.h.

◆ HEAP_SEGMENT_MEMBERS

#define HEAP_SEGMENT_MEMBERS
Value:
ULONG SegmentSignature; \
ULONG SegmentFlags; \
LIST_ENTRY SegmentListEntry; \
struct _HEAP *Heap; \
ULONG NumberOfPages; \
PHEAP_ENTRY FirstEntry; \
PHEAP_ENTRY LastValidEntry; \
ULONG NumberOfUnCommittedPages; \
ULONG NumberOfUnCommittedRanges; \
USHORT SegmentAllocatorBackTraceIndex; \
LIST_ENTRY UCRSegmentList
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
unsigned short USHORT
Definition: pedump.c:61
base of all file and directory entries
Definition: entries.h:83
Definition: heap.h:136
Definition: heap.c:52
Definition: typedefs.h:120
uint32_t ULONG
Definition: typedefs.h:59
_Reserved_ PVOID Reserved
Definition: winddi.h:3974

Definition at line 206 of file heap.h.

◆ HEAP_SEGMENT_SIGNATURE

#define HEAP_SEGMENT_SIGNATURE   0xffeeffee

Definition at line 52 of file heap.h.

◆ HEAP_SEGMENTS

#define HEAP_SEGMENTS   64

Definition at line 15 of file heap.h.

◆ HEAP_SIGNATURE

#define HEAP_SIGNATURE   0xeefeeff

Definition at line 51 of file heap.h.

◆ HEAP_TAG_MASK

#define HEAP_TAG_MASK   (HEAP_MAXIMUM_TAG << HEAP_TAG_SHIFT)

Definition at line 32 of file heap.h.

◆ HEAP_TAGS_MASK

#define HEAP_TAGS_MASK   (HEAP_TAG_MASK ^ (0xFF << HEAP_TAG_SHIFT))

Definition at line 33 of file heap.h.

◆ HEAP_TAIL_FILL

#define HEAP_TAIL_FILL   0xab

Definition at line 27 of file heap.h.

◆ HEAP_USER_ALLOCATED

#define HEAP_USER_ALLOCATED   0x1

Definition at line 55 of file heap.h.

Typedef Documentation

◆ HEAP

typedef struct _HEAP HEAP

◆ HEAP_COUNTERS

◆ HEAP_ENTRY

◆ HEAP_ENTRY_EXTRA

◆ HEAP_FREE_ENTRY

◆ HEAP_FREE_ENTRY_EXTRA

Definition at line 305 of file heap.h.

◆ HEAP_LIST_LOOKUP

◆ HEAP_PSEUDO_TAG_ENTRY

◆ HEAP_SEGMENT

◆ HEAP_TAG_ENTRY

◆ HEAP_TUNING_PARAMETERS

◆ HEAP_UCR_DESCRIPTOR

◆ HEAP_UCR_SEGMENT

◆ HEAP_VIRTUAL_ALLOC_ENTRY

◆ PHEAP

typedef struct _HEAP * PHEAP

◆ PHEAP_COUNTERS

◆ PHEAP_ENTRY

◆ PHEAP_ENTRY_EXTRA

◆ PHEAP_FREE_ENTRY

◆ PHEAP_FREE_ENTRY_EXTRA

Definition at line 305 of file heap.h.

◆ PHEAP_LIST_LOOKUP

◆ PHEAP_PSEUDO_TAG_ENTRY

◆ PHEAP_SEGMENT

◆ PHEAP_TAG_ENTRY

◆ PHEAP_TUNING_PARAMETERS

◆ PHEAP_UCR_DESCRIPTOR

◆ PHEAP_UCR_SEGMENT

◆ PHEAP_VIRTUAL_ALLOC_ENTRY

Function Documentation

◆ C_ASSERT() [1/3]

C_ASSERT ( (1<< HEAP_ENTRY_SHIFT = =sizeof(HEAP_ENTRY))

◆ C_ASSERT() [2/3]

C_ASSERT ( (2<< HEAP_ENTRY_SHIFT = =sizeof(HEAP_FREE_ENTRY))

◆ C_ASSERT() [3/3]

C_ASSERT ( sizeof(HEAP_ENTRY = =8)

◆ RtlDebugAllocateHeap()

PVOID NTAPI RtlDebugAllocateHeap ( PVOID  HeapPtr,
ULONG  Flags,
SIZE_T  Size 
)

Definition at line 130 of file heapdbg.c.

133{
134 PHEAP Heap = (PHEAP)HeapPtr;
135 SIZE_T AllocSize = 1;
136 BOOLEAN HeapLocked = FALSE;
138
140 return RtlpPageHeapAllocate(HeapPtr, Flags, Size);
141
142 if (Heap->Signature != HEAP_SIGNATURE)
143 {
144 DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
145 return NULL;
146 }
147
148 /* Add settable user value flag */
150
151 /* Calculate size */
152 if (Size) AllocSize = Size;
153 AllocSize = ((AllocSize + Heap->AlignRound) & Heap->AlignMask) + sizeof(HEAP_ENTRY_EXTRA);
154
155 /* Check if size didn't exceed max one */
156 if (AllocSize < Size ||
157 AllocSize > Heap->MaximumAllocationSize)
158 {
159 DPRINT1("HEAP: Too big allocation size %x (max allowed %x)\n", Size, Heap->MaximumAllocationSize);
160 return NULL;
161 }
162
163 /* Lock the heap ourselves */
164 if (!(Flags & HEAP_NO_SERIALIZE))
165 {
167 HeapLocked = TRUE;
168
169 /* Add no serialize flag so that the main routine won't try to acquire the lock again */
171 }
172
173 /* Validate the heap if necessary */
174 RtlpValidateHeap(Heap, FALSE);
175
176 /* Call main routine to do the stuff */
177 Result = RtlAllocateHeap(HeapPtr, Flags, Size);
178
179 /* Validate heap headers */
181
182 if (Result)
183 {
185 RtlpValidateHeap(Heap, FALSE);
186 }
187
188 /* Release the lock */
189 if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
190
191 return Result;
192}
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
struct _HEAP * PHEAP
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
NTSTATUS NTAPI RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:133
#define HEAP_SKIP_VALIDATION_CHECKS
Definition: rtltypes.h:165
#define HEAP_VALIDATE_ALL_ENABLED
Definition: rtltypes.h:166
#define HEAP_FLAG_PAGE_ALLOCS
Definition: rtltypes.h:160
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
BOOLEAN NTAPI RtlpValidateHeap(PHEAP Heap, BOOLEAN ForceValidation)
Definition: heap.c:3513
BOOLEAN NTAPI RtlpValidateHeapHeaders(PHEAP Heap, BOOLEAN Recalculate)
Definition: heap.c:3260
struct _HEAP_ENTRY_EXTRA HEAP_ENTRY_EXTRA
#define HEAP_SIGNATURE
Definition: heap.h:51
PVOID NTAPI RtlpPageHeapAllocate(IN PVOID HeapPtr, IN ULONG Flags, IN SIZE_T Size)
Definition: heappage.c:1758
ULONG Flags
Definition: heap.h:226
ULONG_PTR AlignRound
Definition: heap.h:249
ULONG ForceFlags
Definition: heap.h:227
ULONG_PTR AlignMask
Definition: heap.h:250
ULONG Signature
Definition: heap.h:234
SIZE_T MaximumAllocationSize
Definition: heap.h:240
PHEAP_LOCK LockVariable
Definition: heap.h:260
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by RtlAllocateHeap().

◆ RtlDebugCreateHeap()

NTSYSAPI HANDLE NTAPI RtlDebugCreateHeap ( ULONG  Flags,
PVOID  Addr,
SIZE_T  TotalSize,
SIZE_T  CommitSize,
PVOID  Lock,
PRTL_HEAP_PARAMETERS  Parameters 
)

Definition at line 20 of file heapdbg.c.

26{
27 MEMORY_BASIC_INFORMATION MemoryInfo;
29 PHEAP Heap;
30
31 /* Validate parameters */
33 {
34 DPRINT1("HEAP: Incorrect ReserveSize %x\n", ReserveSize);
35 return NULL;
36 }
37
39 {
40 DPRINT1("HEAP: Incorrect CommitSize %x\n", CommitSize);
41 return NULL;
42 }
43
45 {
46 DPRINT1("HEAP: Can't specify Lock routine and have HEAP_NO_SERIALIZE flag set\n");
47 return NULL;
48 }
49
50 /* If the address is specified, check it's virtual memory */
51 if (Addr)
52 {
54 Addr,
56 &MemoryInfo,
57 sizeof(MemoryInfo),
58 NULL);
59
60 if (!NT_SUCCESS(Status))
61 {
62 DPRINT1("HEAP: Specified heap base address %p is invalid, Status 0x%08X\n", Addr, Status);
63 return NULL;
64 }
65
66 if (MemoryInfo.BaseAddress != Addr)
67 {
68 DPRINT1("HEAP: Specified heap base address %p is not really a base one %p\n", Addr, MemoryInfo.BaseAddress);
69 return NULL;
70 }
71
72 if (MemoryInfo.State == MEM_FREE)
73 {
74 DPRINT1("HEAP: Specified heap base address %p is free\n", Addr);
75 return NULL;
76 }
77 }
78
79 /* All validation performed, now call the real routine with skip validation check flag */
83
85 if (!Heap) return NULL;
86
87 // FIXME: Capture stack backtrace
88
90
91 return Heap;
92}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:25
NTSYSAPI NTSTATUS NTAPI ZwQueryVirtualMemory(_In_ HANDLE ProcessHandle, _In_ PVOID Address, _In_ MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass, _Out_ PVOID VirtualMemoryInformation, _In_ SIZE_T Length, _Out_opt_ PSIZE_T ResultLength)
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:406
@ MemoryBasicInformation
Definition: mmtypes.h:183
#define MEM_FREE
Definition: nt_native.h:1317
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
NTSYSAPI PVOID NTAPI RtlCreateHeap(IN ULONG Flags, IN PVOID HeapBase OPTIONAL, IN ULONG ReserveSize OPTIONAL, IN ULONG CommitSize OPTIONAL, IN PVOID Lock OPTIONAL, IN PRTL_HEAP_PARAMETERS Parameters OPTIONAL)
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define HEAP_ENTRY_SIZE
Definition: heap.h:17
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
_In_opt_ PVOID _In_opt_ SIZE_T ReserveSize
Definition: rtlfuncs.h:2168

Referenced by RtlCreateHeap().

◆ RtlDebugDestroyHeap()

BOOLEAN NTAPI RtlDebugDestroyHeap ( HANDLE  HeapPtr)

Definition at line 95 of file heapdbg.c.

96{
97 SIZE_T Size = 0;
98 PHEAP Heap = (PHEAP)HeapPtr;
99
100 if (Heap == RtlGetCurrentPeb()->ProcessHeap)
101 {
102 DPRINT1("HEAP: It's forbidden delete process heap!");
103 return FALSE;
104 }
105
106 if (Heap->Signature != HEAP_SIGNATURE)
107 {
108 DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
109 return FALSE;
110 }
111
112 if (!RtlpValidateHeap(Heap, FALSE)) return FALSE;
113
114 /* Make heap invalid by zeroing its signature */
115 Heap->Signature = 0;
116
117 /* Free validate headers copy if it was existing */
118 if (Heap->HeaderValidateCopy)
119 {
120 ZwFreeVirtualMemory(NtCurrentProcess(),
121 &Heap->HeaderValidateCopy,
122 &Size,
124 }
125
126 return TRUE;
127}
NTSYSAPI PEB *WINAPI RtlGetCurrentPeb(void)
Definition: libsupp.c:63
#define MEM_RELEASE
Definition: nt_native.h:1316
PVOID HeaderValidateCopy
Definition: heap.h:243
PVOID ProcessHeap
Definition: ntddk_ex.h:249

Referenced by RtlDestroyHeap().

◆ RtlDebugFreeHeap()

BOOLEAN NTAPI RtlDebugFreeHeap ( HANDLE  HeapPtr,
ULONG  Flags,
PVOID  Ptr 
)

Definition at line 267 of file heapdbg.c.

270{
271 PHEAP Heap = (PHEAP)HeapPtr;
272 BOOLEAN HeapLocked = FALSE;
273 PHEAP_ENTRY HeapEntry;
275
277 return RtlpPageHeapFree(HeapPtr, Flags, Ptr);
278
279 if (Heap->Signature != HEAP_SIGNATURE)
280 {
281 DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
282 return FALSE;
283 }
284
285 /* Add skip validation flag */
287
288 /* Lock the heap ourselves */
289 if (!(Flags & HEAP_NO_SERIALIZE))
290 {
292 HeapLocked = TRUE;
293
294 /* Add no serialize flag so that the main routine won't try to acquire the lock again */
296 }
297
298 /* Validate the heap if necessary */
299 RtlpValidateHeap(Heap, FALSE);
300
301 /* Get the existing heap entry */
302 HeapEntry = (PHEAP_ENTRY)Ptr - 1;
303
304 /* Validate it */
305 if (RtlpValidateHeapEntry(Heap, HeapEntry))
306 {
307 /* If it succeeded - call the main routine */
308 Result = RtlFreeHeap(HeapPtr, Flags, Ptr);
309
310 /* Validate heap headers and then heap itself */
312 RtlpValidateHeap(Heap, FALSE);
313 }
314
315 /* Release the lock */
316 if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
317
318 return Result;
319}
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
BOOLEAN NTAPI RtlpValidateHeapEntry(PHEAP Heap, PHEAP_ENTRY HeapEntry)
Definition: heap.c:3269
struct _HEAP_ENTRY * PHEAP_ENTRY
BOOLEAN NTAPI RtlpPageHeapFree(HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
Definition: heappage.c:1923

Referenced by RtlFreeHeap().

◆ RtlDebugGetUserInfoHeap()

BOOLEAN NTAPI RtlDebugGetUserInfoHeap ( PVOID  HeapHandle,
ULONG  Flags,
PVOID  BaseAddress,
PVOID UserValue,
PULONG  UserFlags 
)

Definition at line 322 of file heapdbg.c.

327{
328 PHEAP Heap = (PHEAP)HeapHandle;
329 BOOLEAN HeapLocked = FALSE;
330 PHEAP_ENTRY HeapEntry;
332
334 return RtlpPageHeapGetUserInfo(HeapHandle, Flags, BaseAddress, UserValue, UserFlags);
335
336 if (Heap->Signature != HEAP_SIGNATURE)
337 {
338 DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
339 return FALSE;
340 }
341
342 /* Add skip validation flag */
344
345 /* Lock the heap ourselves */
346 if (!(Flags & HEAP_NO_SERIALIZE))
347 {
349 HeapLocked = TRUE;
350
351 /* Add no serialize flag so that the main routine won't try to acquire the lock again */
353 }
354
355 /* Validate the heap if necessary */
356 RtlpValidateHeap(Heap, FALSE);
357
358 /* Get the existing heap entry */
359 HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
360
361 /* Validate it */
362 if (RtlpValidateHeapEntry(Heap, HeapEntry))
363 {
364 /* If it succeeded - call the main routine */
365 Result = RtlGetUserInfoHeap(HeapHandle, Flags, BaseAddress, UserValue, UserFlags);
366 }
367
368 /* Release the lock */
369 if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
370
371 return Result;
372}
BOOLEAN NTAPI RtlGetUserInfoHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, OUT PVOID *UserValue, OUT PULONG UserFlags)
Definition: heap.c:3915
BOOLEAN NTAPI RtlpPageHeapGetUserInfo(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID *UserValue, PULONG UserFlags)
Definition: heappage.c:2185

Referenced by RtlGetUserInfoHeap().

◆ RtlDebugReAllocateHeap()

PVOID NTAPI RtlDebugReAllocateHeap ( HANDLE  HeapPtr,
ULONG  Flags,
PVOID  Ptr,
SIZE_T  Size 
)

Definition at line 195 of file heapdbg.c.

199{
200 PHEAP Heap = (PHEAP)HeapPtr;
201 SIZE_T AllocSize = 1;
202 BOOLEAN HeapLocked = FALSE;
203 PVOID Result = NULL;
204 PHEAP_ENTRY HeapEntry;
205
207 return RtlpPageHeapReAllocate(HeapPtr, Flags, Ptr, Size);
208
209 if (Heap->Signature != HEAP_SIGNATURE)
210 {
211 DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
212 return NULL;
213 }
214
215 /* Add settable user value flag */
217
218 /* Calculate size */
219 if (Size) AllocSize = Size;
220 AllocSize = ((AllocSize + Heap->AlignRound) & Heap->AlignMask) + sizeof(HEAP_ENTRY_EXTRA);
221
222 /* Check if size didn't exceed max one */
223 if (AllocSize < Size ||
224 AllocSize > Heap->MaximumAllocationSize)
225 {
226 DPRINT1("HEAP: Too big allocation size %x (max allowed %x)\n", Size, Heap->MaximumAllocationSize);
227 return NULL;
228 }
229
230 /* Lock the heap ourselves */
231 if (!(Flags & HEAP_NO_SERIALIZE))
232 {
234 HeapLocked = TRUE;
235
236 /* Add no serialize flag so that the main routine won't try to acquire the lock again */
238 }
239
240 /* Validate the heap if necessary */
241 RtlpValidateHeap(Heap, FALSE);
242
243 /* Get the existing heap entry */
244 HeapEntry = (PHEAP_ENTRY)Ptr - 1;
245
246 /* Validate it */
247 if (RtlpValidateHeapEntry(Heap, HeapEntry))
248 {
249 /* Call main routine to do the stuff */
250 Result = RtlReAllocateHeap(HeapPtr, Flags, Ptr, Size);
251
252 if (Result)
253 {
254 /* Validate heap headers and then heap itself */
256 RtlpValidateHeap(Heap, FALSE);
257 }
258 }
259
260 /* Release the lock */
261 if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
262
263 return Result;
264}
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2667
PVOID NTAPI RtlpPageHeapReAllocate(HANDLE HeapPtr, ULONG Flags, PVOID Ptr, SIZE_T Size)
Definition: heappage.c:2015

Referenced by RtlReAllocateHeap().

◆ RtlDebugSetUserFlagsHeap()

BOOLEAN NTAPI RtlDebugSetUserFlagsHeap ( PVOID  HeapHandle,
ULONG  Flags,
PVOID  BaseAddress,
ULONG  UserFlagsReset,
ULONG  UserFlagsSet 
)

Definition at line 431 of file heapdbg.c.

436{
437 PHEAP Heap = (PHEAP)HeapHandle;
438 BOOLEAN HeapLocked = FALSE;
439 PHEAP_ENTRY HeapEntry;
441
443 return RtlpPageHeapSetUserFlags(HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet);
444
445 /* Check if this heap allows flags to be set at all */
446 if (UserFlagsSet & ~HEAP_SETTABLE_USER_FLAGS ||
447 UserFlagsReset & ~HEAP_SETTABLE_USER_FLAGS)
448 {
449 return FALSE;
450 }
451
452 if (Heap->Signature != HEAP_SIGNATURE)
453 {
454 DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
455 return FALSE;
456 }
457
458 /* Add skip validation flag */
460
461 /* Lock the heap ourselves */
462 if (!(Flags & HEAP_NO_SERIALIZE))
463 {
465 HeapLocked = TRUE;
466
467 /* Add no serialize flag so that the main routine won't try to acquire the lock again */
469 }
470
471 /* Validate the heap if necessary */
472 RtlpValidateHeap(Heap, FALSE);
473
474 /* Get the existing heap entry */
475 HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
476
477 /* Validate it */
478 if (RtlpValidateHeapEntry(Heap, HeapEntry))
479 {
480 /* If it succeeded - call the main routine */
481 Result = RtlSetUserFlagsHeap(HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet);
482
483 /* Validate the heap */
484 RtlpValidateHeap(Heap, FALSE);
485 }
486
487 /* Release the lock */
488 if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
489
490 return Result;
491}
#define HEAP_SETTABLE_USER_FLAGS
Definition: nt_native.h:1708
BOOLEAN NTAPI RtlSetUserFlagsHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN ULONG UserFlagsReset, IN ULONG UserFlagsSet)
Definition: heap.c:3860
BOOLEAN NTAPI RtlpPageHeapSetUserFlags(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, ULONG UserFlagsReset, ULONG UserFlagsSet)
Definition: heappage.c:2268

Referenced by RtlSetUserFlagsHeap().

◆ RtlDebugSetUserValueHeap()

BOOLEAN NTAPI RtlDebugSetUserValueHeap ( PVOID  HeapHandle,
ULONG  Flags,
PVOID  BaseAddress,
PVOID  UserValue 
)

Definition at line 375 of file heapdbg.c.

379{
380 PHEAP Heap = (PHEAP)HeapHandle;
381 BOOLEAN HeapLocked = FALSE;
382 PHEAP_ENTRY HeapEntry;
384
386 return RtlpPageHeapSetUserValue(HeapHandle, Flags, BaseAddress, UserValue);
387
388 if (Heap->Signature != HEAP_SIGNATURE)
389 {
390 DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
391 return FALSE;
392 }
393
394 /* Add skip validation flag */
396
397 /* Lock the heap ourselves */
398 if (!(Flags & HEAP_NO_SERIALIZE))
399 {
401 HeapLocked = TRUE;
402
403 /* Add no serialize flag so that the main routine won't try to acquire the lock again */
405 }
406
407 /* Validate the heap if necessary */
408 RtlpValidateHeap(Heap, FALSE);
409
410 /* Get the existing heap entry */
411 HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
412
413 /* Validate it */
414 if (RtlpValidateHeapEntry(Heap, HeapEntry))
415 {
416 /* If it succeeded - call the main routine */
417 Result = RtlSetUserValueHeap(HeapHandle, Flags, BaseAddress, UserValue);
418
419 /* Validate the heap */
420 RtlpValidateHeap(Heap, FALSE);
421 }
422
423 /* Release the lock */
424 if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
425
426 return Result;
427}
BOOLEAN NTAPI RtlSetUserValueHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN PVOID UserValue)
Definition: heap.c:3798
BOOLEAN NTAPI RtlpPageHeapSetUserValue(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID UserValue)
Definition: heappage.c:2227

Referenced by RtlSetUserValueHeap().

◆ RtlDebugSizeHeap()

SIZE_T NTAPI RtlDebugSizeHeap ( HANDLE  HeapPtr,
ULONG  Flags,
PVOID  Ptr 
)

Definition at line 494 of file heapdbg.c.

497{
498 PHEAP Heap = (PHEAP)HeapPtr;
499 BOOLEAN HeapLocked = FALSE;
500 PHEAP_ENTRY HeapEntry;
501 SIZE_T Result = ~(SIZE_T)0;
502
504 return RtlpPageHeapSize(HeapPtr, Flags, Ptr);
505
506 /* Check heap signature */
507 if (Heap->Signature != HEAP_SIGNATURE)
508 {
509 DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
510 return FALSE;
511 }
512
513 /* Add skip validation flag */
515
516 /* Lock the heap ourselves */
517 if (!(Flags & HEAP_NO_SERIALIZE))
518 {
520 HeapLocked = TRUE;
521
522 /* Add no serialize flag so that the main routine won't try to acquire the lock again */
524 }
525
526 /* Validate the heap if necessary */
527 RtlpValidateHeap(Heap, FALSE);
528
529 /* Get the existing heap entry */
530 HeapEntry = (PHEAP_ENTRY)Ptr - 1;
531
532 /* Validate it */
533 if (RtlpValidateHeapEntry(Heap, HeapEntry))
534 {
535 /* If it succeeded - call the main routine */
536 Result = RtlSizeHeap(HeapPtr, Flags, Ptr);
537 }
538
539 /* Release the lock */
540 if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
541
542 return Result;
543}
NTSYSAPI SIZE_T NTAPI RtlSizeHeap(_In_ PVOID HeapHandle, _In_ ULONG Flags, _In_ PVOID MemoryPointer)
SIZE_T NTAPI RtlpPageHeapSize(HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
Definition: heappage.c:2310

Referenced by RtlSizeHeap().

◆ RtlInitializeHeapManager()

VOID NTAPI RtlInitializeHeapManager ( VOID  )

Definition at line 243 of file libsupp.c.

244{
245}

◆ RtlpAddHeapToProcessList()

VOID NTAPI RtlpAddHeapToProcessList ( PHEAP  Heap)

Definition at line 23 of file heapuser.c.

24{
25 PPEB Peb;
26
27 /* Get PEB */
29
30 /* Acquire the lock */
32
33 //_SEH2_TRY {
34 /* Check if max number of heaps reached */
36 {
37 // TODO: Handle this case
39 }
40
41 /* Add the heap to the process heaps */
45 // } _SEH2_FINALLY {
46
47 /* Release the lock */
49
50 // } _SEH2_END
51}
PPEB Peb
Definition: dllmain.c:27
RTL_CRITICAL_SECTION RtlpProcessHeapsListLock
Definition: heapuser.c:17
#define ASSERT(a)
Definition: mode.c:44
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
USHORT ProcessHeapsListIndex
Definition: heap.h:241
ULONG MaximumNumberOfHeaps
Definition: ntddk_ex.h:287
PVOID * ProcessHeaps
Definition: ntddk_ex.h:288
ULONG NumberOfHeaps
Definition: ntddk_ex.h:286

◆ RtlpCoalesceFreeBlocks()

PHEAP_FREE_ENTRY NTAPI RtlpCoalesceFreeBlocks ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry,
PSIZE_T  FreeSize,
BOOLEAN  Remove 
)

Definition at line 1150 of file heap.c.

1154{
1155 PHEAP_FREE_ENTRY CurrentEntry, NextEntry;
1156 UCHAR SegmentOffset;
1157
1158 /* Get the previous entry */
1159 CurrentEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry - FreeEntry->PreviousSize);
1160
1161 /* Check it */
1162 if (CurrentEntry != FreeEntry &&
1163 !(CurrentEntry->Flags & HEAP_ENTRY_BUSY) &&
1164 (*FreeSize + CurrentEntry->Size) <= HEAP_MAX_BLOCK_SIZE)
1165 {
1166 ASSERT(FreeEntry->PreviousSize == CurrentEntry->Size);
1167
1168 /* Remove it if asked for */
1169 if (Remove)
1170 {
1171 RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE);
1172 Heap->TotalFreeSize -= FreeEntry->Size;
1173
1174 /* Remove it only once! */
1175 Remove = FALSE;
1176 }
1177
1178 /* Remove previous entry too */
1179 RtlpRemoveFreeBlock(Heap, CurrentEntry, FALSE);
1180
1181 /* Copy flags */
1182 CurrentEntry->Flags = FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY;
1183
1184 /* Advance FreeEntry and update sizes */
1185 FreeEntry = CurrentEntry;
1186 *FreeSize = *FreeSize + CurrentEntry->Size;
1187 Heap->TotalFreeSize -= CurrentEntry->Size;
1188 FreeEntry->Size = (USHORT)(*FreeSize);
1189
1190 /* Also update previous size if needed */
1191 if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1192 {
1193 ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
1194 }
1195 else
1196 {
1197 SegmentOffset = FreeEntry->SegmentOffset;
1198 ASSERT(SegmentOffset < HEAP_SEGMENTS);
1199 }
1200 }
1201
1202 /* Check the next block if it exists */
1203 if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1204 {
1205 NextEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + *FreeSize);
1206
1207 if (!(NextEntry->Flags & HEAP_ENTRY_BUSY) &&
1208 NextEntry->Size + *FreeSize <= HEAP_MAX_BLOCK_SIZE)
1209 {
1210 ASSERT(*FreeSize == NextEntry->PreviousSize);
1211
1212 /* Remove it if asked for */
1213 if (Remove)
1214 {
1215 RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE);
1216 Heap->TotalFreeSize -= FreeEntry->Size;
1217 }
1218
1219 /* Copy flags */
1220 FreeEntry->Flags = NextEntry->Flags & HEAP_ENTRY_LAST_ENTRY;
1221
1222 /* Remove next entry now */
1223 RtlpRemoveFreeBlock(Heap, NextEntry, FALSE);
1224
1225 /* Update sizes */
1226 *FreeSize = *FreeSize + NextEntry->Size;
1227 Heap->TotalFreeSize -= NextEntry->Size;
1228 FreeEntry->Size = (USHORT)(*FreeSize);
1229
1230 /* Also update previous size if needed */
1231 if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1232 {
1233 ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
1234 }
1235 else
1236 {
1237 SegmentOffset = FreeEntry->SegmentOffset;
1238 ASSERT(SegmentOffset < HEAP_SEGMENTS);
1239 }
1240 }
1241 }
1242 return FreeEntry;
1243}
static VOID RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN NoFill)
Definition: heap.c:422
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:23
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44
#define HEAP_SEGMENTS
Definition: heap.h:15
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
Definition: heap.h:130
SIZE_T TotalFreeSize
Definition: heap.h:239
_In_ BOOLEAN Remove
Definition: psfuncs.h:110
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by RtlFreeHeap(), RtlpDeCommitFreeBlock(), RtlpExtendHeap(), and RtlpGrowBlockInPlace().

◆ RtlpDebugPageHeapValidate()

BOOLEAN NTAPI RtlpDebugPageHeapValidate ( PVOID  HeapPtr,
ULONG  Flags,
PVOID  Block 
)

Definition at line 2351 of file heappage.c.

2354{
2355 PDPH_HEAP_ROOT DphRoot;
2357 BOOLEAN Valid = FALSE;
2358
2359 /* Get a pointer to the heap root */
2360 DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2361 if (!DphRoot) return -1;
2362
2363 /* Add heap flags */
2364 Flags |= DphRoot->HeapFlags;
2365
2366 /* Acquire the heap lock */
2367 RtlpDphPreProcessing(DphRoot, Flags);
2368
2369 /* Find busy memory */
2370 if (BaseAddress)
2372
2373 if (!Node)
2374 {
2375 /* This block was not found in page heap, or the request is to validate all normal heap */
2376 Valid = RtlpDphNormalHeapValidate(DphRoot, Flags, BaseAddress);
2377 }
2378
2379 /* Leave the heap lock */
2380 RtlpDphPostProcessing(DphRoot);
2381
2382 /* Return result of a normal heap validation */
2383 if (BaseAddress && !Node)
2384 return Valid;
2385
2386 /* Otherwise return our own result */
2387 if (!BaseAddress || Node) Valid = TRUE;
2388
2389 return Valid;
2390}
VOID NTAPI RtlpDphPreProcessing(PDPH_HEAP_ROOT DphRoot, ULONG Flags)
Definition: heappage.c:297
PVOID NTAPI RtlpDphPointerFromHandle(PVOID Handle)
Definition: heappage.c:223
VOID NTAPI RtlpDphPostProcessing(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:305
BOOLEAN NTAPI RtlpDphNormalHeapValidate(PDPH_HEAP_ROOT DphRoot, ULONG Flags, PVOID BaseAddress)
Definition: heappage.c:2394
PDPH_HEAP_BLOCK NTAPI RtlpDphFindBusyMemory(PDPH_HEAP_ROOT DphRoot, PVOID pUserMem)
Definition: heappage.c:960
ULONG HeapFlags
Definition: heappage.c:65
Definition: dlist.c:348

Referenced by RtlValidateHeap().

◆ RtlpGetExtraStuffPointer()

PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer ( PHEAP_ENTRY  HeapEntry)

Definition at line 2632 of file heap.c.

2633{
2634 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
2635
2636 /* Check if it's a big block */
2637 if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
2638 {
2639 VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
2640
2641 /* Return a pointer to the extra stuff*/
2642 return &VirtualEntry->ExtraStuff;
2643 }
2644 else
2645 {
2646 /* This is a usual entry, which means extra stuff follows this block */
2647 return (PHEAP_ENTRY_EXTRA)(HeapEntry + HeapEntry->Size - 1);
2648 }
2649}
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:43
Definition: heap.h:292
Definition: heap.h:308
HEAP_ENTRY_EXTRA ExtraStuff
Definition: heap.h:310
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by RtlAllocateHeap(), RtlGetUserInfoHeap(), RtlpAllocateNonDedicated(), RtlReAllocateHeap(), and RtlSetUserValueHeap().

◆ RtlpHeapIsSpecial()

FORCEINLINE BOOLEAN RtlpHeapIsSpecial ( ULONG  Flags)

Definition at line 59 of file heap.h.

60{
62
68 {
69 /* This is a special heap */
70 return TRUE;
71 }
72
73 /* No need for a special treatment */
74 return FALSE;
75}
#define HEAP_VALIDATE_PARAMETERS_ENABLED
Definition: rtltypes.h:167
#define HEAP_CREATE_ENABLE_TRACING
Definition: nt_native.h:1702

Referenced by RtlAllocateHeap(), RtlCreateHeap(), RtlDestroyHeap(), RtlFreeHeap(), RtlGetUserInfoHeap(), RtlReAllocateHeap(), RtlSetUserFlagsHeap(), RtlSetUserValueHeap(), and RtlSizeHeap().

◆ RtlpPageHeapAllocate()

PVOID NTAPI RtlpPageHeapAllocate ( IN PVOID  HeapPtr,
IN ULONG  Flags,
IN SIZE_T  Size 
)

Definition at line 1758 of file heappage.c.

1761{
1762 PDPH_HEAP_ROOT DphRoot;
1763 PDPH_HEAP_BLOCK AvailableNode, BusyNode;
1764 BOOLEAN Biased = FALSE;
1765 ULONG AllocateSize, AccessSize;
1767 SIZE_T UserActualSize;
1768 PVOID Ptr;
1769
1770 /* Check requested size */
1771 if (Size > 0x7FF00000)
1772 {
1773 DPRINT1("extreme size request\n");
1774
1775 /* Generate an exception if needed */
1777
1778 return NULL;
1779 }
1780
1781 /* Unbias the pointer if necessary */
1782 if (IS_BIASED_POINTER(HeapPtr))
1783 {
1784 HeapPtr = (PVOID)POINTER_REMOVE_BIAS(HeapPtr);
1785 Biased = TRUE;
1786 }
1787
1788 /* Get a pointer to the heap root */
1789 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
1790 if (!DphRoot) return NULL;
1791
1792 /* Acquire the heap lock */
1793 RtlpDphPreProcessing(DphRoot, Flags);
1794
1795 /* Perform internal validation if specified by flags */
1797 {
1799 }
1800
1801 /* Add heap flags */
1802 Flags |= DphRoot->HeapFlags;
1803
1804 if (!Biased && !RtlpDphShouldAllocateInPageHeap(DphRoot, Size))
1805 {
1806 /* Perform allocation from a normal heap */
1807 ASSERT(FALSE);
1808 }
1809
1810 /* Perform heap integrity check if specified by flags */
1812 {
1813 RtlpDphVerifyIntegrity(DphRoot);
1814 }
1815
1816 /* Calculate sizes */
1817 AccessSize = ROUND_UP(Size + sizeof(DPH_BLOCK_INFORMATION), PAGE_SIZE);
1818 AllocateSize = AccessSize + PAGE_SIZE;
1819
1820 // FIXME: Move RtlpDphAllocateNode(DphRoot) to this place
1821 AvailableNode = RtlpDphFindAvailableMemory(DphRoot, AllocateSize, TRUE);
1822 if (!AvailableNode)
1823 {
1824 DPRINT1("Page heap: Unable to allocate virtual memory\n");
1825 DbgBreakPoint();
1826
1827 /* Release the lock */
1828 RtlpDphPostProcessing(DphRoot);
1829
1830 return NULL;
1831 }
1832 ASSERT(AvailableNode->nVirtualBlockSize >= AllocateSize);
1833
1834 /* Set protection */
1836 AvailableNode->pVirtualBlock,
1837 AccessSize);
1838 if (!NT_SUCCESS(Status))
1839 {
1840 ASSERT(FALSE);
1841 }
1842
1843 /* Save available node pointer */
1844 Ptr = AvailableNode->pVirtualBlock;
1845
1846 /* Check node's size */
1847 if (AvailableNode->nVirtualBlockSize > AllocateSize)
1848 {
1849 /* The block contains too much free space, reduce it */
1850 AvailableNode->pVirtualBlock += AllocateSize;
1851 AvailableNode->nVirtualBlockSize -= AllocateSize;
1852 DphRoot->nAvailableAllocationBytesCommitted -= AllocateSize;
1853
1854 /* Allocate a new node which will be our busy node */
1855 BusyNode = RtlpDphAllocateNode(DphRoot);
1856 ASSERT(BusyNode != NULL);
1857 BusyNode->pVirtualBlock = Ptr;
1858 BusyNode->nVirtualBlockSize = AllocateSize;
1859 }
1860 else
1861 {
1862 /* The block's size fits exactly */
1863 RtlpDphRemoveFromAvailableList(DphRoot, AvailableNode);
1864 BusyNode = AvailableNode;
1865 }
1866
1867 /* Calculate actual user size */
1868 if (DphRoot->HeapFlags & HEAP_NO_ALIGNMENT)
1869 UserActualSize = Size;
1870 else
1871 UserActualSize = ROUND_UP(Size, 8);
1872
1873 /* Set up the block */
1874 BusyNode->nVirtualAccessSize = AccessSize;
1875 BusyNode->nUserActualSize = UserActualSize;
1876 BusyNode->nUserRequestedSize = Size;
1877
1878 if (DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN)
1879 BusyNode->pUserAllocation = BusyNode->pVirtualBlock + PAGE_SIZE;
1880 else
1881 BusyNode->pUserAllocation = BusyNode->pVirtualBlock + BusyNode->nVirtualAccessSize - UserActualSize;
1882
1883 BusyNode->UserValue = NULL;
1885
1886 // FIXME: Don't forget about stack traces if such flag was set
1887 BusyNode->StackTrace = NULL;
1888
1889 /* Place it on busy list */
1890 RtlpDphPlaceOnBusyList(DphRoot, BusyNode);
1891
1892 /* Zero or patter-fill memory depending on flags */
1893 if (Flags & HEAP_ZERO_MEMORY)
1895 else
1897
1898 /* Write DPH info */
1899 if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
1900 {
1902 BusyNode->pUserAllocation,
1903 Size,
1904 AccessSize);
1905 }
1906
1907 /* Finally allocation is done, perform validation again if required */
1909 {
1911 }
1912
1913 /* Release the lock */
1914 RtlpDphPostProcessing(DphRoot);
1915
1916 DPRINT("Allocated user block pointer: %p\n", BusyNode->pUserAllocation);
1917
1918 /* Return pointer to user allocation */
1919 return BusyNode->pUserAllocation;
1920}
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
BOOLEAN NTAPI RtlpDphWritePageHeapBlockInformation(PDPH_HEAP_ROOT DphRoot, PVOID UserAllocation, SIZE_T Size, SIZE_T UserSize)
Definition: heappage.c:441
BOOLEAN NTAPI RtlpDphShouldAllocateInPageHeap(PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
Definition: heappage.c:1524
VOID NTAPI RtlpDphVerifyIntegrity(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:1320
#define IS_BIASED_POINTER(ptr)
Definition: heappage.c:179
VOID NTAPI RtlpDphRemoveFromAvailableList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:585
VOID NTAPI RtlpDphPlaceOnBusyList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK DphNode)
Definition: heappage.c:467
#define DPH_EXTRA_CHECK_UNDERRUN
Definition: heappage.c:152
#define POINTER_REMOVE_BIAS(ptr)
Definition: heappage.c:180
PDPH_HEAP_BLOCK NTAPI RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:1014
#define DPH_FILL_INFIX
Definition: heappage.c:161
VOID NTAPI RtlpDphInternalValidatePageHeap(PDPH_HEAP_ROOT DphRoot, PVOID Address, ULONG Value)
Definition: heappage.c:1314
NTSTATUS NTAPI RtlpDphSetProtectionBeforeUse(PDPH_HEAP_ROOT DphRoot, PUCHAR VirtualBlock, ULONG UserSize)
Definition: heappage.c:977
#define DPH_DEBUG_INTERNAL_VALIDATE
Definition: heappage.c:147
VOID NTAPI RtlpDphRaiseException(NTSTATUS Status)
Definition: heappage.c:207
PDPH_HEAP_BLOCK NTAPI RtlpDphFindAvailableMemory(PDPH_HEAP_ROOT DphRoot, SIZE_T Size, BOOLEAN Grow)
Definition: heappage.c:904
ULONG RtlpDphDebugOptions
Definition: heappage.c:185
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define HEAP_NO_ALIGNMENT
Definition: rtltypes.h:163
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define DPRINT
Definition: sndvol32.h:71
SIZE_T nUserActualSize
Definition: heappage.c:54
PUCHAR pVirtualBlock
Definition: heappage.c:50
ULONG UserFlags
Definition: heappage.c:56
PUCHAR pUserAllocation
Definition: heappage.c:49
SIZE_T nVirtualAccessSize
Definition: heappage.c:52
SIZE_T nUserRequestedSize
Definition: heappage.c:53
PRTL_TRACE_BLOCK StackTrace
Definition: heappage.c:57
SIZE_T nVirtualBlockSize
Definition: heappage.c:51
PVOID UserValue
Definition: heappage.c:55
ULONG ExtraFlags
Definition: heappage.c:98
SIZE_T nAvailableAllocationBytesCommitted
Definition: heappage.c:86
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by RtlDebugAllocateHeap(), and RtlpPageHeapReAllocate().

◆ RtlpPageHeapCreate()

HANDLE NTAPI RtlpPageHeapCreate ( ULONG  Flags,
PVOID  Addr,
SIZE_T  TotalSize,
SIZE_T  CommitSize,
PVOID  Lock,
PRTL_HEAP_PARAMETERS  Parameters 
)

Definition at line 1533 of file heappage.c.

1539{
1540 PVOID Base = NULL;
1541 PHEAP HeapPtr;
1542 PDPH_HEAP_ROOT DphRoot;
1543 PDPH_HEAP_BLOCK DphNode;
1544 ULONG MemSize;
1546 LARGE_INTEGER PerfCounter;
1547
1548 /* Check for a DPH bypass flag */
1549 if ((ULONG_PTR)Parameters == -1) return NULL;
1550
1551 /* Make sure no user-allocated stuff was provided */
1552 if (Addr || Lock) return NULL;
1553
1554 /* Allocate minimum amount of virtual memory */
1555 MemSize = DPH_RESERVE_SIZE;
1557 if (!NT_SUCCESS(Status))
1558 {
1559 ASSERT(FALSE);
1560 return NULL;
1561 }
1562
1563 /* Set protection */
1565 if (!NT_SUCCESS(Status))
1566 {
1567 //RtlpDphFreeVm(Base, 0, 0, 0);
1568 ASSERT(FALSE);
1569 return NULL;
1570 }
1571
1572 /* Start preparing the 1st page. Fill it with the default filler */
1574
1575 /* Set flags in the "HEAP" structure */
1576 HeapPtr = (PHEAP)Base;
1577 HeapPtr->Flags = Flags | HEAP_FLAG_PAGE_ALLOCS;
1579
1580 /* Set 1st page to read only now */
1582 if (!NT_SUCCESS(Status))
1583 {
1584 ASSERT(FALSE);
1585 return NULL;
1586 }
1587
1588 /* 2nd page is the real DPH root block */
1589 DphRoot = (PDPH_HEAP_ROOT)((PCHAR)Base + PAGE_SIZE);
1590
1591 /* Initialize the DPH root */
1592 DphRoot->Signature = DPH_SIGNATURE;
1593 DphRoot->HeapFlags = Flags;
1594 DphRoot->HeapCritSect = (PHEAP_LOCK)((PCHAR)DphRoot + DPH_POOL_SIZE);
1595 DphRoot->ExtraFlags = RtlpDphGlobalFlags;
1596
1597 ZwQueryPerformanceCounter(&PerfCounter, NULL);
1598 DphRoot->Seed = PerfCounter.LowPart;
1599
1602
1603 /* Create a normal heap for this paged heap */
1604 DphRoot->NormalHeap = RtlCreateHeap(Flags, NULL, TotalSize, CommitSize, NULL, (PRTL_HEAP_PARAMETERS)-1);
1605 if (!DphRoot->NormalHeap)
1606 {
1607 ASSERT(FALSE);
1608 return NULL;
1609 }
1610
1611 /* 3rd page: a pool for DPH allocations */
1612 RtlpDphAddNewPool(DphRoot, NULL, DphRoot + 1, DPH_POOL_SIZE - sizeof(DPH_HEAP_ROOT), FALSE);
1613
1614 /* Allocate internal heap blocks. For the root */
1615 DphNode = RtlpDphAllocateNode(DphRoot);
1616 ASSERT(DphNode != NULL);
1617 DphNode->pVirtualBlock = (PUCHAR)DphRoot;
1619 RtlpDphPlaceOnPoolList(DphRoot, DphNode);
1620
1621 /* For the memory we allocated as a whole */
1622 DphNode = RtlpDphAllocateNode(DphRoot);
1623 ASSERT(DphNode != NULL);
1624 DphNode->pVirtualBlock = Base;
1625 DphNode->nVirtualBlockSize = MemSize;
1626 RtlpDphPlaceOnVirtualList(DphRoot, DphNode);
1627
1628 /* For the remaining part */
1629 DphNode = RtlpDphAllocateNode(DphRoot);
1630 ASSERT(DphNode != NULL);
1632 DphNode->nVirtualBlockSize = MemSize - (2*PAGE_SIZE + DPH_POOL_SIZE);
1633 RtlpDphCoalesceNodeIntoAvailable(DphRoot, DphNode);
1634
1635 //DphRoot->CreateStackTrace = RtlpDphLogStackTrace(1);
1636
1637 /* Initialize AVL-based busy nodes table */
1642 NULL);
1643
1644 /* Initialize per-process startup info */
1646
1647 /* Acquire the heap list lock */
1649
1650 /* Insert this heap to the tail of the global list */
1652
1653 /* Note we increased the size of the list */
1655
1656 /* Release the heap list lock */
1658
1660 {
1661 DPRINT1("Page heap: process 0x%p created heap @ %p (%p, flags 0x%X)\n",
1663 DphRoot->NormalHeap, DphRoot->ExtraFlags);
1664 }
1665
1666 /* Perform internal validation if required */
1669
1670 return (PUCHAR)DphRoot - PAGE_SIZE;
1671}
VOID NTAPI RtlInitializeGenericTableAvl(IN OUT PRTL_AVL_TABLE Table, IN PRTL_AVL_COMPARE_ROUTINE CompareRoutine, IN PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine, IN PRTL_AVL_FREE_ROUTINE FreeRoutine, IN PVOID TableContext)
Definition: avltable.c:26
NTSTATUS NTAPI RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
Definition: libsupp.c:126
#define PAGE_READONLY
Definition: compat.h:138
#define InsertTailList(ListHead, Entry)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
VOID NTAPI RtlpDphPlaceOnPoolList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:511
PHEAP_LOCK RtlpDphPageHeapListLock
Definition: heappage.c:116
ULONG RtlpDphGlobalFlags
Definition: heappage.c:108
LIST_ENTRY RtlpDphPageHeapList
Definition: heappage.c:113
VOID NTAPI RtlpDphFreeNodeForTable(IN PRTL_AVL_TABLE Table, IN PVOID Buffer)
Definition: heappage.c:1223
NTSTATUS NTAPI RtlpDphProtectVm(PVOID Base, SIZE_T Size, ULONG Protection)
Definition: heappage.c:417
BOOLEAN RtlpDphPageHeapListInitialized
Definition: heappage.c:114
#define DPH_RESERVE_SIZE
Definition: heappage.c:134
VOID NTAPI RtlpDphAddNewPool(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK NodeBlock, PVOID Virtual, SIZE_T Size, BOOLEAN PlaceOnPool)
Definition: heappage.c:825
VOID NTAPI RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:680
#define DPH_FILL
Definition: heappage.c:155
ULONG RtlpDphPageHeapListLength
Definition: heappage.c:117
PVOID NTAPI RtlpDphAllocateNodeForTable(IN PRTL_AVL_TABLE Table, IN CLONG ByteSize)
Definition: heappage.c:1202
NTSTATUS NTAPI RtlpDphProcessStartupInitialization(VOID)
Definition: heappage.c:1492
#define DPH_DEBUG_VERBOSE
Definition: heappage.c:148
struct _DPH_HEAP_ROOT * PDPH_HEAP_ROOT
RTL_GENERIC_COMPARE_RESULTS NTAPI RtlpDphCompareNodeForTable(IN PRTL_AVL_TABLE Table, IN PVOID FirstStruct, IN PVOID SecondStruct)
Definition: heappage.c:1183
#define DPH_POOL_SIZE
Definition: heappage.c:135
#define DPH_SIGNATURE
Definition: heappage.c:176
NTSTATUS NTAPI RtlpDphAllocateVm(PVOID *Base, SIZE_T Size, ULONG Type, ULONG Protection)
Definition: heappage.c:342
VOID NTAPI RtlpDphPlaceOnVirtualList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:531
#define NtCurrentTeb
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
NTSYSAPI NTSTATUS NTAPI ZwQueryPerformanceCounter(_Out_ PLARGE_INTEGER Counter, _Out_opt_ PLARGE_INTEGER Frequency)
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2439
struct _HEAP_LOCK * PHEAP_LOCK
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define MEM_COMMIT
Definition: nt_native.h:1313
#define PAGE_NOACCESS
Definition: nt_native.h:1302
HANDLE UniqueProcess
Definition: compat.h:825
PHEAP_LOCK HeapCritSect
Definition: heappage.c:66
ULONG Seed
Definition: heappage.c:99
LIST_ENTRY NextHeap
Definition: heappage.c:97
LIST_ENTRY AvailableAllocationHead
Definition: heappage.c:84
ULONG Signature
Definition: heappage.c:64
PVOID NormalHeap
Definition: heappage.c:100
RTL_AVL_TABLE BusyNodesTable
Definition: heappage.c:74
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
char * PCHAR
Definition: typedefs.h:51
ULONG LowPart
Definition: typedefs.h:106
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151

Referenced by RtlCreateHeap().

◆ RtlpPageHeapDestroy()

PVOID NTAPI RtlpPageHeapDestroy ( HANDLE  HeapPtr)

Definition at line 1674 of file heappage.c.

1675{
1676 PDPH_HEAP_ROOT DphRoot;
1677 PVOID Ptr;
1678 PDPH_HEAP_BLOCK Node, Next;
1679 PHEAP NormalHeap;
1680 ULONG Value;
1681
1682 /* Check if it's not a process heap */
1683 if (HeapPtr == RtlGetProcessHeap())
1684 {
1685 DbgBreakPoint();
1686 return NULL;
1687 }
1688
1689 /* Get pointer to the heap root */
1690 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
1691 if (!DphRoot) return NULL;
1692
1693 RtlpDphPreProcessing(DphRoot, DphRoot->HeapFlags);
1694
1695 /* Get the pointer to the normal heap */
1696 NormalHeap = DphRoot->NormalHeap;
1697
1698 /* Free the delayed-free blocks */
1699 RtlpDphFreeDelayedBlocksFromHeap(DphRoot, NormalHeap);
1700
1701 /* Go through the busy blocks */
1703
1704 while (Ptr)
1705 {
1706 Node = CONTAINING_RECORD(Ptr, DPH_HEAP_BLOCK, pUserAllocation);
1707 if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
1708 {
1709 if (!RtlpDphIsPageHeapBlock(DphRoot, Node->pUserAllocation, &Value, TRUE))
1710 {
1711 RtlpDphReportCorruptedBlock(DphRoot, 3, Node->pUserAllocation, Value);
1712 }
1713 }
1714
1715 /* FIXME: Call AV notification */
1716 //AVrfInternalHeapFreeNotification();
1717
1718 /* Go to the next node */
1720 }
1721
1722 /* Acquire the global heap list lock */
1724
1725 /* Remove the entry and decrement the global counter */
1726 RemoveEntryList(&DphRoot->NextHeap);
1728
1729 /* Release the global heap list lock */
1731
1732 /* Leave and delete this heap's critical section */
1735
1736 /* Now go through all virtual list nodes and release the VM */
1737 Node = DphRoot->pVirtualStorageListHead;
1738 while (Node)
1739 {
1740 Next = Node->pNextAlloc;
1741 /* Release the memory without checking result */
1742 RtlpDphFreeVm(Node->pVirtualBlock, 0, MEM_RELEASE);
1743 Node = Next;
1744 }
1745
1746 /* Destroy the normal heap */
1747 RtlDestroyHeap(NormalHeap);
1748
1749 /* Report success */
1751 DPRINT1("Page heap: process 0x%p destroyed heap @ %p (%p)\n",
1752 NtCurrentTeb()->ClientId.UniqueProcess, HeapPtr, NormalHeap);
1753
1754 return NULL;
1755}
NTSTATUS NTAPI RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:101
union node Node
Definition: types.h:1255
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
NTSTATUS NTAPI RtlpDphFreeVm(PVOID Base, SIZE_T Size, ULONG Type)
Definition: heappage.c:381
BOOLEAN NTAPI RtlpDphIsPageHeapBlock(PDPH_HEAP_ROOT DphRoot, PVOID Block, PULONG ValidationInformation, BOOLEAN CheckFillers)
Definition: heappage.c:1417
VOID NTAPI RtlpDphFreeDelayedBlocksFromHeap(PDPH_HEAP_ROOT DphRoot, PHEAP NormalHeap)
Definition: heappage.c:1254
VOID NTAPI RtlpDphReportCorruptedBlock(_In_ PDPH_HEAP_ROOT DphRoot, _In_ ULONG Reserved, _In_ PVOID Block, _In_ ULONG ValidationInfo)
Definition: heappage.c:1326
NTSYSAPI PVOID NTAPI RtlDestroyHeap(IN PVOID HeapHandle)
PDPH_HEAP_BLOCK pVirtualStorageListHead
Definition: heappage.c:69
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ BOOLEAN Restart)

Referenced by RtlDestroyHeap().

◆ RtlpPageHeapFree()

BOOLEAN NTAPI RtlpPageHeapFree ( HANDLE  HeapPtr,
ULONG  Flags,
PVOID  Ptr 
)

Definition at line 1923 of file heappage.c.

1926{
1927 PDPH_HEAP_ROOT DphRoot;
1929 ULONG ValidationInfo;
1931
1932 /* Check for a NULL pointer freeing */
1933 if (!Ptr)
1934 {
1936 {
1937 DPRINT1("Page heap: freeing a null pointer\n");
1938 DbgBreakPoint();
1939 }
1940 return TRUE;
1941 }
1942
1943 /* Get a pointer to the heap root */
1944 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
1945 if (!DphRoot) return FALSE;
1946
1947 /* Acquire the heap lock */
1948 RtlpDphPreProcessing(DphRoot, Flags);
1949
1950 /* Perform internal validation if specified by flags */
1953
1954 /* Add heap flags */
1955 Flags |= DphRoot->HeapFlags;
1956
1957 /* Find busy memory */
1958 Node = RtlpDphFindBusyMemory(DphRoot, Ptr);
1959
1960 if (!Node)
1961 {
1962 /* This block was not found in page heap, try a normal heap instead */
1963 //RtlpDphNormalHeapFree();
1964 ASSERT(FALSE);
1965 }
1966
1967 if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
1968 {
1969 /* Check and report corrupted block */
1970 if (!RtlpDphIsPageHeapBlock(DphRoot, Ptr, &ValidationInfo, TRUE))
1971 {
1972 RtlpDphReportCorruptedBlock(DphRoot, 1, Ptr, ValidationInfo);
1973 }
1974
1975 // FIXME: Should go inside RtlpDphSetProtectionAfterUse
1976 if (Node->nVirtualAccessSize != 0)
1977 {
1978 /* Set stamps */
1979 Info = (PDPH_BLOCK_INFORMATION)Node->pUserAllocation - 1;
1980 Info->StartStamp = DPH_FILL_START_STAMP_2;
1981 Info->EndStamp = DPH_FILL_END_STAMP_2;
1982
1983 RtlpDphProtectVm(Node->pVirtualBlock, Node->nVirtualAccessSize, PAGE_NOACCESS);
1984 }
1985 }
1986 else
1987 {
1988 // FIXME: Should go inside RtlpDphSetProtectionAfterUse
1989 if (Node->nVirtualAccessSize != 0)
1990 RtlpDphProtectVm(Node->pVirtualBlock + PAGE_SIZE, Node->nVirtualAccessSize, PAGE_NOACCESS);
1991 }
1992
1993 /* Set new protection */
1994 //RtlpDphSetProtectionAfterUse(DphRoot, Node);
1995
1996 /* Remove it from the list of busy nodes */
1998
1999 /* And put it into the list of free nodes */
2000 RtlpDphPlaceOnFreeList(DphRoot, Node);
2001
2002 //if (DphRoot->ExtraFlags & DPH_EXTRA_LOG_STACK_TRACES)
2003 // Node->StackTrace = RtlpDphLogStackTrace(3);
2004 //else
2005 Node->StackTrace = NULL;
2006
2007 /* Leave the heap lock */
2008 RtlpDphPostProcessing(DphRoot);
2009
2010 /* Return success */
2011 return TRUE;
2012}
#define DPH_FILL_START_STAMP_2
Definition: heappage.c:157
struct _DPH_BLOCK_INFORMATION * PDPH_BLOCK_INFORMATION
VOID NTAPI RtlpDphPlaceOnFreeList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:491
VOID NTAPI RtlpDphRemoveFromBusyList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:638
ULONG RtlpDphBreakOptions
Definition: heappage.c:184
#define DPH_BREAK_ON_NULL_FREE
Definition: heappage.c:144
#define DPH_FILL_END_STAMP_2
Definition: heappage.c:159
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690

Referenced by RtlDebugFreeHeap().

◆ RtlpPageHeapGetUserInfo()

BOOLEAN NTAPI RtlpPageHeapGetUserInfo ( PVOID  HeapHandle,
ULONG  Flags,
PVOID  BaseAddress,
PVOID UserValue,
PULONG  UserFlags 
)

Definition at line 2185 of file heappage.c.

2190{
2191 PDPH_HEAP_ROOT DphRoot;
2193
2194 /* Get a pointer to the heap root */
2195 DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2196 if (!DphRoot) return FALSE;
2197
2198 /* Add heap flags */
2199 Flags |= DphRoot->HeapFlags;
2200
2201 /* Acquire the heap lock */
2202 RtlpDphPreProcessing(DphRoot, Flags);
2203
2204 /* Find busy memory */
2206
2207 if (!Node)
2208 {
2209 /* This block was not found in page heap, try a normal heap instead */
2210 //RtlpDphNormalHeapGetUserInfo();
2211 ASSERT(FALSE);
2212 return FALSE;
2213 }
2214
2215 /* Get user values and flags and store them in user provided pointers */
2216 if (UserValue) *UserValue = Node->UserValue;
2217 if (UserFlags) *UserFlags = Node->UserFlags;
2218
2219 /* Leave the heap lock */
2220 RtlpDphPostProcessing(DphRoot);
2221
2222 /* Return success */
2223 return TRUE;
2224}

Referenced by RtlDebugGetUserInfoHeap().

◆ RtlpPageHeapLock()

BOOLEAN NTAPI RtlpPageHeapLock ( HANDLE  HeapPtr)

Definition at line 2415 of file heappage.c.

2416{
2417 PDPH_HEAP_ROOT DphRoot;
2418
2419 /* Get pointer to the heap root */
2420 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2421 if (!DphRoot) return FALSE;
2422
2423 RtlpDphEnterCriticalSection(DphRoot, DphRoot->HeapFlags);
2424 return TRUE;
2425}
VOID NTAPI RtlpDphEnterCriticalSection(PDPH_HEAP_ROOT DphRoot, ULONG Flags)
Definition: heappage.c:261

Referenced by RtlLockHeap().

◆ RtlpPageHeapReAllocate()

PVOID NTAPI RtlpPageHeapReAllocate ( HANDLE  HeapPtr,
ULONG  Flags,
PVOID  Ptr,
SIZE_T  Size 
)

Definition at line 2015 of file heappage.c.

2019{
2020 PDPH_HEAP_ROOT DphRoot;
2021 PDPH_HEAP_BLOCK Node = NULL, AllocatedNode;
2022 BOOLEAN Biased = FALSE, UseNormalHeap = FALSE, OldBlockPageHeap = TRUE;
2023 ULONG ValidationInfo;
2025 PVOID NewAlloc = NULL;
2026
2027 /* Check requested size */
2028 if (Size > 0x7FF00000)
2029 {
2030 DPRINT1("extreme size request\n");
2031
2032 /* Generate an exception if needed */
2034
2035 return NULL;
2036 }
2037
2038 /* Unbias the pointer if necessary */
2039 if (IS_BIASED_POINTER(HeapPtr))
2040 {
2041 HeapPtr = (PVOID)POINTER_REMOVE_BIAS(HeapPtr);
2042 Biased = TRUE;
2043 }
2044
2045 /* Get a pointer to the heap root */
2046 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2047 if (!DphRoot) return NULL;
2048
2049 /* Acquire the heap lock */
2050 RtlpDphPreProcessing(DphRoot, Flags);
2051
2052 /* Perform internal validation if specified by flags */
2054 {
2056 }
2057
2058 /* Add heap flags */
2059 Flags |= DphRoot->HeapFlags;
2060
2061 /* Exit with NULL right away if inplace is specified */
2063 {
2064 /* Release the lock */
2065 RtlpDphPostProcessing(DphRoot);
2066
2067 /* Generate an exception if needed */
2069
2070 return NULL;
2071 }
2072
2073 /* Try to get node of the allocated block */
2074 AllocatedNode = RtlpDphFindBusyMemory(DphRoot, Ptr);
2075
2076 if (!AllocatedNode)
2077 {
2078 /* This block was not found in page heap, try a normal heap instead */
2079 //RtlpDphNormalHeapFree();
2080 ASSERT(FALSE);
2081 OldBlockPageHeap = FALSE;
2082 }
2083
2084 /* Check the block */
2085 if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
2086 {
2087 if (!RtlpDphIsPageHeapBlock(DphRoot, AllocatedNode->pUserAllocation, &ValidationInfo, TRUE))
2088 {
2089 RtlpDphReportCorruptedBlock(DphRoot, 3, AllocatedNode->pUserAllocation, ValidationInfo);
2090 }
2091 }
2092
2093 /* Remove old one from the busy list */
2094 RtlpDphRemoveFromBusyList(DphRoot, AllocatedNode);
2095
2096 if (!Biased && !RtlpDphShouldAllocateInPageHeap(DphRoot, Size))
2097 {
2098 // FIXME: Use normal heap
2099 ASSERT(FALSE);
2100 UseNormalHeap = TRUE;
2101 }
2102 else
2103 {
2104 /* Now do a trick: bias the pointer and call our allocate routine */
2105 NewAlloc = RtlpPageHeapAllocate((PVOID)POINTER_ADD_BIAS(HeapPtr), Flags, Size);
2106 }
2107
2108 if (!NewAlloc)
2109 {
2110 /* New allocation failed, put the block back (if it was found in page heap) */
2111 RtlpDphPlaceOnBusyList(DphRoot, AllocatedNode);
2112
2113 /* Release the lock */
2114 RtlpDphPostProcessing(DphRoot);
2115
2116 /* Perform validation again if required */
2118 {
2120 }
2121
2122 /* Generate an exception if needed */
2124
2125 return NULL;
2126 }
2127
2128 /* Copy contents of the old block */
2129 if (AllocatedNode->nUserRequestedSize > Size)
2130 DataSize = Size;
2131 else
2132 DataSize = AllocatedNode->nUserRequestedSize;
2133
2134 if (DataSize != 0) RtlCopyMemory(NewAlloc, Ptr, DataSize);
2135
2136 /* Copy user flags and values */
2137 if (!UseNormalHeap)
2138 {
2139 /* Get the node of the new block */
2140 Node = RtlpDphFindBusyMemory(DphRoot, NewAlloc);
2141 ASSERT(Node != NULL);
2142
2143 /* Set its values/flags */
2144 Node->UserValue = AllocatedNode->UserValue;
2146 Node->UserFlags = Flags & HEAP_SETTABLE_USER_FLAGS;
2147 else
2148 Node->UserFlags = AllocatedNode->UserFlags;
2149 }
2150
2151 if (!OldBlockPageHeap)
2152 {
2153 /* Weird scenario, investigate */
2154 ASSERT(FALSE);
2155 }
2156
2157 /* Mark the old block as no access */
2158 if (AllocatedNode->nVirtualAccessSize != 0)
2159 {
2160 RtlpDphProtectVm(AllocatedNode->pVirtualBlock, AllocatedNode->nVirtualAccessSize, PAGE_NOACCESS);
2161 }
2162
2163 /* And place it on the free list */
2164 RtlpDphPlaceOnFreeList(DphRoot, AllocatedNode);
2165
2166 // FIXME: Capture stack traces if needed
2167 AllocatedNode->StackTrace = NULL;
2168
2169 /* Finally allocation is done, perform validation again if required */
2171 {
2173 }
2174
2175 /* Release the lock */
2176 RtlpDphPostProcessing(DphRoot);
2177
2178 DPRINT("Allocated new user block pointer: %p\n", NewAlloc);
2179
2180 /* Return pointer to user allocation */
2181 return NewAlloc;
2182}
#define POINTER_ADD_BIAS(ptr)
Definition: heappage.c:181
PVOID NTAPI RtlpPageHeapAllocate(IN PVOID HeapPtr, IN ULONG Flags, IN SIZE_T Size)
Definition: heappage.c:1758
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
#define HEAP_REALLOC_IN_PLACE_ONLY
Definition: nt_native.h:1696
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263

Referenced by RtlDebugReAllocateHeap().

◆ RtlpPageHeapSetUserFlags()

BOOLEAN NTAPI RtlpPageHeapSetUserFlags ( PVOID  HeapHandle,
ULONG  Flags,
PVOID  BaseAddress,
ULONG  UserFlagsReset,
ULONG  UserFlagsSet 
)

Definition at line 2268 of file heappage.c.

2273{
2274 PDPH_HEAP_ROOT DphRoot;
2276
2277 /* Get a pointer to the heap root */
2278 DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2279 if (!DphRoot) return FALSE;
2280
2281 /* Add heap flags */
2282 Flags |= DphRoot->HeapFlags;
2283
2284 /* Acquire the heap lock */
2285 RtlpDphPreProcessing(DphRoot, Flags);
2286
2287 /* Find busy memory */
2289
2290 if (!Node)
2291 {
2292 /* This block was not found in page heap, try a normal heap instead */
2293 //RtlpDphNormalHeapSetUserFlags();
2294 ASSERT(FALSE);
2295 return FALSE;
2296 }
2297
2298 /* Get user values and flags and store them in user provided pointers */
2299 Node->UserFlags &= ~(UserFlagsReset);
2300 Node->UserFlags |= UserFlagsSet;
2301
2302 /* Leave the heap lock */
2303 RtlpDphPostProcessing(DphRoot);
2304
2305 /* Return success */
2306 return TRUE;
2307}

Referenced by RtlDebugSetUserFlagsHeap().

◆ RtlpPageHeapSetUserValue()

BOOLEAN NTAPI RtlpPageHeapSetUserValue ( PVOID  HeapHandle,
ULONG  Flags,
PVOID  BaseAddress,
PVOID  UserValue 
)

Definition at line 2227 of file heappage.c.

2231{
2232 PDPH_HEAP_ROOT DphRoot;
2234
2235 /* Get a pointer to the heap root */
2236 DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2237 if (!DphRoot) return FALSE;
2238
2239 /* Add heap flags */
2240 Flags |= DphRoot->HeapFlags;
2241
2242 /* Acquire the heap lock */
2243 RtlpDphPreProcessing(DphRoot, Flags);
2244
2245 /* Find busy memory */
2247
2248 if (!Node)
2249 {
2250 /* This block was not found in page heap, try a normal heap instead */
2251 //RtlpDphNormalHeapSetUserValue();
2252 ASSERT(FALSE);
2253 return FALSE;
2254 }
2255
2256 /* Get user values and flags and store them in user provided pointers */
2257 Node->UserValue = UserValue;
2258
2259 /* Leave the heap lock */
2260 RtlpDphPostProcessing(DphRoot);
2261
2262 /* Return success */
2263 return TRUE;
2264}

Referenced by RtlDebugSetUserValueHeap().

◆ RtlpPageHeapSize()

SIZE_T NTAPI RtlpPageHeapSize ( HANDLE  HeapPtr,
ULONG  Flags,
PVOID  Ptr 
)

Definition at line 2310 of file heappage.c.

2313{
2314 PDPH_HEAP_ROOT DphRoot;
2316 SIZE_T Size;
2317
2318 /* Get a pointer to the heap root */
2319 DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2320 if (!DphRoot) return -1;
2321
2322 /* Add heap flags */
2323 Flags |= DphRoot->HeapFlags;
2324
2325 /* Acquire the heap lock */
2326 RtlpDphPreProcessing(DphRoot, Flags);
2327
2328 /* Find busy memory */
2330
2331 if (!Node)
2332 {
2333 /* This block was not found in page heap, try a normal heap instead */
2334 //RtlpDphNormalHeapSize();
2335 ASSERT(FALSE);
2336 return -1;
2337 }
2338
2339 /* Get heap block size */
2340 Size = Node->nUserRequestedSize;
2341
2342 /* Leave the heap lock */
2343 RtlpDphPostProcessing(DphRoot);
2344
2345 /* Return user requested size */
2346 return Size;
2347}

Referenced by RtlDebugSizeHeap().

◆ RtlpPageHeapUnlock()

BOOLEAN NTAPI RtlpPageHeapUnlock ( HANDLE  HeapPtr)

Definition at line 2429 of file heappage.c.

2430{
2431 PDPH_HEAP_ROOT DphRoot;
2432
2433 /* Get pointer to the heap root */
2434 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2435 if (!DphRoot) return FALSE;
2436
2438 return TRUE;
2439}
VOID NTAPI RtlpDphLeaveCriticalSection(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:289

Referenced by RtlUnlockHeap().

◆ RtlpRemoveHeapFromProcessList()

VOID NTAPI RtlpRemoveHeapFromProcessList ( PHEAP  Heap)

Definition at line 56 of file heapuser.c.

57{
58 PPEB Peb;
59 PHEAP *Current, *Next;
61
62 /* Get PEB */
64
65 /* Acquire the lock */
67
68 /* Check if we don't need anything to do */
69 if ((Heap->ProcessHeapsListIndex == 0) ||
71 (Peb->NumberOfHeaps == 0))
72 {
73 /* Release the lock */
75
76 return;
77 }
78
79 /* The process actually has more than one heap.
80 Use classic, lernt from university times algorithm for removing an entry
81 from a static array */
82
83 Current = (PHEAP *)&Peb->ProcessHeaps[Heap->ProcessHeapsListIndex - 1];
84 Next = Current + 1;
85
86 /* How many items we need to shift to the left */
88
89 /* Move them all in a loop */
90 while (--Count)
91 {
92 /* Copy it and advance next pointer */
93 *Current = *Next;
94
95 /* Update its index */
96 (*Current)->ProcessHeapsListIndex -= 1;
97
98 /* Advance pointers */
99 Current++;
100 Next++;
101 }
102
103 /* Decrease total number of heaps */
105
106 /* Zero last unused item */
108 Heap->ProcessHeapsListIndex = 0;
109
110 /* Release the lock */
112}
int Count
Definition: noreturn.cpp:7

◆ RtlpValidateHeap()

BOOLEAN NTAPI RtlpValidateHeap ( PHEAP  Heap,
BOOLEAN  ForceValidation 
)

Definition at line 3513 of file heap.c.

3515{
3516 UCHAR SegmentOffset;
3517 SIZE_T TotalFreeSize;
3518 PLIST_ENTRY ListHead, NextEntry;
3519 ULONG FreeBlocksCount, FreeListEntriesCount;
3521
3522 /* Check headers */
3523 if (!RtlpValidateHeapHeaders(Heap, FALSE))
3524 return FALSE;
3525
3526 /* Skip validation if it's not needed */
3527 if (!ForceValidation && !(Heap->Flags & HEAP_VALIDATE_ALL_ENABLED))
3528 return TRUE;
3529
3530 /* Check free list */
3531 FreeListEntriesCount = 0;
3532 ListHead = &Heap->FreeLists;
3533 NextEntry = ListHead->Flink;
3534
3535 while (NextEntry != ListHead)
3536 {
3537 PHEAP_FREE_ENTRY FreeEntry = CONTAINING_RECORD(NextEntry, HEAP_FREE_ENTRY, FreeList);
3538
3539 NextEntry = NextEntry->Flink;
3540
3541 if (NextEntry != ListHead)
3542 {
3543 PHEAP_FREE_ENTRY NextFreeEntry = CONTAINING_RECORD(NextEntry, HEAP_FREE_ENTRY, FreeList);
3544 /* Free entries must be sorted */
3545 if (FreeEntry->Size > NextFreeEntry->Size)
3546 {
3547 DPRINT1("Dedicated free entry %p of size %ld is not put in order.\n", FreeEntry, FreeEntry->Size);
3548 }
3549 }
3550
3551 /* Check that the hint is there */
3552 if (FreeEntry->Size > Heap->DeCommitFreeBlockThreshold)
3553 {
3554 if (Heap->FreeHints[0] == NULL)
3555 {
3556 DPRINT1("No hint pointing to the non-dedicated list although there is a free entry %p of size %ld.\n",
3557 FreeEntry, FreeEntry->Size);
3558 }
3559 if (!RtlTestBit(&Heap->FreeHintBitmap, 0))
3560 {
3561 DPRINT1("Hint bit 0 is not set although there is a free entry %p of size %ld.\n",
3562 FreeEntry, FreeEntry->Size);
3563 }
3564 }
3565 else
3566 {
3567 if (Heap->FreeHints[FreeEntry->Size - 1] == NULL)
3568 {
3569 DPRINT1("No hint pointing to the dedicated list although there is a free entry %p of size %ld.\n",
3570 FreeEntry, FreeEntry->Size);
3571 }
3572 if (!RtlTestBit(&Heap->FreeHintBitmap, FreeEntry->Size - 1))
3573 {
3574 DPRINT1("Hint bit 0 is not set although there is a free entry %p of size %ld.\n",
3575 FreeEntry, FreeEntry->Size);
3576 }
3577 }
3578
3579 /* If there is an in-use entry in a free list - that's quite a big problem */
3580 if (FreeEntry->Flags & HEAP_ENTRY_BUSY)
3581 {
3582 DPRINT1("HEAP: Free element %p is marked in-use\n", FreeEntry);
3583 return FALSE;
3584 }
3585
3586 /* Add up to the total amount of free entries */
3587 FreeListEntriesCount++;
3588 }
3589
3590 /* Check free list hints */
3592 {
3593 if (Heap->FreeHints[HintIndex] != NULL)
3594 {
3596
3597 if (!RtlTestBit(&Heap->FreeHintBitmap, HintIndex))
3598 {
3599 DPRINT1("Hint bitmap bit at %u is not set, but there is a hint entry.\n", HintIndex);
3600 }
3601
3602 if (HintIndex == 0)
3603 {
3604 if (FreeEntry->Size <= Heap->DeCommitFreeBlockThreshold)
3605 {
3606 DPRINT1("There is an entry %p of size %lu, smaller than the decommit threshold %lu in the non-dedicated free list hint.\n",
3607 FreeEntry, FreeEntry->Size, Heap->DeCommitFreeBlockThreshold);
3608 }
3609 }
3610 else
3611 {
3612 if (HintIndex != FreeEntry->Size - 1)
3613 {
3614 DPRINT1("There is an entry %p of size %lu at the position %u in the free entry hint array.\n",
3615 FreeEntry, FreeEntry->Size, HintIndex);
3616 }
3617
3618 if (FreeEntry->FreeList.Blink != &Heap->FreeLists)
3619 {
3620 /* The entry right before the hint must be smaller. */
3621 PHEAP_FREE_ENTRY PreviousFreeEntry = CONTAINING_RECORD(FreeEntry->FreeList.Blink,
3623 FreeList);
3624 if (PreviousFreeEntry->Size >= FreeEntry->Size)
3625 {
3626 DPRINT1("Free entry hint %p of size %lu is larger than the entry before it %p, which is of size %lu.\n",
3627 FreeEntry, FreeEntry->Size, PreviousFreeEntry, PreviousFreeEntry->Size);
3628 }
3629 }
3630 }
3631 }
3632 else if (RtlTestBit(&Heap->FreeHintBitmap, HintIndex))
3633 {
3634 DPRINT1("Hint bitmap bit at %u is set, but there is no hint entry.\n", HintIndex);
3635 }
3636 }
3637
3638 /* Check big allocations */
3639 ListHead = &Heap->VirtualAllocdBlocks;
3640 NextEntry = ListHead->Flink;
3641
3642 while (ListHead != NextEntry)
3643 {
3645
3646 /* We can only check the fill pattern */
3647 if (VirtualAllocBlock->BusyBlock.Flags & HEAP_ENTRY_FILL_PATTERN)
3648 {
3649 if (!RtlpCheckInUsePattern(&VirtualAllocBlock->BusyBlock))
3650 return FALSE;
3651 }
3652
3653 NextEntry = NextEntry->Flink;
3654 }
3655
3656 /* Check all segments */
3657 FreeBlocksCount = 0;
3658 TotalFreeSize = 0;
3659
3660 for (SegmentOffset = 0; SegmentOffset < HEAP_SEGMENTS; SegmentOffset++)
3661 {
3662 PHEAP_SEGMENT Segment = Heap->Segments[SegmentOffset];
3663
3664 /* Go to the next one if there is no segment */
3665 if (!Segment) continue;
3666
3667 if (!RtlpValidateHeapSegment(Heap,
3668 Segment,
3669 SegmentOffset,
3670 &FreeBlocksCount,
3671 &TotalFreeSize,
3672 NULL,
3673 NULL))
3674 {
3675 return FALSE;
3676 }
3677 }
3678
3679 if (FreeListEntriesCount != FreeBlocksCount)
3680 {
3681 DPRINT1("HEAP: Free blocks count in arena (%lu) does not match free blocks number in the free lists (%lu)\n", FreeBlocksCount, FreeListEntriesCount);
3682 return FALSE;
3683 }
3684
3685 if (Heap->TotalFreeSize != TotalFreeSize)
3686 {
3687 DPRINT1("HEAP: Total size of free blocks in arena (%Iu) does not equal to the one in heap header (%Iu)\n", TotalFreeSize, Heap->TotalFreeSize);
3688 return FALSE;
3689 }
3690
3691 return TRUE;
3692}
BOOLEAN NTAPI RtlpCheckInUsePattern(PHEAP_ENTRY HeapEntry)
Definition: heap.c:3230
BOOLEAN NTAPI RtlpValidateHeapSegment(PHEAP Heap, PHEAP_SEGMENT Segment, UCHAR SegmentOffset, PULONG FreeEntriesCount, PSIZE_T TotalFreeSize, PSIZE_T TagEntries, PSIZE_T PseudoTagEntries)
Definition: heap.c:3326
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:42
LIST_ENTRY FreeList
Definition: heap.h:132
HEAP_ENTRY BusyBlock
Definition: heap.h:313
PLIST_ENTRY FreeHints[ANYSIZE_ARRAY]
Definition: heap.h:268
RTL_BITMAP FreeHintBitmap
Definition: heap.h:267
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:251
LIST_ENTRY FreeLists
Definition: heap.h:259
SIZE_T DeCommitFreeBlockThreshold
Definition: heap.h:237
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:253
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
_In_ ULONG _In_ ULONG HintIndex
Definition: rtlfuncs.h:610
_Must_inspect_result_ NTSYSAPI BOOLEAN NTAPI RtlTestBit(_In_ PRTL_BITMAP BitMapHeader, _In_range_(<, BitMapHeader->SizeOfBitMap) ULONG BitNumber)
Definition: bitmap.c:434

Referenced by RtlDebugAllocateHeap(), RtlDebugDestroyHeap(), RtlDebugFreeHeap(), RtlDebugGetUserInfoHeap(), RtlDebugReAllocateHeap(), RtlDebugSetUserFlagsHeap(), RtlDebugSetUserValueHeap(), RtlDebugSizeHeap(), and RtlValidateHeap().

◆ RtlpValidateHeapEntry()

BOOLEAN NTAPI RtlpValidateHeapEntry ( PHEAP  Heap,
PHEAP_ENTRY  HeapEntry 
)

Definition at line 3269 of file heap.c.

3272{
3273 BOOLEAN BigAllocation, EntryFound = FALSE;
3275 ULONG SegmentOffset;
3276
3277 /* Perform various consistency checks of this entry */
3278 if (!HeapEntry) goto invalid_entry;
3279 if ((ULONG_PTR)HeapEntry & (HEAP_ENTRY_SIZE - 1)) goto invalid_entry;
3280 if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY)) goto invalid_entry;
3281
3282 BigAllocation = HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC;
3283 Segment = Heap->Segments[HeapEntry->SegmentOffset];
3284
3285 if (BigAllocation &&
3286 (((ULONG_PTR)HeapEntry & (PAGE_SIZE - 1)) != FIELD_OFFSET(HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock)))
3287 goto invalid_entry;
3288
3289 if (!BigAllocation && (HeapEntry->SegmentOffset >= HEAP_SEGMENTS ||
3290 !Segment ||
3291 HeapEntry < Segment->FirstEntry ||
3292 HeapEntry >= Segment->LastValidEntry))
3293 goto invalid_entry;
3294
3295 if ((HeapEntry->Flags & HEAP_ENTRY_FILL_PATTERN) &&
3296 !RtlpCheckInUsePattern(HeapEntry))
3297 goto invalid_entry;
3298
3299 /* Checks are done, if this is a virtual entry, that's all */
3300 if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) return TRUE;
3301
3302 /* Go through segments and check if this entry fits into any of them */
3303 for (SegmentOffset = 0; SegmentOffset < HEAP_SEGMENTS; SegmentOffset++)
3304 {
3305 Segment = Heap->Segments[SegmentOffset];
3306 if (!Segment) continue;
3307
3308 if ((HeapEntry >= Segment->FirstEntry) &&
3309 (HeapEntry < Segment->LastValidEntry))
3310 {
3311 /* Got it */
3312 EntryFound = TRUE;
3313 break;
3314 }
3315 }
3316
3317 /* Return our result of finding entry in the segments */
3318 return EntryFound;
3319
3320invalid_entry:
3321 DPRINT1("HEAP: Invalid heap entry %p in heap %p\n", HeapEntry, Heap);
3322 return FALSE;
3323}
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

Referenced by RtlDebugFreeHeap(), RtlDebugGetUserInfoHeap(), RtlDebugReAllocateHeap(), RtlDebugSetUserFlagsHeap(), RtlDebugSetUserValueHeap(), RtlDebugSizeHeap(), and RtlValidateHeap().

◆ RtlpValidateHeapHeaders()

BOOLEAN NTAPI RtlpValidateHeapHeaders ( PHEAP  Heap,
BOOLEAN  Recalculate 
)

Definition at line 3260 of file heap.c.

3263{
3264 // We skip header validation for now
3265 return TRUE;
3266}

Referenced by RtlDebugAllocateHeap(), RtlDebugCreateHeap(), RtlDebugFreeHeap(), RtlDebugReAllocateHeap(), and RtlpValidateHeap().

Variable Documentation

◆ RtlpPageHeapEnabled

BOOLEAN RtlpPageHeapEnabled
extern

Definition at line 107 of file heappage.c.

◆ RtlpProcessHeapsListLock

RTL_CRITICAL_SECTION RtlpProcessHeapsListLock
extern