1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * FILE: lib/rtl/heappage.c
4 * PURPOSE: RTL Page Heap implementation
5 * PROGRAMMERS: Copyright 2011 Aleksey Bragin
9 http://msdn.microsoft.com/en-us/library/ms220938(VS.80).aspx
12 /* INCLUDES *****************************************************************/
20 /* TYPES **********************************************************************/
22 typedef struct _DPH_BLOCK_INFORMATION
31 SINGLE_LIST_ENTRY FreePushList
;
36 } DPH_BLOCK_INFORMATION
, *PDPH_BLOCK_INFORMATION
;
38 typedef struct _DPH_HEAP_BLOCK
42 struct _DPH_HEAP_BLOCK
*pNextAlloc
;
43 LIST_ENTRY AvailableEntry
;
44 RTL_BALANCED_LINKS TableLinks
;
46 PUCHAR pUserAllocation
;
48 ULONG nVirtualBlockSize
;
49 ULONG nVirtualAccessSize
;
50 ULONG nUserRequestedSize
;
51 ULONG nUserActualSize
;
54 PRTL_TRACE_BLOCK StackTrace
;
55 LIST_ENTRY AdjacencyEntry
;
56 PUCHAR pVirtualRegion
;
57 } DPH_HEAP_BLOCK
, *PDPH_HEAP_BLOCK
;
59 typedef struct _DPH_HEAP_ROOT
63 PRTL_CRITICAL_SECTION HeapCritSect
;
64 ULONG nRemoteLockAcquired
;
66 PDPH_HEAP_BLOCK pVirtualStorageListHead
;
67 PDPH_HEAP_BLOCK pVirtualStorageListTail
;
68 ULONG nVirtualStorageRanges
;
69 ULONG nVirtualStorageBytes
;
71 RTL_AVL_TABLE BusyNodesTable
;
72 PDPH_HEAP_BLOCK NodeToAllocate
;
73 ULONG nBusyAllocations
;
74 ULONG nBusyAllocationBytesCommitted
;
76 PDPH_HEAP_BLOCK pFreeAllocationListHead
;
77 PDPH_HEAP_BLOCK pFreeAllocationListTail
;
78 ULONG nFreeAllocations
;
79 ULONG nFreeAllocationBytesCommitted
;
81 LIST_ENTRY AvailableAllocationHead
;
82 ULONG nAvailableAllocations
;
83 ULONG nAvailableAllocationBytesCommitted
;
85 PDPH_HEAP_BLOCK pUnusedNodeListHead
;
86 PDPH_HEAP_BLOCK pUnusedNodeListTail
;
88 ULONG nBusyAllocationBytesAccessible
;
89 PDPH_HEAP_BLOCK pNodePoolListHead
;
90 PDPH_HEAP_BLOCK pNodePoolListTail
;
98 PRTL_TRACE_BLOCK CreateStackTrace
;
100 } DPH_HEAP_ROOT
, *PDPH_HEAP_ROOT
;
102 /* GLOBALS ********************************************************************/
104 BOOLEAN RtlpPageHeapEnabled
= FALSE
;
105 ULONG RtlpDphGlobalFlags
;
106 ULONG RtlpPageHeapSizeRangeStart
, RtlpPageHeapSizeRangeEnd
;
107 ULONG RtlpPageHeapDllRangeStart
, RtlpPageHeapDllRangeEnd
;
108 WCHAR RtlpDphTargetDlls
[512];
110 ULONG RtlpDphBreakOptions
;
111 ULONG RtlpDphDebugOptions
;
113 LIST_ENTRY RtlpDphPageHeapList
;
114 BOOLEAN RtlpDphPageHeapListInitialized
;
115 RTL_CRITICAL_SECTION RtlpDphPageHeapListLock
;
116 ULONG RtlpDphPageHeapListLength
;
117 UNICODE_STRING RtlpDphTargetDllsUnicode
;
121 LONG RtlpDphAllocFails
;
122 LONG RtlpDphReleaseFails
;
123 LONG RtlpDphFreeFails
;
124 LONG RtlpDphProtectFails
;
126 #define DPH_RESERVE_SIZE 0x100000
127 #define DPH_POOL_SIZE 0x4000
129 /* RtlpDphBreakOptions */
130 #define DPH_BREAK_ON_RESERVE_FAIL 0x01
131 #define DPH_BREAK_ON_COMMIT_FAIL 0x02
132 #define DPH_BREAK_ON_RELEASE_FAIL 0x04
133 #define DPH_BREAK_ON_FREE_FAIL 0x08
134 #define DPH_BREAK_ON_PROTECT_FAIL 0x10
136 /* RtlpDphDebugOptions */
137 #define DPH_DEBUG_INTERNAL_VALIDATE 0x01
138 #define DPH_DEBUG_VERBOSE 0x04
141 #define DPH_FILL 0xEEEEEEEE
144 #define DPH_SIGNATURE 0xFFEEDDCC
146 /* Biased pointer macros */
147 #define IS_BIASED_POINTER(ptr) ((ULONG_PTR)(ptr) & 1)
148 #define POINTER_REMOVE_BIAS(ptr) ((ULONG_PTR)(ptr) & ~(ULONG_PTR)1)
149 #define POINTER_ADD_BIAS(ptr) ((ULONG_PTR)(ptr) & 1)
151 /* FUNCTIONS ******************************************************************/
154 RtlpSecMemFreeVirtualMemory(HANDLE Process
, PVOID
*Base
, PSIZE_T Size
, ULONG Type
)
157 //PVOID *SavedBase = Base;
158 //PSIZE_T SavedSize = Size;
160 /* Free the memory */
161 Status
= ZwFreeVirtualMemory(Process
, Base
, Size
, Type
);
163 /* Flush secure memory cache if needed and retry freeing */
165 if (Status
== STATUS_INVALID_PAGE_PROTECTION
&&
166 Process
== NtCurrentProcess() &&
167 RtlFlushSecureMemoryCache(*SavedBase
, *SavedSize
))
169 Status
= ZwFreeVirtualMemory(NtCurrentProcess(), SavedBase
, SavedSize
, Type
);
177 RtlpDphAllocateVm(PVOID
*Base
, SIZE_T Size
, ULONG Type
, ULONG Protection
)
180 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
187 /* Check for failures */
188 if (!NT_SUCCESS(Status
))
190 if (Type
== MEM_RESERVE
)
192 _InterlockedIncrement(&RtlpDphCounter
);
193 if (RtlpDphBreakOptions
& DPH_BREAK_ON_RESERVE_FAIL
)
195 DPRINT1("Page heap: AllocVm (%p, %p, %x) failed with %x \n", Base
, Size
, Type
, Status
);
202 _InterlockedIncrement(&RtlpDphAllocFails
);
203 if (RtlpDphBreakOptions
& DPH_BREAK_ON_COMMIT_FAIL
)
205 DPRINT1("Page heap: AllocVm (%p, %p, %x) failed with %x \n", Base
, Size
, Type
, Status
);
216 RtlpDphFreeVm(PVOID Base
, SIZE_T Size
, ULONG Type
, ULONG Protection
)
220 /* Free the memory */
221 Status
= RtlpSecMemFreeVirtualMemory(NtCurrentProcess(), &Base
, &Size
, Type
);
223 /* Log/report failures */
224 if (!NT_SUCCESS(Status
))
226 if (Type
== MEM_RELEASE
)
228 _InterlockedIncrement(&RtlpDphReleaseFails
);
229 if (RtlpDphBreakOptions
& DPH_BREAK_ON_RELEASE_FAIL
)
231 DPRINT1("Page heap: FreeVm (%p, %p, %x) failed with %x \n", Base
, Size
, Type
, Status
);
238 _InterlockedIncrement(&RtlpDphFreeFails
);
239 if (RtlpDphBreakOptions
& DPH_BREAK_ON_FREE_FAIL
)
241 DPRINT1("Page heap: FreeVm (%p, %p, %x) failed with %x \n", Base
, Size
, Type
, Status
);
252 RtlpDphProtectVm(PVOID Base
, SIZE_T Size
, ULONG Protection
)
257 /* Change protection */
258 Status
= ZwProtectVirtualMemory(NtCurrentProcess(), &Base
, &Size
, Protection
, &OldProtection
);
260 /* Log/report failures */
261 if (!NT_SUCCESS(Status
))
263 _InterlockedIncrement(&RtlpDphProtectFails
);
264 if (RtlpDphBreakOptions
& DPH_BREAK_ON_PROTECT_FAIL
)
266 DPRINT1("Page heap: ProtectVm (%p, %p, %x) failed with %x \n", Base
, Size
, Protection
, Status
);
276 RtlpDphPlaceOnPoolList(PDPH_HEAP_ROOT DphRoot
, PDPH_HEAP_BLOCK DphNode
)
278 /* DphNode is being added to the tail of the list */
279 DphNode
->pNextAlloc
= NULL
;
281 /* Add it to the tail of the linked list */
282 if (DphRoot
->pNodePoolListTail
)
283 DphRoot
->pNodePoolListTail
->pNextAlloc
= DphNode
;
285 DphRoot
->pNodePoolListHead
= DphNode
;
286 DphRoot
->pNodePoolListTail
= DphNode
;
288 /* Update byte counts taking in account this new node */
289 DphRoot
->nNodePools
++;
290 DphRoot
->nNodePoolBytes
+= DphNode
->nVirtualBlockSize
;
294 RtlpDphPlaceOnVirtualList(PDPH_HEAP_ROOT DphRoot
, PDPH_HEAP_BLOCK DphNode
)
296 /* Add it to the head of the virtual list */
297 DphNode
->pNextAlloc
= DphRoot
->pVirtualStorageListHead
;
298 if (!DphRoot
->pVirtualStorageListHead
)
299 DphRoot
->pVirtualStorageListTail
= DphNode
;
300 DphRoot
->pVirtualStorageListHead
= DphNode
;
302 /* Update byte counts taking in account this new node */
303 DphRoot
->nVirtualStorageRanges
++;
304 DphRoot
->nVirtualStorageBytes
+= DphNode
->nVirtualBlockSize
;
307 PDPH_HEAP_BLOCK NTAPI
308 RtlpDphTakeNodeFromUnusedList(PDPH_HEAP_ROOT DphRoot
)
310 PDPH_HEAP_BLOCK Node
= DphRoot
->pUnusedNodeListHead
;
311 PDPH_HEAP_BLOCK Next
;
313 /* Take the first entry */
314 if (!Node
) return NULL
;
316 /* Remove that entry (Node) from the list */
317 Next
= Node
->pNextAlloc
;
318 if (DphRoot
->pUnusedNodeListHead
== Node
) DphRoot
->pUnusedNodeListHead
= Next
;
319 if (DphRoot
->pUnusedNodeListTail
== Node
) DphRoot
->pUnusedNodeListTail
= NULL
;
321 /* Decrease amount of unused nodes */
322 DphRoot
->nUnusedNodes
--;
328 RtlpDphReturnNodeToUnusedList(PDPH_HEAP_ROOT DphRoot
,
329 PDPH_HEAP_BLOCK Node
)
331 /* Add it back to the head of the unused list */
332 Node
->pNextAlloc
= DphRoot
->pUnusedNodeListHead
;
333 if (!DphRoot
->pUnusedNodeListHead
) DphRoot
->pUnusedNodeListTail
= Node
;
334 DphRoot
->pUnusedNodeListHead
= Node
;
336 /* Increase amount of unused nodes */
337 DphRoot
->nUnusedNodes
++;
341 RtlpDphRemoveFromAvailableList(PDPH_HEAP_ROOT DphRoot
,
342 PDPH_HEAP_BLOCK Node
)
344 /* Make sure Adjacency list pointers are biased */
345 ASSERT(IS_BIASED_POINTER(Node
->AdjacencyEntry
.Flink
));
346 ASSERT(IS_BIASED_POINTER(Node
->AdjacencyEntry
.Blink
));
348 /* Remove it from the list */
349 RemoveEntryList(&Node
->AvailableEntry
);
351 /* Decrease heap counters */
352 DphRoot
->nAvailableAllocations
--;
353 DphRoot
->nAvailableAllocationBytesCommitted
-= Node
->nVirtualBlockSize
;
355 /* Remove bias from the AdjacencyEntry pointer */
356 POINTER_REMOVE_BIAS(Node
->AdjacencyEntry
.Flink
);
357 POINTER_REMOVE_BIAS(Node
->AdjacencyEntry
.Blink
);
361 RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot
,
362 PDPH_HEAP_BLOCK Node
)
368 RtlpDphAddNewPool(PDPH_HEAP_ROOT DphRoot
, PDPH_HEAP_BLOCK NodeBlock
, PVOID Virtual
, SIZE_T Size
, BOOLEAN PlaceOnPool
)
370 PDPH_HEAP_BLOCK DphNode
, DphStartNode
;
373 NodeCount
= (Size
>> 6) - 1;
374 DphStartNode
= Virtual
;
376 /* Set pNextAlloc for all blocks */
377 for (DphNode
= Virtual
; NodeCount
> 0; DphNode
++, NodeCount
--)
378 DphNode
->pNextAlloc
= DphNode
+ 1;
380 /* and the last one */
381 DphNode
->pNextAlloc
= NULL
;
383 /* Add it to the tail of unused node list */
384 if (DphRoot
->pUnusedNodeListTail
)
385 DphRoot
->pUnusedNodeListTail
->pNextAlloc
= DphStartNode
;
387 DphRoot
->pUnusedNodeListHead
= DphStartNode
;
389 DphRoot
->pUnusedNodeListTail
= DphNode
;
391 /* Increase counters */
392 DphRoot
->nUnusedNodes
+= NodeCount
;
394 /* Check if we need to place it on the pool list */
397 /* Get a node from the unused list */
398 DphNode
= RtlpDphTakeNodeFromUnusedList(DphRoot
);
401 /* Set its virtual block values */
402 DphNode
->pVirtualBlock
= Virtual
;
403 DphNode
->nVirtualBlockSize
= Size
;
405 /* Place it on the pool list */
406 RtlpDphPlaceOnPoolList(DphRoot
, DphNode
);
410 PDPH_HEAP_BLOCK NTAPI
411 RtlpDphFindAvailableMemory(PDPH_HEAP_ROOT DphRoot
,
413 PDPH_HEAP_BLOCK
*Prev
)
419 PDPH_HEAP_BLOCK NTAPI
420 RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot
)
422 PDPH_HEAP_BLOCK Node
;
424 ULONG Size
= DPH_POOL_SIZE
;
427 /* Check for the easy case */
428 if (DphRoot
->pUnusedNodeListHead
)
430 /* Just take a node from this list */
431 Node
= RtlpDphTakeNodeFromUnusedList(DphRoot
);
436 /* There is a need to make free space */
437 Node
= RtlpDphFindAvailableMemory(DphRoot
, DPH_POOL_SIZE
, NULL
);
439 if (!DphRoot
->pUnusedNodeListHead
&& !Node
)
441 /* Retry with a smaller request */
443 Node
= RtlpDphFindAvailableMemory(DphRoot
, PAGE_SIZE
, NULL
);
446 if (!DphRoot
->pUnusedNodeListHead
)
450 RtlpDphRemoveFromAvailableList(DphRoot
, Node
);
451 Ptr
= Node
->pVirtualBlock
;
455 /* No free space, need to alloc a new VM block */
456 Size
= DPH_POOL_SIZE
;
457 Status
= RtlpDphAllocateVm(&Ptr
, DPH_RESERVE_SIZE
, MEM_COMMIT
, PAGE_NOACCESS
);
459 if (!NT_SUCCESS(Status
))
461 /* Retry with a smaller size */
462 Status
= RtlpDphAllocateVm(&Ptr
, 0x10000, MEM_COMMIT
, PAGE_NOACCESS
);
463 if (!NT_SUCCESS(Status
)) return NULL
;
467 /* VM is allocated at this point, set protection */
468 Status
= RtlpDphProtectVm(Ptr
, Size
, PAGE_READWRITE
);
469 if (!NT_SUCCESS(Status
))
475 /* Zero the memory */
476 if (Node
) RtlZeroMemory(Ptr
, Size
);
478 /* Add a new pool based on this VM */
479 RtlpDphAddNewPool(DphRoot
, Node
, Ptr
, Size
, TRUE
);
487 if (Node
->nVirtualBlockSize
> Size
)
489 Node
->pVirtualBlock
+= Size
;
490 Node
->nVirtualBlockSize
-= Size
;
492 RtlpDphCoalesceNodeIntoAvailable(DphRoot
, Node
);
496 RtlpDphReturnNodeToUnusedList(DphRoot
, Node
);
501 return RtlpDphTakeNodeFromUnusedList(DphRoot
);
504 RTL_GENERIC_COMPARE_RESULTS
506 RtlpDphCompareNodeForTable(IN PRTL_AVL_TABLE Table
,
507 IN PVOID FirstStruct
,
508 IN PVOID SecondStruct
)
517 RtlpDphAllocateNodeForTable(IN PRTL_AVL_TABLE Table
,
527 RtlpDphFreeNodeForTable(IN PRTL_AVL_TABLE Table
,
535 RtlpDphInitializeDelayedFreeQueue()
538 return STATUS_SUCCESS
;
542 RtlpDphTargetDllsLogicInitialize()
545 return STATUS_SUCCESS
;
549 RtlpDphInternalValidatePageHeap(PDPH_HEAP_ROOT DphRoot
, PVOID Address
, ULONG Value
)
555 RtlpDphProcessStartupInitialization()
558 PTEB Teb
= NtCurrentTeb();
560 /* Initialize the DPH heap list and its critical section */
561 InitializeListHead(&RtlpDphPageHeapList
);
562 Status
= RtlInitializeCriticalSection(&RtlpDphPageHeapListLock
);
563 if (!NT_SUCCESS(Status
))
569 /* Initialize delayed-free queue */
570 Status
= RtlpDphInitializeDelayedFreeQueue();
571 if (!NT_SUCCESS(Status
)) return Status
;
573 /* Initialize the target dlls string */
574 RtlInitUnicodeString(&RtlpDphTargetDllsUnicode
, RtlpDphTargetDlls
);
575 Status
= RtlpDphTargetDllsLogicInitialize();
577 /* Per-process DPH init is done */
578 RtlpDphPageHeapListInitialized
= TRUE
;
580 DPRINT1("Page heap: pid 0x%X: page heap enabled with flags 0x%X.\n", Teb
->ClientId
.UniqueProcess
, RtlpDphGlobalFlags
);
586 RtlpPageHeapCreate(ULONG Flags
,
591 PRTL_HEAP_PARAMETERS Parameters
)
595 PDPH_HEAP_ROOT DphRoot
;
596 PDPH_HEAP_BLOCK DphNode
;
599 LARGE_INTEGER PerfCounter
;
601 /* Check for a DPH bypass flag */
602 if ((ULONG_PTR
)Parameters
== -1) return NULL
;
604 /* Make sure no user-allocated stuff was provided */
605 if (Addr
|| Lock
) return NULL
;
607 /* Allocate minimum amount of virtual memory */
608 MemSize
= DPH_RESERVE_SIZE
;
609 Status
= RtlpDphAllocateVm(&Base
, MemSize
, MEM_COMMIT
, PAGE_NOACCESS
);
610 if (!NT_SUCCESS(Status
))
617 Status
= RtlpDphProtectVm(Base
, 2*PAGE_SIZE
+ DPH_POOL_SIZE
, PAGE_READWRITE
);
618 if (!NT_SUCCESS(Status
))
620 //RtlpDphFreeVm(Base, 0, 0, 0);
625 /* Start preparing the 1st page. Fill it with the default filler */
626 RtlFillMemory(Base
, PAGE_SIZE
, DPH_FILL
);
628 /* Set flags in the "HEAP" structure */
629 HeapPtr
= (PHEAP
)Base
;
630 HeapPtr
->Flags
= Flags
| HEAP_FLAG_PAGE_ALLOCS
;
631 HeapPtr
->ForceFlags
= Flags
| HEAP_FLAG_PAGE_ALLOCS
;
633 /* Set 1st page to read only now */
634 Status
= RtlpDphProtectVm(Base
, PAGE_SIZE
, PAGE_READONLY
);
635 if (!NT_SUCCESS(Status
))
641 /* 2nd page is the real DPH root block */
642 DphRoot
= (PDPH_HEAP_ROOT
)((PCHAR
)Base
+ PAGE_SIZE
);
644 /* Initialize the DPH root */
645 DphRoot
->Signature
= DPH_SIGNATURE
;
646 DphRoot
->HeapFlags
= Flags
;
647 DphRoot
->HeapCritSect
= (PRTL_CRITICAL_SECTION
)((PCHAR
)DphRoot
+ DPH_POOL_SIZE
);
648 DphRoot
->ExtraFlags
= RtlpDphGlobalFlags
;
650 ZwQueryPerformanceCounter(&PerfCounter
, NULL
);
651 DphRoot
->Seed
= PerfCounter
.LowPart
;
653 RtlInitializeCriticalSection(DphRoot
->HeapCritSect
);
655 /* Create a normal heap for this paged heap */
656 DphRoot
->NormalHeap
= RtlCreateHeap(Flags
, NULL
, TotalSize
, CommitSize
, NULL
, (PRTL_HEAP_PARAMETERS
)-1);
657 if (!DphRoot
->NormalHeap
)
663 /* 3rd page: a pool for DPH allocations */
664 RtlpDphAddNewPool(DphRoot
, NULL
, DphRoot
+ 1, DPH_POOL_SIZE
- sizeof(DPH_HEAP_ROOT
), FALSE
);
666 /* Allocate internal heap blocks. For the root */
667 DphNode
= RtlpDphAllocateNode(DphRoot
);
668 ASSERT(DphNode
!= NULL
);
669 DphNode
->pVirtualBlock
= (PUCHAR
)DphRoot
;
670 DphNode
->nVirtualBlockSize
= DPH_POOL_SIZE
;
671 RtlpDphPlaceOnPoolList(DphRoot
, DphNode
);
673 /* For the memory we allocated as a whole */
674 DphNode
= RtlpDphAllocateNode(DphRoot
);
675 ASSERT(DphNode
!= NULL
);
676 DphNode
->pVirtualBlock
= Base
;
677 DphNode
->nVirtualBlockSize
= MemSize
;
678 RtlpDphPlaceOnVirtualList(DphRoot
, DphNode
);
680 /* For the remaining part */
681 DphNode
= RtlpDphAllocateNode(DphRoot
);
682 ASSERT(DphNode
!= NULL
);
683 DphNode
->pVirtualBlock
= (PUCHAR
)Base
+ 2*PAGE_SIZE
+ DPH_POOL_SIZE
;
684 DphNode
->nVirtualBlockSize
= MemSize
- (2*PAGE_SIZE
+ DPH_POOL_SIZE
);
685 RtlpDphCoalesceNodeIntoAvailable(DphRoot
, DphNode
);
687 //DphRoot->CreateStackTrace = RtlpDphLogStackTrace(1);
689 /* Initialize AVL-based busy nodes table */
690 RtlInitializeGenericTableAvl(&DphRoot
->BusyNodesTable
,
691 RtlpDphCompareNodeForTable
,
692 RtlpDphAllocateNodeForTable
,
693 RtlpDphFreeNodeForTable
,
696 /* Initialize per-process startup info */
697 if (!RtlpDphPageHeapListInitialized
) RtlpDphProcessStartupInitialization();
699 /* Acquire the heap list lock */
700 RtlEnterCriticalSection(&RtlpDphPageHeapListLock
);
702 /* Insert this heap to the tail of the global list */
703 InsertTailList(&RtlpDphPageHeapList
, &DphRoot
->NextHeap
);
705 /* Note we increased the size of the list */
706 RtlpDphPageHeapListLength
++;
708 /* Release the heap list lock */
709 RtlLeaveCriticalSection(&RtlpDphPageHeapListLock
);
711 if (RtlpDphDebugOptions
& DPH_DEBUG_VERBOSE
)
713 DPRINT1("Page heap: process 0x%X created heap @ %p (%p, flags 0x%X)\n",
714 NtCurrentTeb()->ClientId
.UniqueProcess
, (PUCHAR
)DphRoot
- PAGE_SIZE
, DphRoot
->NormalHeap
, DphRoot
->ExtraFlags
);
717 /* Perform internal validation if required */
718 if (RtlpDphDebugOptions
& DPH_DEBUG_INTERNAL_VALIDATE
)
719 RtlpDphInternalValidatePageHeap(DphRoot
, NULL
, 0);
721 return (PUCHAR
)DphRoot
- PAGE_SIZE
;
725 RtlpPageHeapDestroy(HANDLE HeapPtr
)
731 RtlpPageHeapAllocate(IN PVOID HeapPtr
,
739 RtlpPageHeapFree(HANDLE HeapPtr
,
747 RtlpPageHeapReAllocate(HANDLE HeapPtr
,
756 RtlpPageHeapGetUserInfo(PVOID HeapHandle
,
766 RtlpPageHeapSetUserValue(PVOID HeapHandle
,
776 RtlpPageHeapSetUserFlags(PVOID HeapHandle
,
779 ULONG UserFlagsReset
,
786 RtlpPageHeapSize(HANDLE HeapPtr
,