ReactOS 0.4.16-dev-1019-g2c2cdfd
heappage.c File Reference
#include <rtl.h>
#include <heap.h>
#include <reactos/verifier.h>
#include <debug.h>
Include dependency graph for heappage.c:

Go to the source code of this file.

Classes

struct  _DPH_BLOCK_INFORMATION
 
struct  _DPH_HEAP_BLOCK
 
struct  _DPH_HEAP_ROOT
 

Macros

#define NDEBUG
 
#define DPH_RESERVE_SIZE   0x100000
 
#define DPH_POOL_SIZE   0x4000
 
#define DPH_FREE_LIST_MINIMUM   8
 
#define DPH_BREAK_ON_RESERVE_FAIL   0x01
 
#define DPH_BREAK_ON_COMMIT_FAIL   0x02
 
#define DPH_BREAK_ON_RELEASE_FAIL   0x04
 
#define DPH_BREAK_ON_FREE_FAIL   0x08
 
#define DPH_BREAK_ON_PROTECT_FAIL   0x10
 
#define DPH_BREAK_ON_NULL_FREE   0x80
 
#define DPH_DEBUG_INTERNAL_VALIDATE   0x01
 
#define DPH_DEBUG_VERBOSE   0x04
 
#define DPH_EXTRA_LOG_STACK_TRACES   0x02
 
#define DPH_EXTRA_CHECK_UNDERRUN   0x10
 
#define DPH_FILL   0xEEEEEEEE
 
#define DPH_FILL_START_STAMP_1   0xABCDBBBB
 
#define DPH_FILL_START_STAMP_2   0xABCDBBBA
 
#define DPH_FILL_END_STAMP_1   0xDCBABBBB
 
#define DPH_FILL_END_STAMP_2   0xDCBABBBA
 
#define DPH_FILL_SUFFIX   0xD0
 
#define DPH_FILL_INFIX   0xC0
 
#define DPH_VALINFO_BAD_START_STAMP   0x01
 
#define DPH_VALINFO_BAD_END_STAMP   0x02
 
#define DPH_VALINFO_BAD_POINTER   0x04
 
#define DPH_VALINFO_BAD_PREFIX_PATTERN   0x08
 
#define DPH_VALINFO_BAD_SUFFIX_PATTERN   0x10
 
#define DPH_VALINFO_EXCEPTION   0x20
 
#define DPH_VALINFO_1   0x40
 
#define DPH_VALINFO_BAD_INFIX_PATTERN   0x80
 
#define DPH_VALINFO_ALREADY_FREED   0x100
 
#define DPH_VALINFO_CORRUPTED_AFTER_FREE   0x200
 
#define DPH_SIGNATURE   0xFFEEDDCC
 
#define IS_BIASED_POINTER(ptr)   ((ULONG_PTR)(ptr) & 1)
 
#define POINTER_REMOVE_BIAS(ptr)   ((ULONG_PTR)(ptr) & ~(ULONG_PTR)1)
 
#define POINTER_ADD_BIAS(ptr)   ((ULONG_PTR)(ptr) | 1)
 

Typedefs

typedef struct _DPH_BLOCK_INFORMATION DPH_BLOCK_INFORMATION
 
typedef struct _DPH_BLOCK_INFORMATIONPDPH_BLOCK_INFORMATION
 
typedef struct _DPH_HEAP_BLOCK DPH_HEAP_BLOCK
 
typedef struct _DPH_HEAP_BLOCKPDPH_HEAP_BLOCK
 
typedef struct _DPH_HEAP_ROOT DPH_HEAP_ROOT
 
typedef struct _DPH_HEAP_ROOTPDPH_HEAP_ROOT
 

Functions

BOOLEAN NTAPI RtlpDphGrowVirtual (PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
 
BOOLEAN NTAPI RtlpDphIsNormalFreeHeapBlock (PVOID Block, PULONG ValidationInformation, BOOLEAN CheckFillers)
 
VOID NTAPI RtlpDphReportCorruptedBlock (_In_ PDPH_HEAP_ROOT DphRoot, _In_ ULONG Reserved, _In_ PVOID Block, _In_ ULONG ValidationInfo)
 
BOOLEAN NTAPI RtlpDphNormalHeapValidate (PDPH_HEAP_ROOT DphRoot, ULONG Flags, PVOID BaseAddress)
 
VOID NTAPI AVrfInternalHeapFreeNotification (PVOID AllocationBase, SIZE_T AllocationSize)
 
VOID NTAPI RtlpDphRaiseException (NTSTATUS Status)
 
PVOID NTAPI RtlpDphPointerFromHandle (PVOID Handle)
 
PVOID NTAPI RtlpDphHeapFromPointer (PDPH_HEAP_ROOT DphHeap)
 
ULONG NTAPI RtlpDphGetBlockSizeFromCorruptedBlock (PVOID Block)
 
VOID NTAPI RtlpDphEnterCriticalSection (PDPH_HEAP_ROOT DphRoot, ULONG Flags)
 
VOID NTAPI RtlpDphLeaveCriticalSection (PDPH_HEAP_ROOT DphRoot)
 
VOID NTAPI RtlpDphPreProcessing (PDPH_HEAP_ROOT DphRoot, ULONG Flags)
 
VOID NTAPI RtlpDphPostProcessing (PDPH_HEAP_ROOT DphRoot)
 
NTSTATUS NTAPI RtlpSecMemFreeVirtualMemory (HANDLE Process, PVOID *Base, PSIZE_T Size, ULONG Type)
 
NTSTATUS NTAPI RtlpDphAllocateVm (PVOID *Base, SIZE_T Size, ULONG Type, ULONG Protection)
 
NTSTATUS NTAPI RtlpDphFreeVm (PVOID Base, SIZE_T Size, ULONG Type)
 
NTSTATUS NTAPI RtlpDphProtectVm (PVOID Base, SIZE_T Size, ULONG Protection)
 
BOOLEAN NTAPI RtlpDphWritePageHeapBlockInformation (PDPH_HEAP_ROOT DphRoot, PVOID UserAllocation, SIZE_T Size, SIZE_T UserSize)
 
VOID NTAPI RtlpDphPlaceOnBusyList (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK DphNode)
 
VOID NTAPI RtlpDphPlaceOnFreeList (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
 
VOID NTAPI RtlpDphPlaceOnPoolList (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
 
VOID NTAPI RtlpDphPlaceOnVirtualList (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
 
PDPH_HEAP_BLOCK NTAPI RtlpDphTakeNodeFromUnusedList (PDPH_HEAP_ROOT DphRoot)
 
VOID NTAPI RtlpDphReturnNodeToUnusedList (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
 
VOID NTAPI RtlpDphRemoveFromAvailableList (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
 
VOID NTAPI RtlpDphRemoveFromBusyList (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
 
VOID NTAPI RtlpDphRemoveFromFreeList (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node, PDPH_HEAP_BLOCK Prev)
 
VOID NTAPI RtlpDphCoalesceNodeIntoAvailable (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
 
VOID NTAPI RtlpDphCoalesceFreeIntoAvailable (PDPH_HEAP_ROOT DphRoot, ULONG LeaveOnFreeList)
 
VOID NTAPI RtlpDphAddNewPool (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK NodeBlock, PVOID Virtual, SIZE_T Size, BOOLEAN PlaceOnPool)
 
PDPH_HEAP_BLOCK NTAPI RtlpDphSearchAvailableMemoryListForBestFit (PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
 
PDPH_HEAP_BLOCK NTAPI RtlpDphFindAvailableMemory (PDPH_HEAP_ROOT DphRoot, SIZE_T Size, BOOLEAN Grow)
 
PDPH_HEAP_BLOCK NTAPI RtlpDphFindBusyMemory (PDPH_HEAP_ROOT DphRoot, PVOID pUserMem)
 
NTSTATUS NTAPI RtlpDphSetProtectionBeforeUse (PDPH_HEAP_ROOT DphRoot, PUCHAR VirtualBlock, ULONG UserSize)
 
NTSTATUS NTAPI RtlpDphSetProtectionAfterUse (PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
 
PDPH_HEAP_BLOCK NTAPI RtlpDphAllocateNode (PDPH_HEAP_ROOT DphRoot)
 
RTL_GENERIC_COMPARE_RESULTS NTAPI RtlpDphCompareNodeForTable (IN PRTL_AVL_TABLE Table, IN PVOID FirstStruct, IN PVOID SecondStruct)
 
PVOID NTAPI RtlpDphAllocateNodeForTable (IN PRTL_AVL_TABLE Table, IN CLONG ByteSize)
 
VOID NTAPI RtlpDphFreeNodeForTable (IN PRTL_AVL_TABLE Table, IN PVOID Buffer)
 
NTSTATUS NTAPI RtlpDphInitializeDelayedFreeQueue (VOID)
 
VOID NTAPI RtlpDphFreeDelayedBlocksFromHeap (PDPH_HEAP_ROOT DphRoot, PHEAP NormalHeap)
 
NTSTATUS NTAPI RtlpDphTargetDllsLogicInitialize (VOID)
 
VOID NTAPI RtlpDphInternalValidatePageHeap (PDPH_HEAP_ROOT DphRoot, PVOID Address, ULONG Value)
 
VOID NTAPI RtlpDphVerifyIntegrity (PDPH_HEAP_ROOT DphRoot)
 
BOOLEAN NTAPI RtlpDphIsPageHeapBlock (PDPH_HEAP_ROOT DphRoot, PVOID Block, PULONG ValidationInformation, BOOLEAN CheckFillers)
 
NTSTATUS NTAPI RtlpDphProcessStartupInitialization (VOID)
 
BOOLEAN NTAPI RtlpDphShouldAllocateInPageHeap (PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
 
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 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)
 
SIZE_T NTAPI RtlpPageHeapSize (HANDLE HeapHandle, ULONG Flags, PVOID BaseAddress)
 
BOOLEAN NTAPI RtlpDebugPageHeapValidate (PVOID HeapHandle, ULONG Flags, PVOID BaseAddress)
 
BOOLEAN NTAPI RtlpPageHeapLock (HANDLE HeapPtr)
 
BOOLEAN NTAPI RtlpPageHeapUnlock (HANDLE HeapPtr)
 

Variables

BOOLEAN RtlpPageHeapEnabled = FALSE
 
ULONG RtlpDphGlobalFlags
 
ULONG RtlpPageHeapSizeRangeStart
 
ULONG RtlpPageHeapSizeRangeEnd
 
ULONG RtlpPageHeapDllRangeStart
 
ULONG RtlpPageHeapDllRangeEnd
 
WCHAR RtlpDphTargetDlls [512]
 
LIST_ENTRY RtlpDphPageHeapList
 
BOOLEAN RtlpDphPageHeapListInitialized
 
HEAP_LOCK _RtlpDphPageHeapListLock
 
PHEAP_LOCK RtlpDphPageHeapListLock = &_RtlpDphPageHeapListLock
 
ULONG RtlpDphPageHeapListLength
 
UNICODE_STRING RtlpDphTargetDllsUnicode
 
HEAP_LOCK _RtlpDphDelayedFreeQueueLock
 
PHEAP_LOCK RtlpDphDelayedFreeQueueLock = &_RtlpDphDelayedFreeQueueLock
 
LIST_ENTRY RtlpDphDelayedFreeQueue
 
SLIST_HEADER RtlpDphDelayedTemporaryPushList
 
SIZE_T RtlpDphMemoryUsedByDelayedFreeBlocks
 
ULONG RtlpDphNumberOfDelayedFreeBlocks
 
LONG RtlpDphCounter
 
LONG RtlpDphAllocFails
 
LONG RtlpDphReleaseFails
 
LONG RtlpDphFreeFails
 
LONG RtlpDphProtectFails
 
ULONG RtlpDphBreakOptions = 0
 
ULONG RtlpDphDebugOptions
 

Macro Definition Documentation

◆ DPH_BREAK_ON_COMMIT_FAIL

#define DPH_BREAK_ON_COMMIT_FAIL   0x02

Definition at line 140 of file heappage.c.

◆ DPH_BREAK_ON_FREE_FAIL

#define DPH_BREAK_ON_FREE_FAIL   0x08

Definition at line 142 of file heappage.c.

◆ DPH_BREAK_ON_NULL_FREE

#define DPH_BREAK_ON_NULL_FREE   0x80

Definition at line 144 of file heappage.c.

◆ DPH_BREAK_ON_PROTECT_FAIL

#define DPH_BREAK_ON_PROTECT_FAIL   0x10

Definition at line 143 of file heappage.c.

◆ DPH_BREAK_ON_RELEASE_FAIL

#define DPH_BREAK_ON_RELEASE_FAIL   0x04

Definition at line 141 of file heappage.c.

◆ DPH_BREAK_ON_RESERVE_FAIL

#define DPH_BREAK_ON_RESERVE_FAIL   0x01

Definition at line 139 of file heappage.c.

◆ DPH_DEBUG_INTERNAL_VALIDATE

#define DPH_DEBUG_INTERNAL_VALIDATE   0x01

Definition at line 147 of file heappage.c.

◆ DPH_DEBUG_VERBOSE

#define DPH_DEBUG_VERBOSE   0x04

Definition at line 148 of file heappage.c.

◆ DPH_EXTRA_CHECK_UNDERRUN

#define DPH_EXTRA_CHECK_UNDERRUN   0x10

Definition at line 152 of file heappage.c.

◆ DPH_EXTRA_LOG_STACK_TRACES

#define DPH_EXTRA_LOG_STACK_TRACES   0x02

Definition at line 151 of file heappage.c.

◆ DPH_FILL

#define DPH_FILL   0xEEEEEEEE

Definition at line 155 of file heappage.c.

◆ DPH_FILL_END_STAMP_1

#define DPH_FILL_END_STAMP_1   0xDCBABBBB

Definition at line 158 of file heappage.c.

◆ DPH_FILL_END_STAMP_2

#define DPH_FILL_END_STAMP_2   0xDCBABBBA

Definition at line 159 of file heappage.c.

◆ DPH_FILL_INFIX

#define DPH_FILL_INFIX   0xC0

Definition at line 161 of file heappage.c.

◆ DPH_FILL_START_STAMP_1

#define DPH_FILL_START_STAMP_1   0xABCDBBBB

Definition at line 156 of file heappage.c.

◆ DPH_FILL_START_STAMP_2

#define DPH_FILL_START_STAMP_2   0xABCDBBBA

Definition at line 157 of file heappage.c.

◆ DPH_FILL_SUFFIX

#define DPH_FILL_SUFFIX   0xD0

Definition at line 160 of file heappage.c.

◆ DPH_FREE_LIST_MINIMUM

#define DPH_FREE_LIST_MINIMUM   8

Definition at line 136 of file heappage.c.

◆ DPH_POOL_SIZE

#define DPH_POOL_SIZE   0x4000

Definition at line 135 of file heappage.c.

◆ DPH_RESERVE_SIZE

#define DPH_RESERVE_SIZE   0x100000

Definition at line 134 of file heappage.c.

◆ DPH_SIGNATURE

#define DPH_SIGNATURE   0xFFEEDDCC

Definition at line 176 of file heappage.c.

◆ DPH_VALINFO_1

#define DPH_VALINFO_1   0x40

Definition at line 170 of file heappage.c.

◆ DPH_VALINFO_ALREADY_FREED

#define DPH_VALINFO_ALREADY_FREED   0x100

Definition at line 172 of file heappage.c.

◆ DPH_VALINFO_BAD_END_STAMP

#define DPH_VALINFO_BAD_END_STAMP   0x02

Definition at line 165 of file heappage.c.

◆ DPH_VALINFO_BAD_INFIX_PATTERN

#define DPH_VALINFO_BAD_INFIX_PATTERN   0x80

Definition at line 171 of file heappage.c.

◆ DPH_VALINFO_BAD_POINTER

#define DPH_VALINFO_BAD_POINTER   0x04

Definition at line 166 of file heappage.c.

◆ DPH_VALINFO_BAD_PREFIX_PATTERN

#define DPH_VALINFO_BAD_PREFIX_PATTERN   0x08

Definition at line 167 of file heappage.c.

◆ DPH_VALINFO_BAD_START_STAMP

#define DPH_VALINFO_BAD_START_STAMP   0x01

Definition at line 164 of file heappage.c.

◆ DPH_VALINFO_BAD_SUFFIX_PATTERN

#define DPH_VALINFO_BAD_SUFFIX_PATTERN   0x10

Definition at line 168 of file heappage.c.

◆ DPH_VALINFO_CORRUPTED_AFTER_FREE

#define DPH_VALINFO_CORRUPTED_AFTER_FREE   0x200

Definition at line 173 of file heappage.c.

◆ DPH_VALINFO_EXCEPTION

#define DPH_VALINFO_EXCEPTION   0x20

Definition at line 169 of file heappage.c.

◆ IS_BIASED_POINTER

#define IS_BIASED_POINTER (   ptr)    ((ULONG_PTR)(ptr) & 1)

Definition at line 179 of file heappage.c.

◆ NDEBUG

#define NDEBUG

Definition at line 20 of file heappage.c.

◆ POINTER_ADD_BIAS

#define POINTER_ADD_BIAS (   ptr)    ((ULONG_PTR)(ptr) | 1)

Definition at line 181 of file heappage.c.

◆ POINTER_REMOVE_BIAS

#define POINTER_REMOVE_BIAS (   ptr)    ((ULONG_PTR)(ptr) & ~(ULONG_PTR)1)

Definition at line 180 of file heappage.c.

Typedef Documentation

◆ DPH_BLOCK_INFORMATION

◆ DPH_HEAP_BLOCK

◆ DPH_HEAP_ROOT

◆ PDPH_BLOCK_INFORMATION

◆ PDPH_HEAP_BLOCK

◆ PDPH_HEAP_ROOT

Function Documentation

◆ AVrfInternalHeapFreeNotification()

VOID NTAPI AVrfInternalHeapFreeNotification ( PVOID  AllocationBase,
SIZE_T  AllocationSize 
)

Definition at line 364 of file verifier.c.

365{
367
369 return;
370
373 {
375 RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK ProviderHeapFreeCallback;
376
378
379 ProviderHeapFreeCallback = Provider->ProviderNtdllHeapFreeCallback;
380 if (ProviderHeapFreeCallback)
381 {
382 ProviderHeapFreeCallback(AllocationBase, AllocationSize);
383 }
384 }
386}
#define NtCurrentPeb()
Definition: FLS.c:22
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:323
#define FLG_APPLICATION_VERIFIER
Definition: pstypes.h:64
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
LIST_ENTRY AVrfpVerifierProvidersList
Definition: verifier.c:26
BOOL AVrfpInitialized
Definition: verifier.c:24
RTL_CRITICAL_SECTION AVrfpVerifierLock
Definition: verifier.c:25
ULONG NtGlobalFlag
Definition: init.c:54
base of all file and directory entries
Definition: entries.h:83
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
VOID(NTAPI * RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK)(PVOID AllocationBase, SIZE_T AllocationSize)
Definition: verifier.h:8

Referenced by RtlpPageHeapDestroy().

◆ RtlpDebugPageHeapValidate()

BOOLEAN NTAPI RtlpDebugPageHeapValidate ( PVOID  HeapHandle,
ULONG  Flags,
PVOID  BaseAddress 
)

Definition at line 2359 of file heappage.c.

2362{
2363 PDPH_HEAP_ROOT DphRoot;
2365 BOOLEAN Valid = FALSE;
2366
2367 /* Get a pointer to the heap root */
2368 DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2369 if (!DphRoot) return -1;
2370
2371 /* Add heap flags */
2372 Flags |= DphRoot->HeapFlags;
2373
2374 /* Acquire the heap lock */
2375 RtlpDphPreProcessing(DphRoot, Flags);
2376
2377 /* Find busy memory */
2378 if (BaseAddress)
2380
2381 if (!Node)
2382 {
2383 /* This block was not found in page heap, or the request is to validate all normal heap */
2384 Valid = RtlpDphNormalHeapValidate(DphRoot, Flags, BaseAddress);
2385 }
2386
2387 /* Leave the heap lock */
2388 RtlpDphPostProcessing(DphRoot);
2389
2390 /* Return result of a normal heap validation */
2391 if (BaseAddress && !Node)
2392 return Valid;
2393
2394 /* Otherwise return our own result */
2395 if (!BaseAddress || Node) Valid = TRUE;
2396
2397 return Valid;
2398}
unsigned char BOOLEAN
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
VOID NTAPI RtlpDphPreProcessing(PDPH_HEAP_ROOT DphRoot, ULONG Flags)
Definition: heappage.c:301
PVOID NTAPI RtlpDphPointerFromHandle(PVOID Handle)
Definition: heappage.c:227
VOID NTAPI RtlpDphPostProcessing(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:309
BOOLEAN NTAPI RtlpDphNormalHeapValidate(PDPH_HEAP_ROOT DphRoot, ULONG Flags, PVOID BaseAddress)
Definition: heappage.c:2402
PDPH_HEAP_BLOCK NTAPI RtlpDphFindBusyMemory(PDPH_HEAP_ROOT DphRoot, PVOID pUserMem)
Definition: heappage.c:964
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG HeapFlags
Definition: heappage.c:65
Definition: dlist.c:348
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by RtlValidateHeap().

◆ RtlpDphAddNewPool()

VOID NTAPI RtlpDphAddNewPool ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  NodeBlock,
PVOID  Virtual,
SIZE_T  Size,
BOOLEAN  PlaceOnPool 
)

Definition at line 829 of file heappage.c.

830{
831 PDPH_HEAP_BLOCK DphNode, DphStartNode;
832 ULONG NodeCount, i;
833
834 //NodeCount = (Size >> 6) - 1;
835 NodeCount = (ULONG)(Size / sizeof(DPH_HEAP_BLOCK));
836 DphStartNode = Virtual;
837
838 /* Set pNextAlloc for all blocks */
839 for (DphNode = Virtual, i=NodeCount-1; i > 0; i--)
840 {
841 DphNode->pNextAlloc = DphNode + 1;
842 DphNode = DphNode->pNextAlloc;
843 }
844
845 /* and the last one */
846 DphNode->pNextAlloc = NULL;
847
848 /* Add it to the tail of unused node list */
849 if (DphRoot->pUnusedNodeListTail)
850 DphRoot->pUnusedNodeListTail->pNextAlloc = DphStartNode;
851 else
852 DphRoot->pUnusedNodeListHead = DphStartNode;
853
854 DphRoot->pUnusedNodeListTail = DphNode;
855
856 /* Increase counters */
857 DphRoot->nUnusedNodes += NodeCount;
858
859 /* Check if we need to place it on the pool list */
860 if (PlaceOnPool)
861 {
862 /* Get a node from the unused list */
863 DphNode = RtlpDphTakeNodeFromUnusedList(DphRoot);
864 ASSERT(DphNode);
865
866 /* Set its virtual block values */
867 DphNode->pVirtualBlock = Virtual;
868 DphNode->nVirtualBlockSize = Size;
869
870 /* Place it on the pool list */
871 RtlpDphPlaceOnPoolList(DphRoot, DphNode);
872 }
873}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID NTAPI RtlpDphPlaceOnPoolList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:515
PDPH_HEAP_BLOCK NTAPI RtlpDphTakeNodeFromUnusedList(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:551
#define ASSERT(a)
Definition: mode.c:44
PUCHAR pVirtualBlock
Definition: heappage.c:50
SIZE_T nVirtualBlockSize
Definition: heappage.c:51
struct _DPH_HEAP_BLOCK * pNextAlloc
Definition: heappage.c:45
ULONG nUnusedNodes
Definition: heappage.c:90
PDPH_HEAP_BLOCK pUnusedNodeListHead
Definition: heappage.c:88
PDPH_HEAP_BLOCK pUnusedNodeListTail
Definition: heappage.c:89
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by RtlpDphAllocateNode(), and RtlpPageHeapCreate().

◆ RtlpDphAllocateNode()

PDPH_HEAP_BLOCK NTAPI RtlpDphAllocateNode ( PDPH_HEAP_ROOT  DphRoot)

Definition at line 1018 of file heappage.c.

1019{
1022 SIZE_T Size = DPH_POOL_SIZE, SizeVirtual;
1023 PVOID Ptr = NULL;
1024
1025 /* Check for the easy case */
1026 if (DphRoot->pUnusedNodeListHead)
1027 {
1028 /* Just take a node from this list */
1030 ASSERT(Node);
1031 return Node;
1032 }
1033
1034 /* There is a need to make free space */
1036
1037 if (!DphRoot->pUnusedNodeListHead && !Node)
1038 {
1039 /* Retry with a smaller request */
1040 Size = PAGE_SIZE;
1042 }
1043
1044 if (!DphRoot->pUnusedNodeListHead)
1045 {
1046 if (Node)
1047 {
1049 Ptr = Node->pVirtualBlock;
1050 SizeVirtual = Node->nVirtualBlockSize;
1051 }
1052 else
1053 {
1054 /* No free space, need to alloc a new VM block */
1056 SizeVirtual = DPH_RESERVE_SIZE;
1058
1059 if (!NT_SUCCESS(Status))
1060 {
1061 /* Retry with a smaller size */
1062 SizeVirtual = 0x10000;
1064 if (!NT_SUCCESS(Status)) return NULL;
1065 }
1066 }
1067
1068 /* VM is allocated at this point, set protection */
1070 if (!NT_SUCCESS(Status))
1071 {
1072 if (Node)
1073 {
1075 }
1076 else
1077 {
1078 //RtlpDphFreeVm();
1079 ASSERT(FALSE);
1080 }
1081
1082 return NULL;
1083 }
1084
1085 /* Zero the memory */
1086 if (Node) RtlZeroMemory(Ptr, Size);
1087
1088 /* Add a new pool based on this VM */
1089 RtlpDphAddNewPool(DphRoot, Node, Ptr, Size, TRUE);
1090
1091 if (Node)
1092 {
1093 if (Node->nVirtualBlockSize > Size)
1094 {
1095 Node->pVirtualBlock += Size;
1096 Node->nVirtualBlockSize -= Size;
1097
1099 }
1100 else
1101 {
1103 }
1104 }
1105 else
1106 {
1107 /* The new VM block was just allocated a few code lines ago,
1108 so initialize it */
1110 Node->pVirtualBlock = Ptr;
1111 Node->nVirtualBlockSize = SizeVirtual;
1113
1115 Node->pVirtualBlock = (PUCHAR)Ptr + Size;
1116 Node->nVirtualBlockSize = SizeVirtual - Size;
1118
1119 /* Coalesce them into available list */
1121 }
1122 }
1123
1124 return RtlpDphTakeNodeFromUnusedList(DphRoot);
1125}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
union node Node
Definition: types.h:1255
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
Status
Definition: gdiplustypes.h:25
VOID NTAPI RtlpDphRemoveFromAvailableList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:589
NTSTATUS NTAPI RtlpDphProtectVm(PVOID Base, SIZE_T Size, ULONG Protection)
Definition: heappage.c:421
VOID NTAPI RtlpDphReturnNodeToUnusedList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:573
#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:829
VOID NTAPI RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:684
PDPH_HEAP_BLOCK NTAPI RtlpDphFindAvailableMemory(PDPH_HEAP_ROOT DphRoot, SIZE_T Size, BOOLEAN Grow)
Definition: heappage.c:908
#define DPH_POOL_SIZE
Definition: heappage.c:135
NTSTATUS NTAPI RtlpDphAllocateVm(PVOID *Base, SIZE_T Size, ULONG Type, ULONG Protection)
Definition: heappage.c:346
VOID NTAPI RtlpDphPlaceOnVirtualList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:535
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define MEM_COMMIT
Definition: nt_native.h:1313
#define PAGE_NOACCESS
Definition: nt_native.h:1302
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by RtlpDphGrowVirtual(), RtlpPageHeapAllocate(), and RtlpPageHeapCreate().

◆ RtlpDphAllocateNodeForTable()

PVOID NTAPI RtlpDphAllocateNodeForTable ( IN PRTL_AVL_TABLE  Table,
IN CLONG  ByteSize 
)

Definition at line 1206 of file heappage.c.

1208{
1209 PDPH_HEAP_BLOCK pBlock;
1210 PDPH_HEAP_ROOT DphRoot;
1211
1212 /* This mega-assert comes from a text search over Windows 2003 checked binary of ntdll.dll */
1213 ASSERT((ULONG_PTR)(((PRTL_BALANCED_LINKS)0)+1) + sizeof(PUCHAR) == ByteSize);
1214
1215 /* Get pointer to the containing heap root record */
1216 DphRoot = CONTAINING_RECORD(Table, DPH_HEAP_ROOT, BusyNodesTable);
1217 pBlock = DphRoot->NodeToAllocate;
1218
1219 DphRoot->NodeToAllocate = NULL;
1220 ASSERT(pBlock);
1221
1222 return &(pBlock->TableLinks);
1223}
ASMGENDATA Table[]
Definition: genincdata.c:61
RTL_BALANCED_LINKS TableLinks
Definition: heappage.c:47
PDPH_HEAP_BLOCK NodeToAllocate
Definition: heappage.c:75
uint32_t ULONG_PTR
Definition: typedefs.h:65
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:412

Referenced by RtlpPageHeapCreate().

◆ RtlpDphAllocateVm()

NTSTATUS NTAPI RtlpDphAllocateVm ( PVOID Base,
SIZE_T  Size,
ULONG  Type,
ULONG  Protection 
)

Definition at line 346 of file heappage.c.

347{
349 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
350 Base,
351 0,
352 &Size,
353 Type,
354 Protection);
355 DPRINT("Page heap: AllocVm (%p, %Ix, %lx) status %lx\n", Base, Size, Type, Status);
356 /* Check for failures */
357 if (!NT_SUCCESS(Status))
358 {
359 if (Type == MEM_RESERVE)
360 {
363 {
364 DPRINT1("Page heap: AllocVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
366 return Status;
367 }
368 }
369 else
370 {
373 {
374 DPRINT1("Page heap: AllocVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
376 return Status;
377 }
378 }
379 }
380
381 return Status;
382}
Type
Definition: Type.h:7
#define DPRINT1
Definition: precomp.h:8
LONG RtlpDphAllocFails
Definition: heappage.c:129
#define DPH_BREAK_ON_COMMIT_FAIL
Definition: heappage.c:140
ULONG RtlpDphBreakOptions
Definition: heappage.c:184
LONG RtlpDphCounter
Definition: heappage.c:128
#define DPH_BREAK_ON_RESERVE_FAIL
Definition: heappage.c:139
NTSYSAPI void WINAPI DbgBreakPoint(void)
long __cdecl _InterlockedIncrement(_Interlocked_operand_ long volatile *_Addend)
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2478
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define MEM_RESERVE
Definition: nt_native.h:1314
#define DPRINT
Definition: sndvol32.h:73

Referenced by RtlpDphAllocateNode(), RtlpDphGrowVirtual(), and RtlpPageHeapCreate().

◆ RtlpDphCoalesceFreeIntoAvailable()

VOID NTAPI RtlpDphCoalesceFreeIntoAvailable ( PDPH_HEAP_ROOT  DphRoot,
ULONG  LeaveOnFreeList 
)

Definition at line 798 of file heappage.c.

800{
802 SIZE_T FreeAllocations = DphRoot->nFreeAllocations;
803
804 /* Make sure requested size is not too big */
805 ASSERT(FreeAllocations >= LeaveOnFreeList);
806
807 DPRINT("RtlpDphCoalesceFreeIntoAvailable(%p %lu)\n", DphRoot, LeaveOnFreeList);
808
809 while (Node)
810 {
811 FreeAllocations--;
812 if (FreeAllocations < LeaveOnFreeList) break;
813
814 /* Get the next pointer, because it may be changed after following two calls */
815 Next = Node->pNextAlloc;
816
817 /* Remove it from the free list */
819
820 /* And put into the available */
822
823 /* Go to the next node */
824 Node = Next;
825 }
826}
VOID NTAPI RtlpDphRemoveFromFreeList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node, PDPH_HEAP_BLOCK Prev)
Definition: heappage.c:660
STDMETHOD() Next(THIS_ ULONG celt, IAssociationElement *pElement, ULONG *pceltFetched) PURE
ULONG nFreeAllocations
Definition: heappage.c:81
PDPH_HEAP_BLOCK pFreeAllocationListHead
Definition: heappage.c:79

Referenced by RtlpDphFindAvailableMemory().

◆ RtlpDphCoalesceNodeIntoAvailable()

VOID NTAPI RtlpDphCoalesceNodeIntoAvailable ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 684 of file heappage.c.

686{
687 PDPH_HEAP_BLOCK NodeEntry, PrevNode = NULL, NextNode;
688 PLIST_ENTRY AvailListHead;
689 PLIST_ENTRY CurEntry;
690
691 DPRINT("RtlpDphCoalesceNodeIntoAvailable(%p %p)\n", DphRoot, Node);
692
693 /* Update heap counters */
694 DphRoot->nAvailableAllocationBytesCommitted += Node->nVirtualBlockSize;
695 DphRoot->nAvailableAllocations++;
696
697 /* Find where to put this node according to its virtual address */
698 AvailListHead = &DphRoot->AvailableAllocationHead;
699
700 /* Find a point where to insert an available node */
701 CurEntry = AvailListHead->Flink;
702
703 while (CurEntry != AvailListHead)
704 {
705 NodeEntry = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
706 if (NodeEntry->pVirtualBlock >= Node->pVirtualBlock)
707 {
708 PrevNode = NodeEntry;
709 break;
710 }
711 CurEntry = CurEntry->Flink;
712 }
713
714 if (!PrevNode)
715 {
716 /* That means either this list is empty, or we should add to the head of it */
717 InsertHeadList(AvailListHead, &Node->AvailableEntry);
718 }
719 else
720 {
721 /* Check the previous node and merge if possible */
722 if (PrevNode->pVirtualBlock + PrevNode->nVirtualBlockSize == Node->pVirtualBlock)
723 {
724 /* Check they actually belong to the same virtual memory block */
726 MEMORY_BASIC_INFORMATION MemoryBasicInfo;
727
730 Node->pVirtualBlock,
732 &MemoryBasicInfo,
733 sizeof(MemoryBasicInfo),
734 NULL);
735
736 /* There is no way this can fail, we committed this memory! */
738
739 if ((PUCHAR)MemoryBasicInfo.AllocationBase <= PrevNode->pVirtualBlock)
740 {
741 /* They are adjacent, and from the same VM region. - merge! */
742 PrevNode->nVirtualBlockSize += Node->nVirtualBlockSize;
744 DphRoot->nAvailableAllocations--;
745
746 Node = PrevNode;
747 }
748 else
749 {
750 /* Insert after PrevNode */
751 InsertTailList(&PrevNode->AvailableEntry, &Node->AvailableEntry);
752 }
753 }
754 else
755 {
756 /* Insert after PrevNode */
757 InsertTailList(&PrevNode->AvailableEntry, &Node->AvailableEntry);
758 }
759
760 /* Now check the next entry after our one */
761 if (Node->AvailableEntry.Flink != AvailListHead)
762 {
763 NextNode = CONTAINING_RECORD(Node->AvailableEntry.Flink, DPH_HEAP_BLOCK, AvailableEntry);
764 /* Node is not at the tail of the list, check if it's adjacent */
765 if (Node->pVirtualBlock + Node->nVirtualBlockSize == NextNode->pVirtualBlock)
766 {
767 /* Check they actually belong to the same virtual memory block */
769 MEMORY_BASIC_INFORMATION MemoryBasicInfo;
770
773 NextNode->pVirtualBlock,
775 &MemoryBasicInfo,
776 sizeof(MemoryBasicInfo),
777 NULL);
778
779 /* There is no way this can fail, we committed this memory! */
781
782 if ((PUCHAR)MemoryBasicInfo.AllocationBase <= Node->pVirtualBlock)
783 {
784 /* They are adjacent - merge! */
785 Node->nVirtualBlockSize += NextNode->nVirtualBlockSize;
786
787 /* Remove next entry from the list and put it into unused entries list */
788 RemoveEntryList(&NextNode->AvailableEntry);
789 RtlpDphReturnNodeToUnusedList(DphRoot, NextNode);
790 DphRoot->nAvailableAllocations--;
791 }
792 }
793 }
794 }
795}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
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)
@ MemoryBasicInformation
Definition: mmtypes.h:183
LIST_ENTRY AvailableEntry
Definition: heappage.c:46
LIST_ENTRY AvailableAllocationHead
Definition: heappage.c:84
SIZE_T nAvailableAllocationBytesCommitted
Definition: heappage.c:86
ULONG nAvailableAllocations
Definition: heappage.c:85
#define ZwCurrentProcess()

Referenced by RtlpDphAllocateNode(), RtlpDphCoalesceFreeIntoAvailable(), RtlpDphGrowVirtual(), and RtlpPageHeapCreate().

◆ RtlpDphCompareNodeForTable()

RTL_GENERIC_COMPARE_RESULTS NTAPI RtlpDphCompareNodeForTable ( IN PRTL_AVL_TABLE  Table,
IN PVOID  FirstStruct,
IN PVOID  SecondStruct 
)

Definition at line 1187 of file heappage.c.

1190{
1191 ULONG_PTR FirstBlock, SecondBlock;
1192
1193 FirstBlock = *((ULONG_PTR *)FirstStruct);
1194 SecondBlock = *((ULONG_PTR *)SecondStruct);
1195
1196 if (FirstBlock < SecondBlock)
1197 return GenericLessThan;
1198 else if (FirstBlock > SecondBlock)
1199 return GenericGreaterThan;
1200
1201 return GenericEqual;
1202}
_IRQL_requires_same_ _In_ PVOID _In_ PVOID SecondStruct
Definition: rtltypes.h:403
_IRQL_requires_same_ _In_ PVOID FirstStruct
Definition: rtltypes.h:402
@ GenericLessThan
Definition: rtltypes.h:389
@ GenericEqual
Definition: rtltypes.h:391
@ GenericGreaterThan
Definition: rtltypes.h:390

Referenced by RtlpPageHeapCreate().

◆ RtlpDphEnterCriticalSection()

VOID NTAPI RtlpDphEnterCriticalSection ( PDPH_HEAP_ROOT  DphRoot,
ULONG  Flags 
)

Definition at line 265 of file heappage.c.

266{
268 {
269 /* More complex scenario */
270 if (!RtlTryEnterHeapLock(DphRoot->HeapCritSect, TRUE))
271 {
272 if (!DphRoot->nRemoteLockAcquired)
273 {
274 DPRINT1("multithreaded access in HEAP_NO_SERIALIZE heap\n");
276
277 /* Clear out the no serialize flag */
278 DphRoot->HeapFlags &= ~HEAP_NO_SERIALIZE;
279 }
280
281 /* Enter the heap's critical section */
283 }
284 }
285 else
286 {
287 /* Just enter the heap's critical section */
289 }
290}
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:110
BOOLEAN NTAPI RtlTryEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:119
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
PHEAP_LOCK HeapCritSect
Definition: heappage.c:66
ULONG nRemoteLockAcquired
Definition: heappage.c:67

Referenced by RtlpDphPreProcessing(), and RtlpPageHeapLock().

◆ RtlpDphFindAvailableMemory()

PDPH_HEAP_BLOCK NTAPI RtlpDphFindAvailableMemory ( PDPH_HEAP_ROOT  DphRoot,
SIZE_T  Size,
BOOLEAN  Grow 
)

Definition at line 908 of file heappage.c.

911{
914
915 /* Find an available best fitting node */
917
918 /* If that didn't work, try to search a smaller one in the loop */
919 while (!Node)
920 {
921 /* Break if the free list becomes too small */
922 if (DphRoot->nFreeAllocations <= DPH_FREE_LIST_MINIMUM) break;
923
924 /* Calculate a new free list size */
925 NewSize = DphRoot->nFreeAllocations >> 2;
927
928 /* Coalesce free into available */
930
931 /* Try to find an available best fitting node again */
933 }
934
935 /* If Node is NULL, then we could fix the situation only by
936 growing the available VM size */
937 if (!Node && Grow)
938 {
939 /* Grow VM size, if it fails - return failure directly */
940 if (!RtlpDphGrowVirtual(DphRoot, Size)) return NULL;
941
942 /* Try to find an available best fitting node again */
944
945 if (!Node)
946 {
947 /* Do the last attempt: coalesce all free into available (if Size fits there) */
949 {
950 /* Coalesce free into available */
952
953 /* Try to find an available best fitting node again */
955 }
956 }
957 }
958
959 /* Return node we found */
960 return Node;
961}
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
#define DPH_FREE_LIST_MINIMUM
Definition: heappage.c:136
PDPH_HEAP_BLOCK NTAPI RtlpDphSearchAvailableMemoryListForBestFit(PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
Definition: heappage.c:876
BOOLEAN NTAPI RtlpDphGrowVirtual(PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
Definition: heappage.c:1128
VOID NTAPI RtlpDphCoalesceFreeIntoAvailable(PDPH_HEAP_ROOT DphRoot, ULONG LeaveOnFreeList)
Definition: heappage.c:798
SIZE_T nFreeAllocationBytesCommitted
Definition: heappage.c:82

Referenced by RtlpDphAllocateNode(), and RtlpPageHeapAllocate().

◆ RtlpDphFindBusyMemory()

PDPH_HEAP_BLOCK NTAPI RtlpDphFindBusyMemory ( PDPH_HEAP_ROOT  DphRoot,
PVOID  pUserMem 
)

Definition at line 964 of file heappage.c.

966{
968 PVOID Ptr;
969
970 /* Lookup busy block in AVL */
971 Ptr = RtlLookupElementGenericTableAvl(&DphRoot->BusyNodesTable, &pUserMem);
972 if (!Ptr) return NULL;
973
974 /* Restore pointer to the heap block */
975 Node = CONTAINING_RECORD(Ptr, DPH_HEAP_BLOCK, pUserAllocation);
976 ASSERT(Node->pUserAllocation == pUserMem);
977 return Node;
978}
RTL_AVL_TABLE BusyNodesTable
Definition: heappage.c:74
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlLookupElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)

Referenced by RtlpDebugPageHeapValidate(), RtlpPageHeapFree(), RtlpPageHeapGetUserInfo(), RtlpPageHeapReAllocate(), RtlpPageHeapSetUserFlags(), RtlpPageHeapSetUserValue(), and RtlpPageHeapSize().

◆ RtlpDphFreeDelayedBlocksFromHeap()

VOID NTAPI RtlpDphFreeDelayedBlocksFromHeap ( PDPH_HEAP_ROOT  DphRoot,
PHEAP  NormalHeap 
)

Definition at line 1258 of file heappage.c.

1260{
1261 PLIST_ENTRY Current, Next;
1262 PDPH_BLOCK_INFORMATION BlockInfo;
1263 ULONG ValidationInfo;
1264
1265 /* The original routine seems to use a temporary SList to put blocks to be freed,
1266 then it releases the lock and frees the blocks. But let's make it simple for now */
1267
1268 /* Acquire the delayed free queue lock */
1270
1271 /* Traverse the list */
1273 while (Current != &RtlpDphDelayedFreeQueue)
1274 {
1275 /* Get the next entry pointer */
1276 Next = Current->Flink;
1277
1278 BlockInfo = CONTAINING_RECORD(Current, DPH_BLOCK_INFORMATION, FreeQueue);
1279
1280 /* Check if it belongs to the same heap */
1281 if (BlockInfo->Heap == DphRoot)
1282 {
1283 /* Remove it from the list */
1284 RemoveEntryList(Current);
1285
1286 /* Reset its heap to NULL */
1287 BlockInfo->Heap = NULL;
1288
1289 if (!RtlpDphIsNormalFreeHeapBlock(BlockInfo + 1, &ValidationInfo, TRUE))
1290 {
1291 RtlpDphReportCorruptedBlock(DphRoot, 10, BlockInfo + 1, ValidationInfo);
1292 }
1293
1294 /* Decrement counters */
1297
1298 /* Free the normal heap */
1299 RtlFreeHeap(NormalHeap, 0, BlockInfo);
1300 }
1301
1302 /* Move to the next one */
1303 Current = Next;
1304 }
1305
1306 /* Release the delayed free queue lock */
1308}
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
NTSTATUS NTAPI RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:135
BOOLEAN NTAPI RtlpDphIsNormalFreeHeapBlock(PVOID Block, PULONG ValidationInformation, BOOLEAN CheckFillers)
Definition: heappage.c:1484
ULONG RtlpDphNumberOfDelayedFreeBlocks
Definition: heappage.c:125
SIZE_T RtlpDphMemoryUsedByDelayedFreeBlocks
Definition: heappage.c:124
LIST_ENTRY RtlpDphDelayedFreeQueue
Definition: heappage.c:122
PHEAP_LOCK RtlpDphDelayedFreeQueueLock
Definition: heappage.c:121
VOID NTAPI RtlpDphReportCorruptedBlock(_In_ PDPH_HEAP_ROOT DphRoot, _In_ ULONG Reserved, _In_ PVOID Block, _In_ ULONG ValidationInfo)
Definition: heappage.c:1330

Referenced by RtlpPageHeapDestroy().

◆ RtlpDphFreeNodeForTable()

VOID NTAPI RtlpDphFreeNodeForTable ( IN PRTL_AVL_TABLE  Table,
IN PVOID  Buffer 
)

Definition at line 1227 of file heappage.c.

1229{
1230 /* Nothing */
1231}

Referenced by RtlpPageHeapCreate().

◆ RtlpDphFreeVm()

NTSTATUS NTAPI RtlpDphFreeVm ( PVOID  Base,
SIZE_T  Size,
ULONG  Type 
)

Definition at line 385 of file heappage.c.

386{
388
389 /* Free the memory */
391 DPRINT("Page heap: FreeVm (%p, %Ix, %lx) status %lx\n", Base, Size, Type, Status);
392 /* Log/report failures */
393 if (!NT_SUCCESS(Status))
394 {
395 if (Type == MEM_RELEASE)
396 {
399 {
400 DPRINT1("Page heap: FreeVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
402 return Status;
403 }
404 }
405 else
406 {
409 {
410 DPRINT1("Page heap: FreeVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
412 return Status;
413 }
414 }
415 }
416
417 return Status;
418}
NTSTATUS NTAPI RtlpSecMemFreeVirtualMemory(HANDLE Process, PVOID *Base, PSIZE_T Size, ULONG Type)
Definition: heappage.c:323
#define DPH_BREAK_ON_RELEASE_FAIL
Definition: heappage.c:141
LONG RtlpDphReleaseFails
Definition: heappage.c:130
LONG RtlpDphFreeFails
Definition: heappage.c:131
#define DPH_BREAK_ON_FREE_FAIL
Definition: heappage.c:142
#define MEM_RELEASE
Definition: nt_native.h:1316

Referenced by RtlpPageHeapDestroy().

◆ RtlpDphGetBlockSizeFromCorruptedBlock()

ULONG NTAPI RtlpDphGetBlockSizeFromCorruptedBlock ( PVOID  Block)

Definition at line 250 of file heappage.c.

251{
252 PDPH_BLOCK_INFORMATION BlockInfo;
253 BlockInfo = (PDPH_BLOCK_INFORMATION)Block - 1;
254
255 /* Check stamps */
256 if (BlockInfo->StartStamp != DPH_FILL_START_STAMP_1 && BlockInfo->StartStamp != DPH_FILL_START_STAMP_2)
257 {
258 return 0;
259 }
260
261 return BlockInfo->RequestedSize;
262}
#define DPH_FILL_START_STAMP_2
Definition: heappage.c:157
#define DPH_FILL_START_STAMP_1
Definition: heappage.c:156
struct _DPH_BLOCK_INFORMATION * PDPH_BLOCK_INFORMATION

Referenced by RtlpDphReportCorruptedBlock().

◆ RtlpDphGrowVirtual()

BOOLEAN NTAPI RtlpDphGrowVirtual ( PDPH_HEAP_ROOT  DphRoot,
SIZE_T  Size 
)

Definition at line 1128 of file heappage.c.

1130{
1131 PDPH_HEAP_BLOCK Node, AvailableNode;
1132 PVOID Base = NULL;
1133 SIZE_T VirtualSize;
1135
1136 /* Start with allocating a couple of nodes */
1137 Node = RtlpDphAllocateNode(DphRoot);
1138 if (!Node) return FALSE;
1139
1140 AvailableNode = RtlpDphAllocateNode(DphRoot);
1141 if (!AvailableNode)
1142 {
1143 /* Free the allocated node and return failure */
1145 return FALSE;
1146 }
1147
1148 /* Calculate size of VM to allocate by rounding it up */
1149 Size = ROUND_UP(Size, 0xFFFF);
1150 VirtualSize = Size;
1151 if (Size < DPH_RESERVE_SIZE)
1152 VirtualSize = DPH_RESERVE_SIZE;
1153
1154 /* Allocate the virtual memory */
1155 // FIXME: Shouldn't it be MEM_RESERVE with later committing?
1157 if (!NT_SUCCESS(Status))
1158 {
1159 /* Retry again with a smaller size */
1160 VirtualSize = Size;
1162 if (!NT_SUCCESS(Status))
1163 {
1164 /* Free the allocated node and return failure */
1166 RtlpDphReturnNodeToUnusedList(DphRoot, AvailableNode);
1167 return FALSE;
1168 }
1169 }
1170
1171 /* Set up our two nodes describing this VM */
1172 Node->pVirtualBlock = Base;
1173 Node->nVirtualBlockSize = VirtualSize;
1174 AvailableNode->pVirtualBlock = Base;
1175 AvailableNode->nVirtualBlockSize = VirtualSize;
1176
1177 /* Add them to virtual and available lists respectively */
1179 RtlpDphCoalesceNodeIntoAvailable(DphRoot, AvailableNode);
1180
1181 /* Return success */
1182 return TRUE;
1183}
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
PDPH_HEAP_BLOCK NTAPI RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:1018

Referenced by RtlpDphFindAvailableMemory().

◆ RtlpDphHeapFromPointer()

PVOID NTAPI RtlpDphHeapFromPointer ( PDPH_HEAP_ROOT  DphHeap)

Definition at line 244 of file heappage.c.

245{
246 return ((PUCHAR)DphHeap) - PAGE_SIZE;
247}

Referenced by RtlpDphReportCorruptedBlock().

◆ RtlpDphInitializeDelayedFreeQueue()

NTSTATUS NTAPI RtlpDphInitializeDelayedFreeQueue ( VOID  )

Definition at line 1234 of file heappage.c.

1235{
1237
1239 if (!NT_SUCCESS(Status))
1240 {
1241 // TODO: Log this error!
1242 DPRINT1("Failure initializing delayed free queue critical section\n");
1243 return Status;
1244 }
1245
1246 /* Initialize lists */
1249
1250 /* Reset counters */
1253
1254 return Status;
1255}
NTSTATUS NTAPI RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
Definition: libsupp.c:128
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
SLIST_HEADER RtlpDphDelayedTemporaryPushList
Definition: heappage.c:123
NTSYSAPI VOID NTAPI RtlInitializeSListHead(_Out_ PSLIST_HEADER ListHead)
Definition: slist.c:25

Referenced by RtlpDphProcessStartupInitialization().

◆ RtlpDphInternalValidatePageHeap()

VOID NTAPI RtlpDphInternalValidatePageHeap ( PDPH_HEAP_ROOT  DphRoot,
PVOID  Address,
ULONG  Value 
)

Definition at line 1318 of file heappage.c.

1319{
1321}
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15

Referenced by RtlpPageHeapAllocate(), RtlpPageHeapCreate(), RtlpPageHeapFree(), and RtlpPageHeapReAllocate().

◆ RtlpDphIsNormalFreeHeapBlock()

BOOLEAN NTAPI RtlpDphIsNormalFreeHeapBlock ( PVOID  Block,
PULONG  ValidationInformation,
BOOLEAN  CheckFillers 
)

Definition at line 1484 of file heappage.c.

1487{
1488 ASSERT(ValidationInformation != NULL);
1489
1491 *ValidationInformation = 0;
1492 return TRUE;
1493}

Referenced by RtlpDphFreeDelayedBlocksFromHeap().

◆ RtlpDphIsPageHeapBlock()

BOOLEAN NTAPI RtlpDphIsPageHeapBlock ( PDPH_HEAP_ROOT  DphRoot,
PVOID  Block,
PULONG  ValidationInformation,
BOOLEAN  CheckFillers 
)

Definition at line 1421 of file heappage.c.

1425{
1426 PDPH_BLOCK_INFORMATION BlockInfo;
1427 BOOLEAN SomethingWrong = FALSE;
1428 PUCHAR Byte, Start, End;
1429
1430 ASSERT(ValidationInformation != NULL);
1431 *ValidationInformation = 0;
1432
1433 // _SEH2_TRY {
1434 BlockInfo = (PDPH_BLOCK_INFORMATION)Block - 1;
1435
1436 /* Check stamps */
1437 if (BlockInfo->StartStamp != DPH_FILL_START_STAMP_1)
1438 {
1439 *ValidationInformation |= DPH_VALINFO_BAD_START_STAMP;
1440 SomethingWrong = TRUE;
1441
1442 /* Check if it has an alloc/free mismatch */
1443 if (BlockInfo->StartStamp == DPH_FILL_START_STAMP_2)
1444 {
1445 /* Notify respectively */
1446 *ValidationInformation = 0x101;
1447 }
1448 }
1449
1450 if (BlockInfo->EndStamp != DPH_FILL_END_STAMP_1)
1451 {
1452 *ValidationInformation |= DPH_VALINFO_BAD_END_STAMP;
1453 SomethingWrong = TRUE;
1454 }
1455
1456 /* Check root heap pointer */
1457 if (BlockInfo->Heap != DphRoot)
1458 {
1459 *ValidationInformation |= DPH_VALINFO_BAD_POINTER;
1460 SomethingWrong = TRUE;
1461 }
1462
1463 /* Check other fillers if requested */
1464 if (CheckFillers)
1465 {
1466 /* Check space after the block */
1467 Start = (PUCHAR)Block + BlockInfo->RequestedSize;
1468 End = (PUCHAR)ROUND_UP(Start, PAGE_SIZE);
1469 for (Byte = Start; Byte < End; Byte++)
1470 {
1471 if (*Byte != DPH_FILL_SUFFIX)
1472 {
1473 *ValidationInformation |= DPH_VALINFO_BAD_SUFFIX_PATTERN;
1474 SomethingWrong = TRUE;
1475 break;
1476 }
1477 }
1478 }
1479
1480 return (SomethingWrong == FALSE);
1481}
unsigned char Byte
Definition: zlib.h:37
return pTarget Start()
#define DPH_VALINFO_BAD_END_STAMP
Definition: heappage.c:165
#define DPH_VALINFO_BAD_POINTER
Definition: heappage.c:166
#define DPH_VALINFO_BAD_START_STAMP
Definition: heappage.c:164
#define DPH_FILL_SUFFIX
Definition: heappage.c:160
#define DPH_VALINFO_BAD_SUFFIX_PATTERN
Definition: heappage.c:168
#define DPH_FILL_END_STAMP_1
Definition: heappage.c:158

Referenced by RtlpPageHeapDestroy(), RtlpPageHeapFree(), and RtlpPageHeapReAllocate().

◆ RtlpDphLeaveCriticalSection()

VOID NTAPI RtlpDphLeaveCriticalSection ( PDPH_HEAP_ROOT  DphRoot)

Definition at line 293 of file heappage.c.

294{
295 /* Just leave the heap's critical section */
297}

Referenced by RtlpDphPostProcessing(), and RtlpPageHeapUnlock().

◆ RtlpDphNormalHeapValidate()

BOOLEAN NTAPI RtlpDphNormalHeapValidate ( PDPH_HEAP_ROOT  DphRoot,
ULONG  Flags,
PVOID  BaseAddress 
)

Definition at line 2402 of file heappage.c.

2405{
2407 if (!BaseAddress)
2408 {
2409 /* Validate all normal heap */
2410 return RtlValidateHeap(DphRoot->NormalHeap, Flags, NULL);
2411 }
2412
2413 // FIXME: Check is this a normal heap block
2414 /*if (!RtlpDphIsNormalHeapBlock(DphRoot, BaseAddress, &ValidationInfo))
2415 {
2416 }*/
2417
2418 return RtlValidateHeap(DphRoot->NormalHeap, Flags, BlockInfo);
2419}
NTSYSAPI BOOLEAN WINAPI RtlValidateHeap(HANDLE, ULONG, LPCVOID)
PVOID NormalHeap
Definition: heappage.c:100

Referenced by RtlpDebugPageHeapValidate().

◆ RtlpDphPlaceOnBusyList()

VOID NTAPI RtlpDphPlaceOnBusyList ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  DphNode 
)

Definition at line 471 of file heappage.c.

472{
473 BOOLEAN NewElement;
474 PVOID AddressUserData;
475
476 DPRINT("RtlpDphPlaceOnBusyList(%p %p)\n", DphRoot, DphNode);
477
478 /* Add it to the AVL busy nodes table */
479 DphRoot->NodeToAllocate = DphNode;
480 AddressUserData = RtlInsertElementGenericTableAvl(&DphRoot->BusyNodesTable,
481 &DphNode->pUserAllocation,
482 sizeof(ULONG_PTR),
483 &NewElement);
484
485 ASSERT(AddressUserData == &DphNode->pUserAllocation);
486 ASSERT(NewElement == TRUE);
487
488 /* Update heap counters */
489 DphRoot->nBusyAllocations++;
492}
PUCHAR pUserAllocation
Definition: heappage.c:49
SIZE_T nVirtualAccessSize
Definition: heappage.c:52
ULONG nBusyAllocations
Definition: heappage.c:76
SIZE_T nBusyAllocationBytesCommitted
Definition: heappage.c:77
SIZE_T nBusyAllocationBytesAccessible
Definition: heappage.c:91
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement)

Referenced by RtlpPageHeapAllocate(), and RtlpPageHeapReAllocate().

◆ RtlpDphPlaceOnFreeList()

VOID NTAPI RtlpDphPlaceOnFreeList ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 495 of file heappage.c.

496{
497 DPRINT("RtlpDphPlaceOnFreeList(%p %p)\n", DphRoot, Node);
498
499 /* Node is being added to the tail of the list */
500 Node->pNextAlloc = NULL;
501
502 /* Add it to the tail of the linked list */
503 if (DphRoot->pFreeAllocationListTail)
505 else
506 DphRoot->pFreeAllocationListHead = Node;
507 DphRoot->pFreeAllocationListTail = Node;
508
509 /* Update byte counts taking in account this new node */
510 DphRoot->nFreeAllocations++;
511 DphRoot->nFreeAllocationBytesCommitted += Node->nVirtualBlockSize;
512}
PDPH_HEAP_BLOCK pFreeAllocationListTail
Definition: heappage.c:80

Referenced by RtlpPageHeapFree(), and RtlpPageHeapReAllocate().

◆ RtlpDphPlaceOnPoolList()

VOID NTAPI RtlpDphPlaceOnPoolList ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 515 of file heappage.c.

516{
517 DPRINT("RtlpDphPlaceOnPoolList(%p %p)\n", DphRoot, Node);
518
519 /* Node is being added to the tail of the list */
520 Node->pNextAlloc = NULL;
521
522 /* Add it to the tail of the linked list */
523 if (DphRoot->pNodePoolListTail)
525 else
526 DphRoot->pNodePoolListHead = Node;
527 DphRoot->pNodePoolListTail = Node;
528
529 /* Update byte counts taking in account this new node */
530 DphRoot->nNodePools++;
531 DphRoot->nNodePoolBytes += Node->nVirtualBlockSize;
532}
PDPH_HEAP_BLOCK pNodePoolListTail
Definition: heappage.c:93
SIZE_T nNodePoolBytes
Definition: heappage.c:95
PDPH_HEAP_BLOCK pNodePoolListHead
Definition: heappage.c:92
ULONG nNodePools
Definition: heappage.c:94

Referenced by RtlpDphAddNewPool(), and RtlpPageHeapCreate().

◆ RtlpDphPlaceOnVirtualList()

VOID NTAPI RtlpDphPlaceOnVirtualList ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 535 of file heappage.c.

536{
537 DPRINT("RtlpDphPlaceOnVirtualList(%p %p)\n", DphRoot, Node);
538
539 /* Add it to the head of the virtual list */
540 Node->pNextAlloc = DphRoot->pVirtualStorageListHead;
541 if (!DphRoot->pVirtualStorageListHead)
542 DphRoot->pVirtualStorageListTail = Node;
543 DphRoot->pVirtualStorageListHead = Node;
544
545 /* Update byte counts taking in account this new node */
546 DphRoot->nVirtualStorageRanges++;
547 DphRoot->nVirtualStorageBytes += Node->nVirtualBlockSize;
548}
PDPH_HEAP_BLOCK pVirtualStorageListTail
Definition: heappage.c:70
PDPH_HEAP_BLOCK pVirtualStorageListHead
Definition: heappage.c:69
ULONG nVirtualStorageRanges
Definition: heappage.c:71
SIZE_T nVirtualStorageBytes
Definition: heappage.c:72

Referenced by RtlpDphAllocateNode(), RtlpDphGrowVirtual(), and RtlpPageHeapCreate().

◆ RtlpDphPointerFromHandle()

PVOID NTAPI RtlpDphPointerFromHandle ( PVOID  Handle)

Definition at line 227 of file heappage.c.

228{
229 PHEAP NormalHeap = (PHEAP)Handle;
231
232 if (NormalHeap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
233 {
234 if (DphHeap->Signature == DPH_SIGNATURE)
235 return DphHeap;
236 }
237
238 DPRINT1("heap handle with incorrect signature\n");
240 return NULL;
241}
struct _HEAP * PHEAP
ULONG Handle
Definition: gdb_input.c:15
struct _DPH_HEAP_ROOT * PDPH_HEAP_ROOT
#define DPH_SIGNATURE
Definition: heappage.c:176
#define HEAP_FLAG_PAGE_ALLOCS
Definition: rtltypes.h:160
ULONG Signature
Definition: heappage.c:64
Definition: heap.c:52
ULONG ForceFlags
Definition: heap.h:227

Referenced by RtlpDebugPageHeapValidate(), RtlpPageHeapAllocate(), RtlpPageHeapDestroy(), RtlpPageHeapFree(), RtlpPageHeapGetUserInfo(), RtlpPageHeapLock(), RtlpPageHeapReAllocate(), RtlpPageHeapSetUserFlags(), RtlpPageHeapSetUserValue(), RtlpPageHeapSize(), and RtlpPageHeapUnlock().

◆ RtlpDphPostProcessing()

VOID NTAPI RtlpDphPostProcessing ( PDPH_HEAP_ROOT  DphRoot)

Definition at line 309 of file heappage.c.

310{
311 if (!DphRoot) return;
312
314 {
315 /* FIXME: Validate integrity, internal lists if necessary */
316 }
317
318 /* Release the lock */
320}
VOID NTAPI RtlpDphLeaveCriticalSection(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:293
#define DPH_DEBUG_INTERNAL_VALIDATE
Definition: heappage.c:147
ULONG RtlpDphDebugOptions
Definition: heappage.c:185

Referenced by RtlpDebugPageHeapValidate(), RtlpPageHeapAllocate(), RtlpPageHeapFree(), RtlpPageHeapGetUserInfo(), RtlpPageHeapReAllocate(), RtlpPageHeapSetUserFlags(), RtlpPageHeapSetUserValue(), and RtlpPageHeapSize().

◆ RtlpDphPreProcessing()

VOID NTAPI RtlpDphPreProcessing ( PDPH_HEAP_ROOT  DphRoot,
ULONG  Flags 
)

Definition at line 301 of file heappage.c.

302{
304
305 /* FIXME: Validate integrity, internal lists if necessary */
306}
VOID NTAPI RtlpDphEnterCriticalSection(PDPH_HEAP_ROOT DphRoot, ULONG Flags)
Definition: heappage.c:265

Referenced by RtlpDebugPageHeapValidate(), RtlpPageHeapAllocate(), RtlpPageHeapDestroy(), RtlpPageHeapFree(), RtlpPageHeapGetUserInfo(), RtlpPageHeapReAllocate(), RtlpPageHeapSetUserFlags(), RtlpPageHeapSetUserValue(), and RtlpPageHeapSize().

◆ RtlpDphProcessStartupInitialization()

NTSTATUS NTAPI RtlpDphProcessStartupInitialization ( VOID  )

Definition at line 1496 of file heappage.c.

1497{
1499 PTEB Teb = NtCurrentTeb();
1500
1501 /* Initialize the DPH heap list and its critical section */
1504 if (!NT_SUCCESS(Status))
1505 {
1506 ASSERT(FALSE);
1507 return Status;
1508 }
1509
1510 /* Initialize delayed-free queue */
1512 if (!NT_SUCCESS(Status)) return Status;
1513
1514 /* Initialize the target dlls string */
1517
1518 /* Per-process DPH init is done */
1520
1521 DPRINT1("Page heap: pid 0x%p: page heap enabled with flags 0x%X.\n",
1523
1524 return Status;
1525}
WCHAR RtlpDphTargetDlls[512]
Definition: heappage.c:111
PHEAP_LOCK RtlpDphPageHeapListLock
Definition: heappage.c:116
ULONG RtlpDphGlobalFlags
Definition: heappage.c:108
LIST_ENTRY RtlpDphPageHeapList
Definition: heappage.c:113
BOOLEAN RtlpDphPageHeapListInitialized
Definition: heappage.c:114
UNICODE_STRING RtlpDphTargetDllsUnicode
Definition: heappage.c:118
NTSTATUS NTAPI RtlpDphInitializeDelayedFreeQueue(VOID)
Definition: heappage.c:1234
NTSTATUS NTAPI RtlpDphTargetDllsLogicInitialize(VOID)
Definition: heappage.c:1311
#define NtCurrentTeb
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
HANDLE UniqueProcess
Definition: compat.h:825
Definition: compat.h:836
CLIENT_ID ClientId
Definition: compat.h:839

Referenced by RtlpPageHeapCreate().

◆ RtlpDphProtectVm()

NTSTATUS NTAPI RtlpDphProtectVm ( PVOID  Base,
SIZE_T  Size,
ULONG  Protection 
)

Definition at line 421 of file heappage.c.

422{
424 ULONG OldProtection;
425
426 /* Change protection */
427 Status = ZwProtectVirtualMemory(NtCurrentProcess(), &Base, &Size, Protection, &OldProtection);
428
429 /* Log/report failures */
430 if (!NT_SUCCESS(Status))
431 {
434 {
435 DPRINT1("Page heap: ProtectVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Protection, Status);
437 return Status;
438 }
439 }
440
441 return Status;
442}
#define DPH_BREAK_ON_PROTECT_FAIL
Definition: heappage.c:143
LONG RtlpDphProtectFails
Definition: heappage.c:132
NTSYSAPI NTSTATUS NTAPI ZwProtectVirtualMemory(_In_ HANDLE ProcessHandle, _In_ PVOID *BaseAddress, _In_ SIZE_T *NumberOfBytesToProtect, _In_ ULONG NewAccessProtection, _Out_ PULONG OldAccessProtection)

Referenced by RtlpDphAllocateNode(), RtlpDphSetProtectionBeforeUse(), RtlpPageHeapCreate(), RtlpPageHeapFree(), and RtlpPageHeapReAllocate().

◆ RtlpDphRaiseException()

VOID NTAPI RtlpDphRaiseException ( NTSTATUS  Status)

Definition at line 211 of file heappage.c.

212{
213 EXCEPTION_RECORD Exception;
214
215 /* Initialize exception record */
216 Exception.ExceptionCode = Status;
218 Exception.ExceptionFlags = 0;
219 Exception.ExceptionRecord = NULL;
220 Exception.NumberParameters = 0;
221
222 /* Raise the exception */
223 RtlRaiseException(&Exception);
224}
VOID NTAPI RtlpDphRaiseException(NTSTATUS Status)
Definition: heappage.c:211
NTSYSAPI VOID NTAPI RtlRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord)
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
DWORD ExceptionCode
Definition: compat.h:208
DWORD NumberParameters
Definition: compat.h:212
DWORD ExceptionFlags
Definition: compat.h:209
PVOID ExceptionAddress
Definition: compat.h:211

Referenced by RtlpDphRaiseException(), RtlpPageHeapAllocate(), and RtlpPageHeapReAllocate().

◆ RtlpDphRemoveFromAvailableList()

VOID NTAPI RtlpDphRemoveFromAvailableList ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 589 of file heappage.c.

591{
592 /* Make sure Adjacency list pointers are biased */
593 //ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Flink));
594 //ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Blink));
595
596 DPRINT("RtlpDphRemoveFromAvailableList(%p %p)\n", DphRoot, Node);
597
598 /* Check if it is in the list */
599#if 0
600 {
601 PLIST_ENTRY CurEntry;
602 PDPH_HEAP_BLOCK NodeEntry;
604
605 /* Find where to put this node according to its virtual address */
606 CurEntry = DphRoot->AvailableAllocationHead.Flink;
607
608 while (CurEntry != &DphRoot->AvailableAllocationHead)
609 {
610 NodeEntry = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
611
612 if (NodeEntry == Node)
613 {
614 Found = TRUE;
615 break;
616 }
617
618 CurEntry = CurEntry->Flink;
619 }
620
621 if (!Found)
622 {
623 DPRINT1("Trying to remove non-existing in availlist node!\n");
625 }
626 }
627#endif
628
629 /* Remove it from the list */
630 RemoveEntryList(&Node->AvailableEntry);
631
632 /* Decrease heap counters */
633 DphRoot->nAvailableAllocations--;
634 DphRoot->nAvailableAllocationBytesCommitted -= Node->nVirtualBlockSize;
635
636 /* Remove bias from the AdjacencyEntry pointer */
637 Node->AdjacencyEntry.Flink = (PLIST_ENTRY)POINTER_REMOVE_BIAS(Node->AdjacencyEntry.Flink);
638 Node->AdjacencyEntry.Blink = (PLIST_ENTRY)POINTER_REMOVE_BIAS(Node->AdjacencyEntry.Blink);
639}
return Found
Definition: dirsup.c:1270
#define POINTER_REMOVE_BIAS(ptr)
Definition: heappage.c:180
struct _LIST_ENTRY * PLIST_ENTRY

Referenced by RtlpDphAllocateNode(), and RtlpPageHeapAllocate().

◆ RtlpDphRemoveFromBusyList()

VOID NTAPI RtlpDphRemoveFromBusyList ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 642 of file heappage.c.

644{
645 BOOLEAN ElementPresent;
646
647 DPRINT("RtlpDphRemoveFromBusyList(%p %p)\n", DphRoot, Node);
648
649 /* Delete it from busy nodes table */
650 ElementPresent = RtlDeleteElementGenericTableAvl(&DphRoot->BusyNodesTable, &Node->pUserAllocation);
651 ASSERT(ElementPresent == TRUE);
652
653 /* Update counters */
654 DphRoot->nBusyAllocations--;
655 DphRoot->nBusyAllocationBytesCommitted -= Node->nVirtualBlockSize;
656 DphRoot->nBusyAllocationBytesAccessible -= Node->nVirtualAccessSize;
657}
NTSYSAPI BOOLEAN NTAPI RtlDeleteElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)

Referenced by RtlpPageHeapFree(), and RtlpPageHeapReAllocate().

◆ RtlpDphRemoveFromFreeList()

VOID NTAPI RtlpDphRemoveFromFreeList ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node,
PDPH_HEAP_BLOCK  Prev 
)

Definition at line 660 of file heappage.c.

663{
665
666 DPRINT("RtlpDphRemoveFromFreeList(%p %p %p)\n", DphRoot, Node, Prev);
667
668 /* Detach it from the list */
669 Next = Node->pNextAlloc;
670 if (DphRoot->pFreeAllocationListHead == Node)
671 DphRoot->pFreeAllocationListHead = Next;
672 if (DphRoot->pFreeAllocationListTail == Node)
673 DphRoot->pFreeAllocationListTail = Prev;
674 if (Prev) Prev->pNextAlloc = Next;
675
676 /* Decrease heap counters */
677 DphRoot->nFreeAllocations--;
678 DphRoot->nFreeAllocationBytesCommitted -= Node->nVirtualBlockSize;
679
680 Node->StackTrace = NULL;
681}

Referenced by RtlpDphCoalesceFreeIntoAvailable().

◆ RtlpDphReportCorruptedBlock()

VOID NTAPI RtlpDphReportCorruptedBlock ( _In_ PDPH_HEAP_ROOT  DphRoot,
_In_ ULONG  Reserved,
_In_ PVOID  Block,
_In_ ULONG  ValidationInfo 
)

Definition at line 1330 of file heappage.c.

1335{
1337 DPH_BLOCK_INFORMATION SafeInfo = {0};
1338
1339 DPRINT1("Corrupted heap block %p\n", Block);
1340
1341 _SEH2_TRY
1342 {
1343 PDPH_BLOCK_INFORMATION BlockInfo = (PDPH_BLOCK_INFORMATION)Block - 1;
1344 RtlCopyMemory(&SafeInfo, BlockInfo, sizeof(SafeInfo));
1345 }
1347 {
1348 DPRINT1("ERROR: Could not read DPH_BLOCK_INFORMATION\n");
1349 RtlZeroMemory(&SafeInfo, sizeof(SafeInfo));
1350 }
1351 _SEH2_END;
1352
1353 if (ValidationInfo & DPH_VALINFO_CORRUPTED_AFTER_FREE)
1354 {
1356 APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_HEADER, "block corrupted after having been freed",
1357 RtlpDphHeapFromPointer(DphRoot), "Heap handle", Block, "Heap block", (PVOID)Size, "Block size", 0, "");
1358 }
1359
1360 if (ValidationInfo & DPH_VALINFO_ALREADY_FREED)
1361 {
1363 APPLICATION_VERIFIER_DOUBLE_FREE, "block already freed", RtlpDphHeapFromPointer(DphRoot), "Heap handle",
1364 Block, "Heap block", Size, "Block size", 0, "");
1365 }
1366
1367 if (ValidationInfo & DPH_VALINFO_BAD_INFIX_PATTERN)
1368 {
1370 APPLICATION_VERIFIER_CORRUPTED_FREED_HEAP_BLOCK, "corrupted infix pattern for freed block",
1371 RtlpDphHeapFromPointer(DphRoot), "Heap handle", Block, "Heap block", Size, "Block size", 0, "");
1372 }
1373
1374 if (ValidationInfo & DPH_VALINFO_BAD_POINTER)
1375 {
1377 APPLICATION_VERIFIER_SWITCHED_HEAP_HANDLE, "corrupted heap pointer or using wrong heap",
1378 RtlpDphHeapFromPointer(DphRoot), "Heap handle used", Block, "Heap block", Size, "Block size",
1379 SafeInfo.Heap, "Actual heap handle");
1380 }
1381
1382 if (ValidationInfo & DPH_VALINFO_BAD_SUFFIX_PATTERN)
1383 {
1386 "Heap handle used", Block, "Heap block", Size, "Block size", 0, "");
1387 }
1388
1389 if (ValidationInfo & DPH_VALINFO_BAD_PREFIX_PATTERN)
1390 {
1393 "Heap handle used", Block, "Heap block", Size, "Block size", 0, "");
1394 }
1395
1396 if (ValidationInfo & DPH_VALINFO_BAD_START_STAMP)
1397 {
1400 "Heap handle used", Block, "Heap block", Size, "Block size", (PVOID)(ULONG_PTR)SafeInfo.StartStamp,
1401 "Corrupted start stamp");
1402 }
1403
1404 if (ValidationInfo & DPH_VALINFO_BAD_END_STAMP)
1405 {
1408 "Heap handle used", Block, "Heap block", Size, "Block size", (PVOID)(ULONG_PTR)SafeInfo.EndStamp,
1409 "Corrupted end stamp");
1410 }
1411
1412 if (ValidationInfo & DPH_VALINFO_EXCEPTION)
1413 {
1415 APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_EXCEPTION_RAISED_FOR_HEADER, "exception raised while verifying block",
1416 RtlpDphHeapFromPointer(DphRoot), "Heap handle used", Block, "Heap block", Size, "Block size", 0, "");
1417 }
1418}
ULONG NTAPI RtlpDphGetBlockSizeFromCorruptedBlock(PVOID Block)
Definition: heappage.c:250
#define DPH_VALINFO_EXCEPTION
Definition: heappage.c:169
#define DPH_VALINFO_ALREADY_FREED
Definition: heappage.c:172
#define DPH_VALINFO_CORRUPTED_AFTER_FREE
Definition: heappage.c:173
#define DPH_VALINFO_BAD_PREFIX_PATTERN
Definition: heappage.c:167
PVOID NTAPI RtlpDphHeapFromPointer(PDPH_HEAP_ROOT DphHeap)
Definition: heappage.c:244
#define DPH_VALINFO_BAD_INFIX_PATTERN
Definition: heappage.c:171
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define VERIFIER_STOP(Code, Msg, Val1, Desc1, Val2, Desc2, Val3, Desc3, Val4, Desc4)
Definition: verifier.h:171
#define APPLICATION_VERIFIER_CORRUPTED_FREED_HEAP_BLOCK
Definition: verifier.h:107
#define APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_PREFIX
Definition: verifier.h:111
#define APPLICATION_VERIFIER_SWITCHED_HEAP_HANDLE
Definition: verifier.h:99
#define APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_START_STAMP
Definition: verifier.h:109
#define APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_END_STAMP
Definition: verifier.h:110
#define APPLICATION_VERIFIER_DOUBLE_FREE
Definition: verifier.h:100
#define APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_EXCEPTION_RAISED_FOR_HEADER
Definition: verifier.h:104
#define APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_SUFFIX
Definition: verifier.h:108
#define APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_HEADER
Definition: verifier.h:106

Referenced by RtlpDphFreeDelayedBlocksFromHeap(), RtlpPageHeapDestroy(), RtlpPageHeapFree(), and RtlpPageHeapReAllocate().

◆ RtlpDphReturnNodeToUnusedList()

VOID NTAPI RtlpDphReturnNodeToUnusedList ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 573 of file heappage.c.

575{
576 DPRINT("RtlpDphReturnNodeToUnusedList(%p, %p)\n", DphRoot, Node);
577
578 /* Add it back to the head of the unused list */
579 Node->pNextAlloc = DphRoot->pUnusedNodeListHead;
580 if (!DphRoot->pUnusedNodeListHead)
581 DphRoot->pUnusedNodeListTail = Node;
582 DphRoot->pUnusedNodeListHead = Node;
583
584 /* Increase amount of unused nodes */
585 DphRoot->nUnusedNodes++;
586}

Referenced by RtlpDphAllocateNode(), RtlpDphCoalesceNodeIntoAvailable(), and RtlpDphGrowVirtual().

◆ RtlpDphSearchAvailableMemoryListForBestFit()

PDPH_HEAP_BLOCK NTAPI RtlpDphSearchAvailableMemoryListForBestFit ( PDPH_HEAP_ROOT  DphRoot,
SIZE_T  Size 
)

Definition at line 876 of file heappage.c.

878{
879 PLIST_ENTRY CurEntry;
880 PDPH_HEAP_BLOCK Node, NodeFound = NULL;
881
882 CurEntry = DphRoot->AvailableAllocationHead.Flink;
883
884 while (CurEntry != &DphRoot->AvailableAllocationHead)
885 {
886 /* Get the current available node */
887 Node = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
888
889 /* Check its size */
890 if (Node->nVirtualBlockSize >= Size)
891 {
892 NodeFound = Node;
893 break;
894 }
895
896 /* Move to the next available entry */
897 CurEntry = CurEntry->Flink;
898 }
899
900 /* Make sure Adjacency list pointers are biased */
901 //ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Flink));
902 //ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Blink));
903
904 return NodeFound;
905}

Referenced by RtlpDphFindAvailableMemory().

◆ RtlpDphSetProtectionAfterUse()

NTSTATUS NTAPI RtlpDphSetProtectionAfterUse ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 1002 of file heappage.c.

1003{
1004 ASSERT((Node->nVirtualAccessSize + PAGE_SIZE) <= Node->nVirtualBlockSize);
1005
1006 // FIXME: Bring stuff here
1007 if (DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN)
1008 {
1009 }
1010 else
1011 {
1012 }
1013
1014 return STATUS_SUCCESS;
1015}
#define DPH_EXTRA_CHECK_UNDERRUN
Definition: heappage.c:152
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG ExtraFlags
Definition: heappage.c:98

◆ RtlpDphSetProtectionBeforeUse()

NTSTATUS NTAPI RtlpDphSetProtectionBeforeUse ( PDPH_HEAP_ROOT  DphRoot,
PUCHAR  VirtualBlock,
ULONG  UserSize 
)

Definition at line 981 of file heappage.c.

982{
983 ULONG Protection;
984 PVOID Base;
985
987 {
988 Base = VirtualBlock + PAGE_SIZE;
989 }
990 else
991 {
992 Base = VirtualBlock;
993 }
994
995 // FIXME: It should be different, but for now it's fine
996 Protection = PAGE_READWRITE;
997
998 return RtlpDphProtectVm(Base, UserSize, Protection);
999}

Referenced by RtlpPageHeapAllocate().

◆ RtlpDphShouldAllocateInPageHeap()

BOOLEAN NTAPI RtlpDphShouldAllocateInPageHeap ( PDPH_HEAP_ROOT  DphRoot,
SIZE_T  Size 
)

Definition at line 1528 of file heappage.c.

1530{
1531 //UNIMPLEMENTED;
1532 /* Always use page heap for now */
1533 return TRUE;
1534}

Referenced by RtlpPageHeapAllocate(), and RtlpPageHeapReAllocate().

◆ RtlpDphTakeNodeFromUnusedList()

PDPH_HEAP_BLOCK NTAPI RtlpDphTakeNodeFromUnusedList ( PDPH_HEAP_ROOT  DphRoot)

Definition at line 551 of file heappage.c.

552{
555
556 DPRINT("RtlpDphTakeNodeFromUnusedList(%p), ret %p\n", DphRoot, Node);
557
558 /* Take the first entry */
559 if (!Node) return NULL;
560
561 /* Remove that entry (Node) from the list */
562 Next = Node->pNextAlloc;
563 if (DphRoot->pUnusedNodeListHead == Node) DphRoot->pUnusedNodeListHead = Next;
564 if (DphRoot->pUnusedNodeListTail == Node) DphRoot->pUnusedNodeListTail = NULL;
565
566 /* Decrease amount of unused nodes */
567 DphRoot->nUnusedNodes--;
568
569 return Node;
570}

Referenced by RtlpDphAddNewPool(), and RtlpDphAllocateNode().

◆ RtlpDphTargetDllsLogicInitialize()

NTSTATUS NTAPI RtlpDphTargetDllsLogicInitialize ( VOID  )

Definition at line 1311 of file heappage.c.

1312{
1314 return STATUS_SUCCESS;
1315}

Referenced by RtlpDphProcessStartupInitialization().

◆ RtlpDphVerifyIntegrity()

VOID NTAPI RtlpDphVerifyIntegrity ( PDPH_HEAP_ROOT  DphRoot)

Definition at line 1324 of file heappage.c.

1325{
1327}

Referenced by RtlpPageHeapAllocate().

◆ RtlpDphWritePageHeapBlockInformation()

BOOLEAN NTAPI RtlpDphWritePageHeapBlockInformation ( PDPH_HEAP_ROOT  DphRoot,
PVOID  UserAllocation,
SIZE_T  Size,
SIZE_T  UserSize 
)

Definition at line 445 of file heappage.c.

446{
447 PDPH_BLOCK_INFORMATION BlockInfo;
448 PUCHAR FillPtr;
449
450 /* Get pointer to the block info structure */
451 BlockInfo = (PDPH_BLOCK_INFORMATION)UserAllocation - 1;
452
453 /* Set up basic fields */
454 BlockInfo->Heap = DphRoot;
455 BlockInfo->ActualSize = UserSize;
456 BlockInfo->RequestedSize = Size;
458 BlockInfo->EndStamp = DPH_FILL_END_STAMP_1;
459
460 /* Fill with a pattern */
461 FillPtr = (PUCHAR)UserAllocation + Size;
462 RtlFillMemory(FillPtr, ROUND_UP(FillPtr, PAGE_SIZE) - (ULONG_PTR)FillPtr, DPH_FILL_SUFFIX);
463
464 /* FIXME: Check if logging stack traces is turned on */
465 //if (DphRoot->ExtraFlags &
466
467 return TRUE;
468}
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599

Referenced by RtlpPageHeapAllocate().

◆ RtlpPageHeapAllocate()

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

Definition at line 1766 of file heappage.c.

1769{
1770 PDPH_HEAP_ROOT DphRoot;
1771 PDPH_HEAP_BLOCK AvailableNode, BusyNode;
1772 BOOLEAN Biased = FALSE;
1773 ULONG AllocateSize, AccessSize;
1775 SIZE_T UserActualSize;
1776 PVOID Ptr;
1777
1778 /* Check requested size */
1779 if (Size > 0x7FF00000)
1780 {
1781 DPRINT1("extreme size request\n");
1782
1783 /* Generate an exception if needed */
1785
1786 return NULL;
1787 }
1788
1789 /* Unbias the pointer if necessary */
1790 if (IS_BIASED_POINTER(HeapPtr))
1791 {
1792 HeapPtr = (PVOID)POINTER_REMOVE_BIAS(HeapPtr);
1793 Biased = TRUE;
1794 }
1795
1796 /* Get a pointer to the heap root */
1797 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
1798 if (!DphRoot) return NULL;
1799
1800 /* Acquire the heap lock */
1801 RtlpDphPreProcessing(DphRoot, Flags);
1802
1803 /* Perform internal validation if specified by flags */
1805 {
1807 }
1808
1809 /* Add heap flags */
1810 Flags |= DphRoot->HeapFlags;
1811
1812 if (!Biased && !RtlpDphShouldAllocateInPageHeap(DphRoot, Size))
1813 {
1814 /* Perform allocation from a normal heap */
1815 ASSERT(FALSE);
1816 }
1817
1818 /* Perform heap integrity check if specified by flags */
1820 {
1821 RtlpDphVerifyIntegrity(DphRoot);
1822 }
1823
1824 /* Calculate sizes */
1825 AccessSize = ROUND_UP(Size + sizeof(DPH_BLOCK_INFORMATION), PAGE_SIZE);
1826 AllocateSize = AccessSize + PAGE_SIZE;
1827
1828 // FIXME: Move RtlpDphAllocateNode(DphRoot) to this place
1829 AvailableNode = RtlpDphFindAvailableMemory(DphRoot, AllocateSize, TRUE);
1830 if (!AvailableNode)
1831 {
1832 DPRINT1("Page heap: Unable to allocate virtual memory\n");
1833 DbgBreakPoint();
1834
1835 /* Release the lock */
1836 RtlpDphPostProcessing(DphRoot);
1837
1838 return NULL;
1839 }
1840 ASSERT(AvailableNode->nVirtualBlockSize >= AllocateSize);
1841
1842 /* Set protection */
1844 AvailableNode->pVirtualBlock,
1845 AccessSize);
1846 if (!NT_SUCCESS(Status))
1847 {
1848 ASSERT(FALSE);
1849 }
1850
1851 /* Save available node pointer */
1852 Ptr = AvailableNode->pVirtualBlock;
1853
1854 /* Check node's size */
1855 if (AvailableNode->nVirtualBlockSize > AllocateSize)
1856 {
1857 /* The block contains too much free space, reduce it */
1858 AvailableNode->pVirtualBlock += AllocateSize;
1859 AvailableNode->nVirtualBlockSize -= AllocateSize;
1860 DphRoot->nAvailableAllocationBytesCommitted -= AllocateSize;
1861
1862 /* Allocate a new node which will be our busy node */
1863 BusyNode = RtlpDphAllocateNode(DphRoot);
1864 ASSERT(BusyNode != NULL);
1865 BusyNode->pVirtualBlock = Ptr;
1866 BusyNode->nVirtualBlockSize = AllocateSize;
1867 }
1868 else
1869 {
1870 /* The block's size fits exactly */
1871 RtlpDphRemoveFromAvailableList(DphRoot, AvailableNode);
1872 BusyNode = AvailableNode;
1873 }
1874
1875 /* Calculate actual user size */
1876 if (DphRoot->HeapFlags & HEAP_NO_ALIGNMENT)
1877 UserActualSize = Size;
1878 else
1879 UserActualSize = ROUND_UP(Size, 8);
1880
1881 /* Set up the block */
1882 BusyNode->nVirtualAccessSize = AccessSize;
1883 BusyNode->nUserActualSize = UserActualSize;
1884 BusyNode->nUserRequestedSize = Size;
1885
1886 if (DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN)
1887 BusyNode->pUserAllocation = BusyNode->pVirtualBlock + PAGE_SIZE;
1888 else
1889 BusyNode->pUserAllocation = BusyNode->pVirtualBlock + BusyNode->nVirtualAccessSize - UserActualSize;
1890
1891 BusyNode->UserValue = NULL;
1893
1894 // FIXME: Don't forget about stack traces if such flag was set
1895 BusyNode->StackTrace = NULL;
1896
1897 /* Place it on busy list */
1898 RtlpDphPlaceOnBusyList(DphRoot, BusyNode);
1899
1900 /* Zero or patter-fill memory depending on flags */
1901 if (Flags & HEAP_ZERO_MEMORY)
1903 else
1905
1906 /* Write DPH info */
1907 if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
1908 {
1910 BusyNode->pUserAllocation,
1911 Size,
1912 AccessSize);
1913 }
1914
1915 /* Finally allocation is done, perform validation again if required */
1917 {
1919 }
1920
1921 /* Release the lock */
1922 RtlpDphPostProcessing(DphRoot);
1923
1924 DPRINT("Allocated user block pointer: %p\n", BusyNode->pUserAllocation);
1925
1926 /* Return pointer to user allocation */
1927 return BusyNode->pUserAllocation;
1928}
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
BOOLEAN NTAPI RtlpDphWritePageHeapBlockInformation(PDPH_HEAP_ROOT DphRoot, PVOID UserAllocation, SIZE_T Size, SIZE_T UserSize)
Definition: heappage.c:445
BOOLEAN NTAPI RtlpDphShouldAllocateInPageHeap(PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
Definition: heappage.c:1528
VOID NTAPI RtlpDphVerifyIntegrity(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:1324
#define IS_BIASED_POINTER(ptr)
Definition: heappage.c:179
VOID NTAPI RtlpDphPlaceOnBusyList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK DphNode)
Definition: heappage.c:471
#define DPH_FILL_INFIX
Definition: heappage.c:161
VOID NTAPI RtlpDphInternalValidatePageHeap(PDPH_HEAP_ROOT DphRoot, PVOID Address, ULONG Value)
Definition: heappage.c:1318
NTSTATUS NTAPI RtlpDphSetProtectionBeforeUse(PDPH_HEAP_ROOT DphRoot, PUCHAR VirtualBlock, ULONG UserSize)
Definition: heappage.c:981
#define HEAP_NO_ALIGNMENT
Definition: rtltypes.h:163
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
#define HEAP_SETTABLE_USER_FLAGS
Definition: nt_native.h:1708
SIZE_T nUserActualSize
Definition: heappage.c:54
ULONG UserFlags
Definition: heappage.c:56
SIZE_T nUserRequestedSize
Definition: heappage.c:53
PRTL_TRACE_BLOCK StackTrace
Definition: heappage.c:57
PVOID UserValue
Definition: heappage.c:55

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 1537 of file heappage.c.

1543{
1544 PVOID Base = NULL;
1545 PHEAP HeapPtr;
1546 PDPH_HEAP_ROOT DphRoot;
1547 PDPH_HEAP_BLOCK DphNode;
1548 ULONG MemSize;
1550 LARGE_INTEGER PerfCounter;
1551
1552 /* Check for a DPH bypass flag */
1553 if ((ULONG_PTR)Parameters == -1) return NULL;
1554
1555 /* Make sure no user-allocated stuff was provided */
1556 if (Addr || Lock) return NULL;
1557
1558 /* Allocate minimum amount of virtual memory */
1559 MemSize = DPH_RESERVE_SIZE;
1561 if (!NT_SUCCESS(Status))
1562 {
1563 ASSERT(FALSE);
1564 return NULL;
1565 }
1566
1567 /* Set protection */
1569 if (!NT_SUCCESS(Status))
1570 {
1571 //RtlpDphFreeVm(Base, 0, 0, 0);
1572 ASSERT(FALSE);
1573 return NULL;
1574 }
1575
1576 /* Start preparing the 1st page. Fill it with the default filler */
1578
1579 /* Set flags in the "HEAP" structure */
1580 HeapPtr = (PHEAP)Base;
1581 HeapPtr->Flags = Flags | HEAP_FLAG_PAGE_ALLOCS;
1583
1584 /* Set 1st page to read only now */
1586 if (!NT_SUCCESS(Status))
1587 {
1588 ASSERT(FALSE);
1589 return NULL;
1590 }
1591
1592 /* 2nd page is the real DPH root block */
1593 DphRoot = (PDPH_HEAP_ROOT)((PCHAR)Base + PAGE_SIZE);
1594
1595 /* Initialize the DPH root */
1596 DphRoot->Signature = DPH_SIGNATURE;
1597 DphRoot->HeapFlags = Flags;
1598 DphRoot->HeapCritSect = (PHEAP_LOCK)((PCHAR)DphRoot + DPH_POOL_SIZE);
1599 DphRoot->ExtraFlags = RtlpDphGlobalFlags;
1600
1601 ZwQueryPerformanceCounter(&PerfCounter, NULL);
1602 DphRoot->Seed = PerfCounter.LowPart;
1603
1606
1607 /* Create a normal heap for this paged heap */
1608 DphRoot->NormalHeap = RtlCreateHeap(Flags, NULL, TotalSize, CommitSize, NULL, (PRTL_HEAP_PARAMETERS)-1);
1609 if (!DphRoot->NormalHeap)
1610 {
1611 ASSERT(FALSE);
1612 return NULL;
1613 }
1614
1615 /* 3rd page: a pool for DPH allocations */
1616 RtlpDphAddNewPool(DphRoot, NULL, DphRoot + 1, DPH_POOL_SIZE - sizeof(DPH_HEAP_ROOT), FALSE);
1617
1618 /* Allocate internal heap blocks. For the root */
1619 DphNode = RtlpDphAllocateNode(DphRoot);
1620 ASSERT(DphNode != NULL);
1621 DphNode->pVirtualBlock = (PUCHAR)DphRoot;
1623 RtlpDphPlaceOnPoolList(DphRoot, DphNode);
1624
1625 /* For the memory we allocated as a whole */
1626 DphNode = RtlpDphAllocateNode(DphRoot);
1627 ASSERT(DphNode != NULL);
1628 DphNode->pVirtualBlock = Base;
1629 DphNode->nVirtualBlockSize = MemSize;
1630 RtlpDphPlaceOnVirtualList(DphRoot, DphNode);
1631
1632 /* For the remaining part */
1633 DphNode = RtlpDphAllocateNode(DphRoot);
1634 ASSERT(DphNode != NULL);
1636 DphNode->nVirtualBlockSize = MemSize - (2*PAGE_SIZE + DPH_POOL_SIZE);
1637 RtlpDphCoalesceNodeIntoAvailable(DphRoot, DphNode);
1638
1639 //DphRoot->CreateStackTrace = RtlpDphLogStackTrace(1);
1640
1641 /* Initialize AVL-based busy nodes table */
1646 NULL);
1647
1648 /* Initialize per-process startup info */
1650
1651 /* Acquire the heap list lock */
1653
1654 /* Insert this heap to the tail of the global list */
1656
1657 /* Note we increased the size of the list */
1659
1660 /* Release the heap list lock */
1662
1664 {
1665 DPRINT1("Page heap: process 0x%p created heap @ %p (%p, flags 0x%X)\n",
1667 DphRoot->NormalHeap, DphRoot->ExtraFlags);
1668 }
1669
1670 /* Perform internal validation if required */
1673
1674 return (PUCHAR)DphRoot - PAGE_SIZE;
1675}
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
#define PAGE_READONLY
Definition: compat.h:138
VOID NTAPI RtlpDphFreeNodeForTable(IN PRTL_AVL_TABLE Table, IN PVOID Buffer)
Definition: heappage.c:1227
#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:1206
NTSTATUS NTAPI RtlpDphProcessStartupInitialization(VOID)
Definition: heappage.c:1496
#define DPH_DEBUG_VERBOSE
Definition: heappage.c:148
RTL_GENERIC_COMPARE_RESULTS NTAPI RtlpDphCompareNodeForTable(IN PRTL_AVL_TABLE Table, IN PVOID FirstStruct, IN PVOID SecondStruct)
Definition: heappage.c:1187
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
NTSYSAPI NTSTATUS NTAPI ZwQueryPerformanceCounter(_Out_ PLARGE_INTEGER Counter, _Out_opt_ PLARGE_INTEGER Frequency)
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:406
struct _HEAP_LOCK * PHEAP_LOCK
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)
ULONG Seed
Definition: heappage.c:99
LIST_ENTRY NextHeap
Definition: heappage.c:97
ULONG Flags
Definition: heap.h:226
char * PCHAR
Definition: typedefs.h:51
ULONG LowPart
Definition: typedefs.h:106
_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
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151

Referenced by AVrfpDebugPageHeapCreate(), and RtlCreateHeap().

◆ RtlpPageHeapDestroy()

PVOID NTAPI RtlpPageHeapDestroy ( HANDLE  HeapPtr)

Definition at line 1678 of file heappage.c.

1679{
1680 PDPH_HEAP_ROOT DphRoot;
1681 PVOID Ptr;
1683 PHEAP NormalHeap;
1684 ULONG Value;
1685
1686 /* Check if it's not a process heap */
1687 if (HeapPtr == RtlGetProcessHeap())
1688 {
1690 "attempt to destroy process heap",
1691 HeapPtr, "Heap handle",
1692 0, "",
1693 0, "",
1694 0, "");
1695 return NULL;
1696 }
1697
1698 /* Get pointer to the heap root */
1699 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
1700 if (!DphRoot) return NULL;
1701
1702 RtlpDphPreProcessing(DphRoot, DphRoot->HeapFlags);
1703
1704 /* Get the pointer to the normal heap */
1705 NormalHeap = DphRoot->NormalHeap;
1706
1707 /* Free the delayed-free blocks */
1708 RtlpDphFreeDelayedBlocksFromHeap(DphRoot, NormalHeap);
1709
1710 /* Go through the busy blocks */
1712
1713 while (Ptr)
1714 {
1715 Node = CONTAINING_RECORD(Ptr, DPH_HEAP_BLOCK, pUserAllocation);
1716 if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
1717 {
1718 if (!RtlpDphIsPageHeapBlock(DphRoot, Node->pUserAllocation, &Value, TRUE))
1719 {
1720 RtlpDphReportCorruptedBlock(DphRoot, 3, Node->pUserAllocation, Value);
1721 }
1722 }
1723
1724 AVrfInternalHeapFreeNotification(Node->pUserAllocation, Node->nUserRequestedSize);
1725
1726 /* Go to the next node */
1728 }
1729
1730 /* Acquire the global heap list lock */
1732
1733 /* Remove the entry and decrement the global counter */
1734 RemoveEntryList(&DphRoot->NextHeap);
1736
1737 /* Release the global heap list lock */
1739
1740 /* Leave and delete this heap's critical section */
1743
1744 /* Now go through all virtual list nodes and release the VM */
1745 Node = DphRoot->pVirtualStorageListHead;
1746 while (Node)
1747 {
1748 Next = Node->pNextAlloc;
1749 /* Release the memory without checking result */
1750 RtlpDphFreeVm(Node->pVirtualBlock, 0, MEM_RELEASE);
1751 Node = Next;
1752 }
1753
1754 /* Destroy the normal heap */
1755 RtlDestroyHeap(NormalHeap);
1756
1757 /* Report success */
1759 DPRINT1("Page heap: process 0x%p destroyed heap @ %p (%p)\n",
1760 NtCurrentTeb()->ClientId.UniqueProcess, HeapPtr, NormalHeap);
1761
1762 return NULL;
1763}
NTSTATUS NTAPI RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:103
NTSTATUS NTAPI RtlpDphFreeVm(PVOID Base, SIZE_T Size, ULONG Type)
Definition: heappage.c:385
VOID NTAPI AVrfInternalHeapFreeNotification(PVOID AllocationBase, SIZE_T AllocationSize)
Definition: verifier.c:364
BOOLEAN NTAPI RtlpDphIsPageHeapBlock(PDPH_HEAP_ROOT DphRoot, PVOID Block, PULONG ValidationInformation, BOOLEAN CheckFillers)
Definition: heappage.c:1421
VOID NTAPI RtlpDphFreeDelayedBlocksFromHeap(PDPH_HEAP_ROOT DphRoot, PHEAP NormalHeap)
Definition: heappage.c:1258
NTSYSAPI PVOID NTAPI RtlDestroyHeap(IN PVOID HeapHandle)
#define APPLICATION_VERIFIER_DESTROY_PROCESS_HEAP
Definition: verifier.h:102
_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 AVrfpDebugPageHeapDestroy(), and RtlDestroyHeap().

◆ RtlpPageHeapFree()

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

Definition at line 1931 of file heappage.c.

1934{
1935 PDPH_HEAP_ROOT DphRoot;
1937 ULONG ValidationInfo;
1939
1940 /* Check for a NULL pointer freeing */
1941 if (!Ptr)
1942 {
1944 {
1945 DPRINT1("Page heap: freeing a null pointer\n");
1946 DbgBreakPoint();
1947 }
1948 return TRUE;
1949 }
1950
1951 /* Get a pointer to the heap root */
1952 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
1953 if (!DphRoot) return FALSE;
1954
1955 /* Acquire the heap lock */
1956 RtlpDphPreProcessing(DphRoot, Flags);
1957
1958 /* Perform internal validation if specified by flags */
1961
1962 /* Add heap flags */
1963 Flags |= DphRoot->HeapFlags;
1964
1965 /* Find busy memory */
1966 Node = RtlpDphFindBusyMemory(DphRoot, Ptr);
1967
1968 if (!Node)
1969 {
1970 /* This block was not found in page heap, try a normal heap instead */
1971 //RtlpDphNormalHeapFree();
1972 ASSERT(FALSE);
1973 }
1974
1975 if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
1976 {
1977 /* Check and report corrupted block */
1978 if (!RtlpDphIsPageHeapBlock(DphRoot, Ptr, &ValidationInfo, TRUE))
1979 {
1980 RtlpDphReportCorruptedBlock(DphRoot, 1, Ptr, ValidationInfo);
1981 }
1982
1983 // FIXME: Should go inside RtlpDphSetProtectionAfterUse
1984 if (Node->nVirtualAccessSize != 0)
1985 {
1986 /* Set stamps */
1987 Info = (PDPH_BLOCK_INFORMATION)Node->pUserAllocation - 1;
1988 Info->StartStamp = DPH_FILL_START_STAMP_2;
1989 Info->EndStamp = DPH_FILL_END_STAMP_2;
1990
1991 RtlpDphProtectVm(Node->pVirtualBlock, Node->nVirtualAccessSize, PAGE_NOACCESS);
1992 }
1993 }
1994 else
1995 {
1996 // FIXME: Should go inside RtlpDphSetProtectionAfterUse
1997 if (Node->nVirtualAccessSize != 0)
1998 RtlpDphProtectVm(Node->pVirtualBlock + PAGE_SIZE, Node->nVirtualAccessSize, PAGE_NOACCESS);
1999 }
2000
2001 /* Set new protection */
2002 //RtlpDphSetProtectionAfterUse(DphRoot, Node);
2003
2004 /* Remove it from the list of busy nodes */
2006
2007 /* And put it into the list of free nodes */
2008 RtlpDphPlaceOnFreeList(DphRoot, Node);
2009
2010 //if (DphRoot->ExtraFlags & DPH_EXTRA_LOG_STACK_TRACES)
2011 // Node->StackTrace = RtlpDphLogStackTrace(3);
2012 //else
2013 Node->StackTrace = NULL;
2014
2015 /* Leave the heap lock */
2016 RtlpDphPostProcessing(DphRoot);
2017
2018 /* Return success */
2019 return TRUE;
2020}
VOID NTAPI RtlpDphPlaceOnFreeList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:495
VOID NTAPI RtlpDphRemoveFromBusyList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:642
#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 2193 of file heappage.c.

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

Referenced by RtlDebugGetUserInfoHeap().

◆ RtlpPageHeapLock()

BOOLEAN NTAPI RtlpPageHeapLock ( HANDLE  HeapPtr)

Definition at line 2423 of file heappage.c.

2424{
2425 PDPH_HEAP_ROOT DphRoot;
2426
2427 /* Get pointer to the heap root */
2428 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2429 if (!DphRoot) return FALSE;
2430
2431 RtlpDphEnterCriticalSection(DphRoot, DphRoot->HeapFlags);
2432 return TRUE;
2433}

Referenced by RtlLockHeap().

◆ RtlpPageHeapReAllocate()

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

Definition at line 2023 of file heappage.c.

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

Referenced by RtlDebugReAllocateHeap().

◆ RtlpPageHeapSetUserFlags()

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

Definition at line 2276 of file heappage.c.

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

Referenced by RtlDebugSetUserFlagsHeap().

◆ RtlpPageHeapSetUserValue()

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

Definition at line 2235 of file heappage.c.

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

Referenced by RtlDebugSetUserValueHeap().

◆ RtlpPageHeapSize()

SIZE_T NTAPI RtlpPageHeapSize ( HANDLE  HeapHandle,
ULONG  Flags,
PVOID  BaseAddress 
)

Definition at line 2318 of file heappage.c.

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

Referenced by RtlDebugSizeHeap().

◆ RtlpPageHeapUnlock()

BOOLEAN NTAPI RtlpPageHeapUnlock ( HANDLE  HeapPtr)

Definition at line 2437 of file heappage.c.

2438{
2439 PDPH_HEAP_ROOT DphRoot;
2440
2441 /* Get pointer to the heap root */
2442 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2443 if (!DphRoot) return FALSE;
2444
2446 return TRUE;
2447}

Referenced by RtlUnlockHeap().

◆ RtlpSecMemFreeVirtualMemory()

NTSTATUS NTAPI RtlpSecMemFreeVirtualMemory ( HANDLE  Process,
PVOID Base,
PSIZE_T  Size,
ULONG  Type 
)

Definition at line 323 of file heappage.c.

324{
326 //PVOID *SavedBase = Base;
327 //PSIZE_T SavedSize = Size;
328
329 /* Free the memory */
330 Status = ZwFreeVirtualMemory(Process, Base, Size, Type);
331
332 /* Flush secure memory cache if needed and retry freeing */
333#if 0
336 RtlFlushSecureMemoryCache(*SavedBase, *SavedSize))
337 {
338 Status = ZwFreeVirtualMemory(NtCurrentProcess(), SavedBase, SavedSize, Type);
339 }
340#endif
341
342 return Status;
343}
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
BOOLEAN NTAPI RtlFlushSecureMemoryCache(IN PVOID MemoryCache, IN OPTIONAL SIZE_T MemoryLength)
Definition: security.c:830

Referenced by RtlpDphFreeVm().

Variable Documentation

◆ _RtlpDphDelayedFreeQueueLock

HEAP_LOCK _RtlpDphDelayedFreeQueueLock

Definition at line 120 of file heappage.c.

◆ _RtlpDphPageHeapListLock

HEAP_LOCK _RtlpDphPageHeapListLock

Definition at line 115 of file heappage.c.

◆ RtlpDphAllocFails

LONG RtlpDphAllocFails

Definition at line 129 of file heappage.c.

Referenced by RtlpDphAllocateVm().

◆ RtlpDphBreakOptions

ULONG RtlpDphBreakOptions = 0

Definition at line 184 of file heappage.c.

Referenced by RtlpDphAllocateVm(), RtlpDphFreeVm(), RtlpDphProtectVm(), and RtlpPageHeapFree().

◆ RtlpDphCounter

LONG RtlpDphCounter

Definition at line 128 of file heappage.c.

Referenced by RtlpDphAllocateVm().

◆ RtlpDphDebugOptions

◆ RtlpDphDelayedFreeQueue

LIST_ENTRY RtlpDphDelayedFreeQueue

◆ RtlpDphDelayedFreeQueueLock

PHEAP_LOCK RtlpDphDelayedFreeQueueLock = &_RtlpDphDelayedFreeQueueLock

◆ RtlpDphDelayedTemporaryPushList

SLIST_HEADER RtlpDphDelayedTemporaryPushList

Definition at line 123 of file heappage.c.

Referenced by RtlpDphInitializeDelayedFreeQueue().

◆ RtlpDphFreeFails

LONG RtlpDphFreeFails

Definition at line 131 of file heappage.c.

Referenced by RtlpDphFreeVm().

◆ RtlpDphGlobalFlags

◆ RtlpDphMemoryUsedByDelayedFreeBlocks

SIZE_T RtlpDphMemoryUsedByDelayedFreeBlocks

◆ RtlpDphNumberOfDelayedFreeBlocks

ULONG RtlpDphNumberOfDelayedFreeBlocks

◆ RtlpDphPageHeapList

LIST_ENTRY RtlpDphPageHeapList

Definition at line 113 of file heappage.c.

Referenced by RtlpDphProcessStartupInitialization(), and RtlpPageHeapCreate().

◆ RtlpDphPageHeapListInitialized

BOOLEAN RtlpDphPageHeapListInitialized

Definition at line 114 of file heappage.c.

Referenced by RtlpDphProcessStartupInitialization(), and RtlpPageHeapCreate().

◆ RtlpDphPageHeapListLength

ULONG RtlpDphPageHeapListLength

Definition at line 117 of file heappage.c.

Referenced by RtlpPageHeapCreate(), and RtlpPageHeapDestroy().

◆ RtlpDphPageHeapListLock

PHEAP_LOCK RtlpDphPageHeapListLock = &_RtlpDphPageHeapListLock

◆ RtlpDphProtectFails

LONG RtlpDphProtectFails

Definition at line 132 of file heappage.c.

Referenced by RtlpDphProtectVm().

◆ RtlpDphReleaseFails

LONG RtlpDphReleaseFails

Definition at line 130 of file heappage.c.

Referenced by RtlpDphFreeVm().

◆ RtlpDphTargetDlls

WCHAR RtlpDphTargetDlls[512]

Definition at line 111 of file heappage.c.

Referenced by RtlpDphProcessStartupInitialization().

◆ RtlpDphTargetDllsUnicode

UNICODE_STRING RtlpDphTargetDllsUnicode

Definition at line 118 of file heappage.c.

Referenced by RtlpDphProcessStartupInitialization().

◆ RtlpPageHeapDllRangeEnd

ULONG RtlpPageHeapDllRangeEnd

Definition at line 110 of file heappage.c.

◆ RtlpPageHeapDllRangeStart

ULONG RtlpPageHeapDllRangeStart

Definition at line 110 of file heappage.c.

◆ RtlpPageHeapEnabled

BOOLEAN RtlpPageHeapEnabled = FALSE

◆ RtlpPageHeapSizeRangeEnd

ULONG RtlpPageHeapSizeRangeEnd

Definition at line 109 of file heappage.c.

◆ RtlpPageHeapSizeRangeStart

ULONG RtlpPageHeapSizeRangeStart

Definition at line 109 of file heappage.c.