ReactOS 0.4.15-dev-7918-g2a2556c
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 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

◆ RtlpDebugPageHeapValidate()

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

Definition at line 2351 of file heappage.c.

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

826{
827 PDPH_HEAP_BLOCK DphNode, DphStartNode;
828 ULONG NodeCount, i;
829
830 //NodeCount = (Size >> 6) - 1;
831 NodeCount = (ULONG)(Size / sizeof(DPH_HEAP_BLOCK));
832 DphStartNode = Virtual;
833
834 /* Set pNextAlloc for all blocks */
835 for (DphNode = Virtual, i=NodeCount-1; i > 0; i--)
836 {
837 DphNode->pNextAlloc = DphNode + 1;
838 DphNode = DphNode->pNextAlloc;
839 }
840
841 /* and the last one */
842 DphNode->pNextAlloc = NULL;
843
844 /* Add it to the tail of unused node list */
845 if (DphRoot->pUnusedNodeListTail)
846 DphRoot->pUnusedNodeListTail->pNextAlloc = DphStartNode;
847 else
848 DphRoot->pUnusedNodeListHead = DphStartNode;
849
850 DphRoot->pUnusedNodeListTail = DphNode;
851
852 /* Increase counters */
853 DphRoot->nUnusedNodes += NodeCount;
854
855 /* Check if we need to place it on the pool list */
856 if (PlaceOnPool)
857 {
858 /* Get a node from the unused list */
859 DphNode = RtlpDphTakeNodeFromUnusedList(DphRoot);
860 ASSERT(DphNode);
861
862 /* Set its virtual block values */
863 DphNode->pVirtualBlock = Virtual;
864 DphNode->nVirtualBlockSize = Size;
865
866 /* Place it on the pool list */
867 RtlpDphPlaceOnPoolList(DphRoot, DphNode);
868 }
869}
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:511
PDPH_HEAP_BLOCK NTAPI RtlpDphTakeNodeFromUnusedList(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:547
#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 1014 of file heappage.c.

1015{
1018 SIZE_T Size = DPH_POOL_SIZE, SizeVirtual;
1019 PVOID Ptr = NULL;
1020
1021 /* Check for the easy case */
1022 if (DphRoot->pUnusedNodeListHead)
1023 {
1024 /* Just take a node from this list */
1026 ASSERT(Node);
1027 return Node;
1028 }
1029
1030 /* There is a need to make free space */
1032
1033 if (!DphRoot->pUnusedNodeListHead && !Node)
1034 {
1035 /* Retry with a smaller request */
1036 Size = PAGE_SIZE;
1038 }
1039
1040 if (!DphRoot->pUnusedNodeListHead)
1041 {
1042 if (Node)
1043 {
1045 Ptr = Node->pVirtualBlock;
1046 SizeVirtual = Node->nVirtualBlockSize;
1047 }
1048 else
1049 {
1050 /* No free space, need to alloc a new VM block */
1052 SizeVirtual = DPH_RESERVE_SIZE;
1054
1055 if (!NT_SUCCESS(Status))
1056 {
1057 /* Retry with a smaller size */
1058 SizeVirtual = 0x10000;
1060 if (!NT_SUCCESS(Status)) return NULL;
1061 }
1062 }
1063
1064 /* VM is allocated at this point, set protection */
1066 if (!NT_SUCCESS(Status))
1067 {
1068 if (Node)
1069 {
1071 }
1072 else
1073 {
1074 //RtlpDphFreeVm();
1075 ASSERT(FALSE);
1076 }
1077
1078 return NULL;
1079 }
1080
1081 /* Zero the memory */
1082 if (Node) RtlZeroMemory(Ptr, Size);
1083
1084 /* Add a new pool based on this VM */
1085 RtlpDphAddNewPool(DphRoot, Node, Ptr, Size, TRUE);
1086
1087 if (Node)
1088 {
1089 if (Node->nVirtualBlockSize > Size)
1090 {
1091 Node->pVirtualBlock += Size;
1092 Node->nVirtualBlockSize -= Size;
1093
1095 }
1096 else
1097 {
1099 }
1100 }
1101 else
1102 {
1103 /* The new VM block was just allocated a few code lines ago,
1104 so initialize it */
1106 Node->pVirtualBlock = Ptr;
1107 Node->nVirtualBlockSize = SizeVirtual;
1109
1111 Node->pVirtualBlock = (PUCHAR)Ptr + Size;
1112 Node->nVirtualBlockSize = SizeVirtual - Size;
1114
1115 /* Coalesce them into available list */
1117 }
1118 }
1119
1120 return RtlpDphTakeNodeFromUnusedList(DphRoot);
1121}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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:585
NTSTATUS NTAPI RtlpDphProtectVm(PVOID Base, SIZE_T Size, ULONG Protection)
Definition: heappage.c:417
VOID NTAPI RtlpDphReturnNodeToUnusedList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:569
#define DPH_RESERVE_SIZE
Definition: heappage.c:134
VOID NTAPI RtlpDphAddNewPool(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK NodeBlock, PVOID Virtual, SIZE_T Size, BOOLEAN PlaceOnPool)
Definition: heappage.c:825
VOID NTAPI RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:680
PDPH_HEAP_BLOCK NTAPI RtlpDphFindAvailableMemory(PDPH_HEAP_ROOT DphRoot, SIZE_T Size, BOOLEAN Grow)
Definition: heappage.c:904
#define DPH_POOL_SIZE
Definition: heappage.c:135
NTSTATUS NTAPI RtlpDphAllocateVm(PVOID *Base, SIZE_T Size, ULONG Type, ULONG Protection)
Definition: heappage.c:342
VOID NTAPI RtlpDphPlaceOnVirtualList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:531
#define 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 1202 of file heappage.c.

1204{
1205 PDPH_HEAP_BLOCK pBlock;
1206 PDPH_HEAP_ROOT DphRoot;
1207
1208 /* This mega-assert comes from a text search over Windows 2003 checked binary of ntdll.dll */
1209 ASSERT((ULONG_PTR)(((PRTL_BALANCED_LINKS)0)+1) + sizeof(PUCHAR) == ByteSize);
1210
1211 /* Get pointer to the containing heap root record */
1212 DphRoot = CONTAINING_RECORD(Table, DPH_HEAP_ROOT, BusyNodesTable);
1213 pBlock = DphRoot->NodeToAllocate;
1214
1215 DphRoot->NodeToAllocate = NULL;
1216 ASSERT(pBlock);
1217
1218 return &(pBlock->TableLinks);
1219}
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
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:399

Referenced by RtlpPageHeapCreate().

◆ RtlpDphAllocateVm()

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

Definition at line 342 of file heappage.c.

343{
345 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
346 Base,
347 0,
348 &Size,
349 Type,
350 Protection);
351 DPRINT("Page heap: AllocVm (%p, %Ix, %lx) status %lx\n", Base, Size, Type, Status);
352 /* Check for failures */
353 if (!NT_SUCCESS(Status))
354 {
355 if (Type == MEM_RESERVE)
356 {
359 {
360 DPRINT1("Page heap: AllocVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
362 return Status;
363 }
364 }
365 else
366 {
369 {
370 DPRINT1("Page heap: AllocVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
372 return Status;
373 }
374 }
375 }
376
377 return Status;
378}
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:2439
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define MEM_RESERVE
Definition: nt_native.h:1314
#define DPRINT
Definition: sndvol32.h:71

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

◆ RtlpDphCoalesceFreeIntoAvailable()

VOID NTAPI RtlpDphCoalesceFreeIntoAvailable ( PDPH_HEAP_ROOT  DphRoot,
ULONG  LeaveOnFreeList 
)

Definition at line 794 of file heappage.c.

796{
798 SIZE_T FreeAllocations = DphRoot->nFreeAllocations;
799
800 /* Make sure requested size is not too big */
801 ASSERT(FreeAllocations >= LeaveOnFreeList);
802
803 DPRINT("RtlpDphCoalesceFreeIntoAvailable(%p %lu)\n", DphRoot, LeaveOnFreeList);
804
805 while (Node)
806 {
807 FreeAllocations--;
808 if (FreeAllocations < LeaveOnFreeList) break;
809
810 /* Get the next pointer, because it may be changed after following two calls */
811 Next = Node->pNextAlloc;
812
813 /* Remove it from the free list */
815
816 /* And put into the available */
818
819 /* Go to the next node */
820 Node = Next;
821 }
822}
VOID NTAPI RtlpDphRemoveFromFreeList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node, PDPH_HEAP_BLOCK Prev)
Definition: heappage.c:656
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 680 of file heappage.c.

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

1186{
1187 ULONG_PTR FirstBlock, SecondBlock;
1188
1189 FirstBlock = *((ULONG_PTR *)FirstStruct);
1190 SecondBlock = *((ULONG_PTR *)SecondStruct);
1191
1192 if (FirstBlock < SecondBlock)
1193 return GenericLessThan;
1194 else if (FirstBlock > SecondBlock)
1195 return GenericGreaterThan;
1196
1197 return GenericEqual;
1198}
_IRQL_requires_same_ _In_ PVOID _In_ PVOID SecondStruct
Definition: rtltypes.h:390
_IRQL_requires_same_ _In_ PVOID FirstStruct
Definition: rtltypes.h:389
@ GenericLessThan
Definition: rtltypes.h:376
@ GenericEqual
Definition: rtltypes.h:378
@ GenericGreaterThan
Definition: rtltypes.h:377

Referenced by RtlpPageHeapCreate().

◆ RtlpDphEnterCriticalSection()

VOID NTAPI RtlpDphEnterCriticalSection ( PDPH_HEAP_ROOT  DphRoot,
ULONG  Flags 
)

Definition at line 261 of file heappage.c.

262{
264 {
265 /* More complex scenario */
266 if (!RtlTryEnterHeapLock(DphRoot->HeapCritSect, TRUE))
267 {
268 if (!DphRoot->nRemoteLockAcquired)
269 {
270 DPRINT1("multithreaded access in HEAP_NO_SERIALIZE heap\n");
272
273 /* Clear out the no serialize flag */
274 DphRoot->HeapFlags &= ~HEAP_NO_SERIALIZE;
275 }
276
277 /* Enter the heap's critical section */
279 }
280 }
281 else
282 {
283 /* Just enter the heap's critical section */
285 }
286}
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
BOOLEAN NTAPI RtlTryEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:117
#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 904 of file heappage.c.

907{
910
911 /* Find an available best fitting node */
913
914 /* If that didn't work, try to search a smaller one in the loop */
915 while (!Node)
916 {
917 /* Break if the free list becomes too small */
918 if (DphRoot->nFreeAllocations <= DPH_FREE_LIST_MINIMUM) break;
919
920 /* Calculate a new free list size */
921 NewSize = DphRoot->nFreeAllocations >> 2;
923
924 /* Coalesce free into available */
926
927 /* Try to find an available best fitting node again */
929 }
930
931 /* If Node is NULL, then we could fix the situation only by
932 growing the available VM size */
933 if (!Node && Grow)
934 {
935 /* Grow VM size, if it fails - return failure directly */
936 if (!RtlpDphGrowVirtual(DphRoot, Size)) return NULL;
937
938 /* Try to find an available best fitting node again */
940
941 if (!Node)
942 {
943 /* Do the last attempt: coalesce all free into available (if Size fits there) */
945 {
946 /* Coalesce free into available */
948
949 /* Try to find an available best fitting node again */
951 }
952 }
953 }
954
955 /* Return node we found */
956 return Node;
957}
_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:872
BOOLEAN NTAPI RtlpDphGrowVirtual(PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
Definition: heappage.c:1124
VOID NTAPI RtlpDphCoalesceFreeIntoAvailable(PDPH_HEAP_ROOT DphRoot, ULONG LeaveOnFreeList)
Definition: heappage.c:794
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 960 of file heappage.c.

962{
964 PVOID Ptr;
965
966 /* Lookup busy block in AVL */
967 Ptr = RtlLookupElementGenericTableAvl(&DphRoot->BusyNodesTable, &pUserMem);
968 if (!Ptr) return NULL;
969
970 /* Restore pointer to the heap block */
971 Node = CONTAINING_RECORD(Ptr, DPH_HEAP_BLOCK, pUserAllocation);
972 ASSERT(Node->pUserAllocation == pUserMem);
973 return Node;
974}
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 1254 of file heappage.c.

1256{
1257 PLIST_ENTRY Current, Next;
1258 PDPH_BLOCK_INFORMATION BlockInfo;
1259 ULONG ValidationInfo;
1260
1261 /* The original routine seems to use a temporary SList to put blocks to be freed,
1262 then it releases the lock and frees the blocks. But let's make it simple for now */
1263
1264 /* Acquire the delayed free queue lock */
1266
1267 /* Traverse the list */
1269 while (Current != &RtlpDphDelayedFreeQueue)
1270 {
1271 /* Get the next entry pointer */
1272 Next = Current->Flink;
1273
1274 BlockInfo = CONTAINING_RECORD(Current, DPH_BLOCK_INFORMATION, FreeQueue);
1275
1276 /* Check if it belongs to the same heap */
1277 if (BlockInfo->Heap == DphRoot)
1278 {
1279 /* Remove it from the list */
1280 RemoveEntryList(Current);
1281
1282 /* Reset its heap to NULL */
1283 BlockInfo->Heap = NULL;
1284
1285 if (!RtlpDphIsNormalFreeHeapBlock(BlockInfo + 1, &ValidationInfo, TRUE))
1286 {
1287 RtlpDphReportCorruptedBlock(DphRoot, 10, BlockInfo + 1, ValidationInfo);
1288 }
1289
1290 /* Decrement counters */
1293
1294 /* Free the normal heap */
1295 RtlFreeHeap(NormalHeap, 0, BlockInfo);
1296 }
1297
1298 /* Move to the next one */
1299 Current = Next;
1300 }
1301
1302 /* Release the delayed free queue lock */
1304}
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
NTSTATUS NTAPI RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:133
BOOLEAN NTAPI RtlpDphIsNormalFreeHeapBlock(PVOID Block, PULONG ValidationInformation, BOOLEAN CheckFillers)
Definition: heappage.c:1480
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:1326

Referenced by RtlpPageHeapDestroy().

◆ RtlpDphFreeNodeForTable()

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

Definition at line 1223 of file heappage.c.

1225{
1226 /* Nothing */
1227}

Referenced by RtlpPageHeapCreate().

◆ RtlpDphFreeVm()

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

Definition at line 381 of file heappage.c.

382{
384
385 /* Free the memory */
387 DPRINT("Page heap: FreeVm (%p, %Ix, %lx) status %lx\n", Base, Size, Type, Status);
388 /* Log/report failures */
389 if (!NT_SUCCESS(Status))
390 {
391 if (Type == MEM_RELEASE)
392 {
395 {
396 DPRINT1("Page heap: FreeVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
398 return Status;
399 }
400 }
401 else
402 {
405 {
406 DPRINT1("Page heap: FreeVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
408 return Status;
409 }
410 }
411 }
412
413 return Status;
414}
NTSTATUS NTAPI RtlpSecMemFreeVirtualMemory(HANDLE Process, PVOID *Base, PSIZE_T Size, ULONG Type)
Definition: heappage.c:319
#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 246 of file heappage.c.

247{
248 PDPH_BLOCK_INFORMATION BlockInfo;
249 BlockInfo = (PDPH_BLOCK_INFORMATION)Block - 1;
250
251 /* Check stamps */
252 if (BlockInfo->StartStamp != DPH_FILL_START_STAMP_1 && BlockInfo->StartStamp != DPH_FILL_START_STAMP_2)
253 {
254 return 0;
255 }
256
257 return BlockInfo->RequestedSize;
258}
#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 1124 of file heappage.c.

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

Referenced by RtlpDphFindAvailableMemory().

◆ RtlpDphHeapFromPointer()

PVOID NTAPI RtlpDphHeapFromPointer ( PDPH_HEAP_ROOT  DphHeap)

Definition at line 240 of file heappage.c.

241{
242 return ((PUCHAR)DphHeap) - PAGE_SIZE;
243}

Referenced by RtlpDphReportCorruptedBlock().

◆ RtlpDphInitializeDelayedFreeQueue()

NTSTATUS NTAPI RtlpDphInitializeDelayedFreeQueue ( VOID  )

Definition at line 1230 of file heappage.c.

1231{
1233
1235 if (!NT_SUCCESS(Status))
1236 {
1237 // TODO: Log this error!
1238 DPRINT1("Failure initializing delayed free queue critical section\n");
1239 return Status;
1240 }
1241
1242 /* Initialize lists */
1245
1246 /* Reset counters */
1249
1250 return Status;
1251}
NTSTATUS NTAPI RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
Definition: libsupp.c:126
#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 1314 of file heappage.c.

1315{
1317}
#define UNIMPLEMENTED
Definition: debug.h:115

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

◆ RtlpDphIsNormalFreeHeapBlock()

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

Definition at line 1480 of file heappage.c.

1483{
1484 ASSERT(ValidationInformation != NULL);
1485
1487 *ValidationInformation = 0;
1488 return TRUE;
1489}

Referenced by RtlpDphFreeDelayedBlocksFromHeap().

◆ RtlpDphIsPageHeapBlock()

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

Definition at line 1417 of file heappage.c.

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

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

◆ RtlpDphLeaveCriticalSection()

VOID NTAPI RtlpDphLeaveCriticalSection ( PDPH_HEAP_ROOT  DphRoot)

Definition at line 289 of file heappage.c.

290{
291 /* Just leave the heap's critical section */
293}

Referenced by RtlpDphPostProcessing(), and RtlpPageHeapUnlock().

◆ RtlpDphNormalHeapValidate()

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

Definition at line 2394 of file heappage.c.

2397{
2399 if (!BaseAddress)
2400 {
2401 /* Validate all normal heap */
2402 return RtlValidateHeap(DphRoot->NormalHeap, Flags, NULL);
2403 }
2404
2405 // FIXME: Check is this a normal heap block
2406 /*if (!RtlpDphIsNormalHeapBlock(DphRoot, BaseAddress, &ValidationInfo))
2407 {
2408 }*/
2409
2410 return RtlValidateHeap(DphRoot->NormalHeap, Flags, BlockInfo);
2411}
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 467 of file heappage.c.

468{
469 BOOLEAN NewElement;
470 PVOID AddressUserData;
471
472 DPRINT("RtlpDphPlaceOnBusyList(%p %p)\n", DphRoot, DphNode);
473
474 /* Add it to the AVL busy nodes table */
475 DphRoot->NodeToAllocate = DphNode;
476 AddressUserData = RtlInsertElementGenericTableAvl(&DphRoot->BusyNodesTable,
477 &DphNode->pUserAllocation,
478 sizeof(ULONG_PTR),
479 &NewElement);
480
481 ASSERT(AddressUserData == &DphNode->pUserAllocation);
482 ASSERT(NewElement == TRUE);
483
484 /* Update heap counters */
485 DphRoot->nBusyAllocations++;
488}
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 491 of file heappage.c.

492{
493 DPRINT("RtlpDphPlaceOnFreeList(%p %p)\n", DphRoot, Node);
494
495 /* Node is being added to the tail of the list */
496 Node->pNextAlloc = NULL;
497
498 /* Add it to the tail of the linked list */
499 if (DphRoot->pFreeAllocationListTail)
501 else
502 DphRoot->pFreeAllocationListHead = Node;
503 DphRoot->pFreeAllocationListTail = Node;
504
505 /* Update byte counts taking in account this new node */
506 DphRoot->nFreeAllocations++;
507 DphRoot->nFreeAllocationBytesCommitted += Node->nVirtualBlockSize;
508}
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 511 of file heappage.c.

512{
513 DPRINT("RtlpDphPlaceOnPoolList(%p %p)\n", DphRoot, Node);
514
515 /* Node is being added to the tail of the list */
516 Node->pNextAlloc = NULL;
517
518 /* Add it to the tail of the linked list */
519 if (DphRoot->pNodePoolListTail)
521 else
522 DphRoot->pNodePoolListHead = Node;
523 DphRoot->pNodePoolListTail = Node;
524
525 /* Update byte counts taking in account this new node */
526 DphRoot->nNodePools++;
527 DphRoot->nNodePoolBytes += Node->nVirtualBlockSize;
528}
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 531 of file heappage.c.

532{
533 DPRINT("RtlpDphPlaceOnVirtualList(%p %p)\n", DphRoot, Node);
534
535 /* Add it to the head of the virtual list */
536 Node->pNextAlloc = DphRoot->pVirtualStorageListHead;
537 if (!DphRoot->pVirtualStorageListHead)
538 DphRoot->pVirtualStorageListTail = Node;
539 DphRoot->pVirtualStorageListHead = Node;
540
541 /* Update byte counts taking in account this new node */
542 DphRoot->nVirtualStorageRanges++;
543 DphRoot->nVirtualStorageBytes += Node->nVirtualBlockSize;
544}
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 223 of file heappage.c.

224{
225 PHEAP NormalHeap = (PHEAP)Handle;
227
228 if (NormalHeap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
229 {
230 if (DphHeap->Signature == DPH_SIGNATURE)
231 return DphHeap;
232 }
233
234 DPRINT1("heap handle with incorrect signature\n");
236 return NULL;
237}
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 305 of file heappage.c.

306{
307 if (!DphRoot) return;
308
310 {
311 /* FIXME: Validate integrity, internal lists if necessary */
312 }
313
314 /* Release the lock */
316}
VOID NTAPI RtlpDphLeaveCriticalSection(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:289
#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 297 of file heappage.c.

298{
300
301 /* FIXME: Validate integrity, internal lists if necessary */
302}
VOID NTAPI RtlpDphEnterCriticalSection(PDPH_HEAP_ROOT DphRoot, ULONG Flags)
Definition: heappage.c:261

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

◆ RtlpDphProcessStartupInitialization()

NTSTATUS NTAPI RtlpDphProcessStartupInitialization ( VOID  )

Definition at line 1492 of file heappage.c.

1493{
1495 PTEB Teb = NtCurrentTeb();
1496
1497 /* Initialize the DPH heap list and its critical section */
1500 if (!NT_SUCCESS(Status))
1501 {
1502 ASSERT(FALSE);
1503 return Status;
1504 }
1505
1506 /* Initialize delayed-free queue */
1508 if (!NT_SUCCESS(Status)) return Status;
1509
1510 /* Initialize the target dlls string */
1513
1514 /* Per-process DPH init is done */
1516
1517 DPRINT1("Page heap: pid 0x%p: page heap enabled with flags 0x%X.\n",
1519
1520 return Status;
1521}
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:1230
NTSTATUS NTAPI RtlpDphTargetDllsLogicInitialize(VOID)
Definition: heappage.c:1307
#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 417 of file heappage.c.

418{
420 ULONG OldProtection;
421
422 /* Change protection */
423 Status = ZwProtectVirtualMemory(NtCurrentProcess(), &Base, &Size, Protection, &OldProtection);
424
425 /* Log/report failures */
426 if (!NT_SUCCESS(Status))
427 {
430 {
431 DPRINT1("Page heap: ProtectVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Protection, Status);
433 return Status;
434 }
435 }
436
437 return Status;
438}
#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 207 of file heappage.c.

208{
209 EXCEPTION_RECORD Exception;
210
211 /* Initialize exception record */
212 Exception.ExceptionCode = Status;
214 Exception.ExceptionFlags = 0;
215 Exception.ExceptionRecord = NULL;
216 Exception.NumberParameters = 0;
217
218 /* Raise the exception */
219 RtlRaiseException(&Exception);
220}
VOID NTAPI RtlpDphRaiseException(NTSTATUS Status)
Definition: heappage.c:207
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 585 of file heappage.c.

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

640{
641 BOOLEAN ElementPresent;
642
643 DPRINT("RtlpDphRemoveFromBusyList(%p %p)\n", DphRoot, Node);
644
645 /* Delete it from busy nodes table */
646 ElementPresent = RtlDeleteElementGenericTableAvl(&DphRoot->BusyNodesTable, &Node->pUserAllocation);
647 ASSERT(ElementPresent == TRUE);
648
649 /* Update counters */
650 DphRoot->nBusyAllocations--;
651 DphRoot->nBusyAllocationBytesCommitted -= Node->nVirtualBlockSize;
652 DphRoot->nBusyAllocationBytesAccessible -= Node->nVirtualAccessSize;
653}
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 656 of file heappage.c.

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

Referenced by RtlpDphCoalesceFreeIntoAvailable().

◆ RtlpDphReportCorruptedBlock()

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

Definition at line 1326 of file heappage.c.

1331{
1333 DPH_BLOCK_INFORMATION SafeInfo = {0};
1334
1335 DPRINT1("Corrupted heap block %p\n", Block);
1336
1337 _SEH2_TRY
1338 {
1339 PDPH_BLOCK_INFORMATION BlockInfo = (PDPH_BLOCK_INFORMATION)Block - 1;
1340 RtlCopyMemory(&SafeInfo, BlockInfo, sizeof(SafeInfo));
1341 }
1343 {
1344 DPRINT1("ERROR: Could not read DPH_BLOCK_INFORMATION\n");
1345 RtlZeroMemory(&SafeInfo, sizeof(SafeInfo));
1346 }
1347 _SEH2_END;
1348
1349 if (ValidationInfo & DPH_VALINFO_CORRUPTED_AFTER_FREE)
1350 {
1352 APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_AFTER_FREE, "block corrupted after having been freed",
1353 RtlpDphHeapFromPointer(DphRoot), "Heap handle", Block, "Heap block", (PVOID)Size, "Block size", 0, "");
1354 }
1355
1356 if (ValidationInfo & DPH_VALINFO_ALREADY_FREED)
1357 {
1359 APPLICATION_VERIFIER_DOUBLE_FREE, "block already freed", RtlpDphHeapFromPointer(DphRoot), "Heap handle",
1360 Block, "Heap block", Size, "Block size", 0, "");
1361 }
1362
1363 if (ValidationInfo & DPH_VALINFO_BAD_INFIX_PATTERN)
1364 {
1366 APPLICATION_VERIFIER_CORRUPTED_INFIX_PATTERN, "corrupted infix pattern for freed block",
1367 RtlpDphHeapFromPointer(DphRoot), "Heap handle", Block, "Heap block", Size, "Block size", 0, "");
1368 }
1369
1370 if (ValidationInfo & DPH_VALINFO_BAD_POINTER)
1371 {
1373 APPLICATION_VERIFIER_CORRUPT_HEAP_POINTER, "corrupted heap pointer or using wrong heap",
1374 RtlpDphHeapFromPointer(DphRoot), "Heap handle used", Block, "Heap block", Size, "Block size",
1375 SafeInfo.Heap, "Actual heap handle");
1376 }
1377
1378 if (ValidationInfo & DPH_VALINFO_BAD_SUFFIX_PATTERN)
1379 {
1381 APPLICATION_VERIFIER_CORRUPTED_SUFFIX_PATTERN, "corrupted suffix pattern", RtlpDphHeapFromPointer(DphRoot),
1382 "Heap handle used", Block, "Heap block", Size, "Block size", 0, "");
1383 }
1384
1385 if (ValidationInfo & DPH_VALINFO_BAD_PREFIX_PATTERN)
1386 {
1388 APPLICATION_VERIFIER_CORRUPTED_PREFIX_PATTERN, "corrupted prefix pattern", RtlpDphHeapFromPointer(DphRoot),
1389 "Heap handle used", Block, "Heap block", Size, "Block size", 0, "");
1390 }
1391
1392 if (ValidationInfo & DPH_VALINFO_BAD_START_STAMP)
1393 {
1395 APPLICATION_VERIFIER_CORRUPTED_START_STAMP, "corrupted start stamp", RtlpDphHeapFromPointer(DphRoot),
1396 "Heap handle used", Block, "Heap block", Size, "Block size", (PVOID)(ULONG_PTR)SafeInfo.StartStamp,
1397 "Corrupted start stamp");
1398 }
1399
1400 if (ValidationInfo & DPH_VALINFO_BAD_END_STAMP)
1401 {
1404 "Heap handle used", Block, "Heap block", Size, "Block size", (PVOID)(ULONG_PTR)SafeInfo.EndStamp,
1405 "Corrupted end stamp");
1406 }
1407
1408 if (ValidationInfo & DPH_VALINFO_EXCEPTION)
1409 {
1411 APPLICATION_VERIFIER_EXCEPTION_WHILE_VERIFYING_BLOCK_HEADER, "exception raised while verifying block",
1412 RtlpDphHeapFromPointer(DphRoot), "Heap handle used", Block, "Heap block", Size, "Block size", 0, "");
1413 }
1414}
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
ULONG NTAPI RtlpDphGetBlockSizeFromCorruptedBlock(PVOID Block)
Definition: heappage.c:246
#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:240
#define DPH_VALINFO_BAD_INFIX_PATTERN
Definition: heappage.c:171
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define APPLICATION_VERIFIER_CORRUPTED_END_STAMP
Definition: verifier.h:97
VOID NTAPI RtlApplicationVerifierStop(_In_ ULONG_PTR Code, _In_ PCSTR Message, _In_ PVOID Value1, _In_ PCSTR Description1, _In_ PVOID Value2, _In_ PCSTR Description2, _In_ PVOID Value3, _In_ PCSTR Description3, _In_ PVOID Value4, _In_ PCSTR Description4)
Definition: appverifier.c:23
#define APPLICATION_VERIFIER_CORRUPTED_SUFFIX_PATTERN
Definition: verifier.h:95
#define APPLICATION_VERIFIER_CORRUPT_HEAP_POINTER
Definition: verifier.h:89
#define APPLICATION_VERIFIER_CORRUPTED_INFIX_PATTERN
Definition: verifier.h:94
#define APPLICATION_VERIFIER_DOUBLE_FREE
Definition: verifier.h:90
#define APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_AFTER_FREE
Definition: verifier.h:93
#define APPLICATION_VERIFIER_CORRUPTED_START_STAMP
Definition: verifier.h:96
#define APPLICATION_VERIFIER_CORRUPTED_PREFIX_PATTERN
Definition: verifier.h:98
#define APPLICATION_VERIFIER_EXCEPTION_WHILE_VERIFYING_BLOCK_HEADER
Definition: verifier.h:92

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

◆ RtlpDphReturnNodeToUnusedList()

VOID NTAPI RtlpDphReturnNodeToUnusedList ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 569 of file heappage.c.

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

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

◆ RtlpDphSearchAvailableMemoryListForBestFit()

PDPH_HEAP_BLOCK NTAPI RtlpDphSearchAvailableMemoryListForBestFit ( PDPH_HEAP_ROOT  DphRoot,
SIZE_T  Size 
)

Definition at line 872 of file heappage.c.

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

Referenced by RtlpDphFindAvailableMemory().

◆ RtlpDphSetProtectionAfterUse()

NTSTATUS NTAPI RtlpDphSetProtectionAfterUse ( PDPH_HEAP_ROOT  DphRoot,
PDPH_HEAP_BLOCK  Node 
)

Definition at line 998 of file heappage.c.

999{
1000 ASSERT((Node->nVirtualAccessSize + PAGE_SIZE) <= Node->nVirtualBlockSize);
1001
1002 // FIXME: Bring stuff here
1003 if (DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN)
1004 {
1005 }
1006 else
1007 {
1008 }
1009
1010 return STATUS_SUCCESS;
1011}
#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 977 of file heappage.c.

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

Referenced by RtlpPageHeapAllocate().

◆ RtlpDphShouldAllocateInPageHeap()

BOOLEAN NTAPI RtlpDphShouldAllocateInPageHeap ( PDPH_HEAP_ROOT  DphRoot,
SIZE_T  Size 
)

Definition at line 1524 of file heappage.c.

1526{
1527 //UNIMPLEMENTED;
1528 /* Always use page heap for now */
1529 return TRUE;
1530}

Referenced by RtlpPageHeapAllocate(), and RtlpPageHeapReAllocate().

◆ RtlpDphTakeNodeFromUnusedList()

PDPH_HEAP_BLOCK NTAPI RtlpDphTakeNodeFromUnusedList ( PDPH_HEAP_ROOT  DphRoot)

Definition at line 547 of file heappage.c.

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

Referenced by RtlpDphAddNewPool(), and RtlpDphAllocateNode().

◆ RtlpDphTargetDllsLogicInitialize()

NTSTATUS NTAPI RtlpDphTargetDllsLogicInitialize ( VOID  )

Definition at line 1307 of file heappage.c.

1308{
1310 return STATUS_SUCCESS;
1311}

Referenced by RtlpDphProcessStartupInitialization().

◆ RtlpDphVerifyIntegrity()

VOID NTAPI RtlpDphVerifyIntegrity ( PDPH_HEAP_ROOT  DphRoot)

Definition at line 1320 of file heappage.c.

1321{
1323}

Referenced by RtlpPageHeapAllocate().

◆ RtlpDphWritePageHeapBlockInformation()

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

Definition at line 441 of file heappage.c.

442{
443 PDPH_BLOCK_INFORMATION BlockInfo;
444 PUCHAR FillPtr;
445
446 /* Get pointer to the block info structure */
447 BlockInfo = (PDPH_BLOCK_INFORMATION)UserAllocation - 1;
448
449 /* Set up basic fields */
450 BlockInfo->Heap = DphRoot;
451 BlockInfo->ActualSize = UserSize;
452 BlockInfo->RequestedSize = Size;
454 BlockInfo->EndStamp = DPH_FILL_END_STAMP_1;
455
456 /* Fill with a pattern */
457 FillPtr = (PUCHAR)UserAllocation + Size;
458 RtlFillMemory(FillPtr, ROUND_UP(FillPtr, PAGE_SIZE) - (ULONG_PTR)FillPtr, DPH_FILL_SUFFIX);
459
460 /* FIXME: Check if logging stack traces is turned on */
461 //if (DphRoot->ExtraFlags &
462
463 return TRUE;
464}
#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 1758 of file heappage.c.

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

1539{
1540 PVOID Base = NULL;
1541 PHEAP HeapPtr;
1542 PDPH_HEAP_ROOT DphRoot;
1543 PDPH_HEAP_BLOCK DphNode;
1544 ULONG MemSize;
1546 LARGE_INTEGER PerfCounter;
1547
1548 /* Check for a DPH bypass flag */
1549 if ((ULONG_PTR)Parameters == -1) return NULL;
1550
1551 /* Make sure no user-allocated stuff was provided */
1552 if (Addr || Lock) return NULL;
1553
1554 /* Allocate minimum amount of virtual memory */
1555 MemSize = DPH_RESERVE_SIZE;
1557 if (!NT_SUCCESS(Status))
1558 {
1559 ASSERT(FALSE);
1560 return NULL;
1561 }
1562
1563 /* Set protection */
1565 if (!NT_SUCCESS(Status))
1566 {
1567 //RtlpDphFreeVm(Base, 0, 0, 0);
1568 ASSERT(FALSE);
1569 return NULL;
1570 }
1571
1572 /* Start preparing the 1st page. Fill it with the default filler */
1574
1575 /* Set flags in the "HEAP" structure */
1576 HeapPtr = (PHEAP)Base;
1577 HeapPtr->Flags = Flags | HEAP_FLAG_PAGE_ALLOCS;
1579
1580 /* Set 1st page to read only now */
1582 if (!NT_SUCCESS(Status))
1583 {
1584 ASSERT(FALSE);
1585 return NULL;
1586 }
1587
1588 /* 2nd page is the real DPH root block */
1589 DphRoot = (PDPH_HEAP_ROOT)((PCHAR)Base + PAGE_SIZE);
1590
1591 /* Initialize the DPH root */
1592 DphRoot->Signature = DPH_SIGNATURE;
1593 DphRoot->HeapFlags = Flags;
1594 DphRoot->HeapCritSect = (PHEAP_LOCK)((PCHAR)DphRoot + DPH_POOL_SIZE);
1595 DphRoot->ExtraFlags = RtlpDphGlobalFlags;
1596
1597 ZwQueryPerformanceCounter(&PerfCounter, NULL);
1598 DphRoot->Seed = PerfCounter.LowPart;
1599
1602
1603 /* Create a normal heap for this paged heap */
1604 DphRoot->NormalHeap = RtlCreateHeap(Flags, NULL, TotalSize, CommitSize, NULL, (PRTL_HEAP_PARAMETERS)-1);
1605 if (!DphRoot->NormalHeap)
1606 {
1607 ASSERT(FALSE);
1608 return NULL;
1609 }
1610
1611 /* 3rd page: a pool for DPH allocations */
1612 RtlpDphAddNewPool(DphRoot, NULL, DphRoot + 1, DPH_POOL_SIZE - sizeof(DPH_HEAP_ROOT), FALSE);
1613
1614 /* Allocate internal heap blocks. For the root */
1615 DphNode = RtlpDphAllocateNode(DphRoot);
1616 ASSERT(DphNode != NULL);
1617 DphNode->pVirtualBlock = (PUCHAR)DphRoot;
1619 RtlpDphPlaceOnPoolList(DphRoot, DphNode);
1620
1621 /* For the memory we allocated as a whole */
1622 DphNode = RtlpDphAllocateNode(DphRoot);
1623 ASSERT(DphNode != NULL);
1624 DphNode->pVirtualBlock = Base;
1625 DphNode->nVirtualBlockSize = MemSize;
1626 RtlpDphPlaceOnVirtualList(DphRoot, DphNode);
1627
1628 /* For the remaining part */
1629 DphNode = RtlpDphAllocateNode(DphRoot);
1630 ASSERT(DphNode != NULL);
1632 DphNode->nVirtualBlockSize = MemSize - (2*PAGE_SIZE + DPH_POOL_SIZE);
1633 RtlpDphCoalesceNodeIntoAvailable(DphRoot, DphNode);
1634
1635 //DphRoot->CreateStackTrace = RtlpDphLogStackTrace(1);
1636
1637 /* Initialize AVL-based busy nodes table */
1642 NULL);
1643
1644 /* Initialize per-process startup info */
1646
1647 /* Acquire the heap list lock */
1649
1650 /* Insert this heap to the tail of the global list */
1652
1653 /* Note we increased the size of the list */
1655
1656 /* Release the heap list lock */
1658
1660 {
1661 DPRINT1("Page heap: process 0x%p created heap @ %p (%p, flags 0x%X)\n",
1663 DphRoot->NormalHeap, DphRoot->ExtraFlags);
1664 }
1665
1666 /* Perform internal validation if required */
1669
1670 return (PUCHAR)DphRoot - PAGE_SIZE;
1671}
VOID NTAPI RtlInitializeGenericTableAvl(IN OUT PRTL_AVL_TABLE Table, IN PRTL_AVL_COMPARE_ROUTINE CompareRoutine, IN PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine, IN PRTL_AVL_FREE_ROUTINE FreeRoutine, IN PVOID TableContext)
Definition: avltable.c:26
#define PAGE_READONLY
Definition: compat.h:138
VOID NTAPI RtlpDphFreeNodeForTable(IN PRTL_AVL_TABLE Table, IN PVOID Buffer)
Definition: heappage.c:1223
#define DPH_FILL
Definition: heappage.c:155
ULONG RtlpDphPageHeapListLength
Definition: heappage.c:117
PVOID NTAPI RtlpDphAllocateNodeForTable(IN PRTL_AVL_TABLE Table, IN CLONG ByteSize)
Definition: heappage.c:1202
NTSTATUS NTAPI RtlpDphProcessStartupInitialization(VOID)
Definition: heappage.c:1492
#define DPH_DEBUG_VERBOSE
Definition: heappage.c:148
RTL_GENERIC_COMPARE_RESULTS NTAPI RtlpDphCompareNodeForTable(IN PRTL_AVL_TABLE Table, IN PVOID FirstStruct, IN PVOID SecondStruct)
Definition: heappage.c:1183
#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 RtlCreateHeap().

◆ RtlpPageHeapDestroy()

PVOID NTAPI RtlpPageHeapDestroy ( HANDLE  HeapPtr)

Definition at line 1674 of file heappage.c.

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

Referenced by RtlDestroyHeap().

◆ RtlpPageHeapFree()

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

Definition at line 1923 of file heappage.c.

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

Referenced by RtlDebugFreeHeap().

◆ RtlpPageHeapGetUserInfo()

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

Definition at line 2185 of file heappage.c.

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

Referenced by RtlDebugGetUserInfoHeap().

◆ RtlpPageHeapLock()

BOOLEAN NTAPI RtlpPageHeapLock ( HANDLE  HeapPtr)

Definition at line 2415 of file heappage.c.

2416{
2417 PDPH_HEAP_ROOT DphRoot;
2418
2419 /* Get pointer to the heap root */
2420 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2421 if (!DphRoot) return FALSE;
2422
2423 RtlpDphEnterCriticalSection(DphRoot, DphRoot->HeapFlags);
2424 return TRUE;
2425}

Referenced by RtlLockHeap().

◆ RtlpPageHeapReAllocate()

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

Definition at line 2015 of file heappage.c.

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

Referenced by RtlDebugReAllocateHeap().

◆ RtlpPageHeapSetUserFlags()

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

Definition at line 2268 of file heappage.c.

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

Referenced by RtlDebugSetUserFlagsHeap().

◆ RtlpPageHeapSetUserValue()

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

Definition at line 2227 of file heappage.c.

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

Referenced by RtlDebugSetUserValueHeap().

◆ RtlpPageHeapSize()

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

Definition at line 2310 of file heappage.c.

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

Referenced by RtlDebugSizeHeap().

◆ RtlpPageHeapUnlock()

BOOLEAN NTAPI RtlpPageHeapUnlock ( HANDLE  HeapPtr)

Definition at line 2429 of file heappage.c.

2430{
2431 PDPH_HEAP_ROOT DphRoot;
2432
2433 /* Get pointer to the heap root */
2434 DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2435 if (!DphRoot) return FALSE;
2436
2438 return TRUE;
2439}

Referenced by RtlUnlockHeap().

◆ RtlpSecMemFreeVirtualMemory()

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

Definition at line 319 of file heappage.c.

320{
322 //PVOID *SavedBase = Base;
323 //PSIZE_T SavedSize = Size;
324
325 /* Free the memory */
326 Status = ZwFreeVirtualMemory(Process, Base, Size, Type);
327
328 /* Flush secure memory cache if needed and retry freeing */
329#if 0
332 RtlFlushSecureMemoryCache(*SavedBase, *SavedSize))
333 {
334 Status = ZwFreeVirtualMemory(NtCurrentProcess(), SavedBase, SavedSize, Type);
335 }
336#endif
337
338 return Status;
339}
_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.