Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

heappage.c File Reference

#include "ntrtlp.h"
#include "heappage.h"
#include "heappagi.h"
#include "heappriv.h"

Go to the source code of this file.

Classes

struct  _DPH_TARGET_DLL

Defines

#define DPH_HEAP_SIGNATURE   0xFFEEDDCC
#define FILL_BYTE   0xEE
#define HEAD_FILL_SIZE   0x10
#define RESERVE_SIZE   0x100000
#define VM_UNIT_SIZE   0x10000
#define POOL_SIZE   0x4000
#define INLINE   __inline
#define MIN_FREE_LIST_LENGTH   8
#define ROUNDUP2(x, n)   ((( x ) + (( n ) - 1 )) & ~(( n ) - 1 ))
#define DEBUG_CODE(a)
#define RETAIL_ASSERT(a)
#define DEBUG_ASSERT(a)   DEBUG_CODE( RETAIL_ASSERT( a ))
#define HEAP_HANDLE_FROM_ROOT(HeapRoot)   ((PVOID)(((PCHAR)(HeapRoot)) - PAGE_SIZE ))
#define IF_GENERATE_EXCEPTION(Flags, Status)
#define OUT_OF_VM_BREAK(Flags, szText)
#define ENQUEUE_HEAD(Node, Head, Tail)
#define ENQUEUE_TAIL(Node, Head, Tail)
#define DEQUEUE_NODE(Node, Prev, Head, Tail)
#define BIAS_POINTER(p)   ((PVOID)((ULONG_PTR)(p) | (ULONG_PTR)0x01))
#define UNBIAS_POINTER(p)   ((PVOID)((ULONG_PTR)(p) & ~((ULONG_PTR)0x01)))
#define IS_BIASED_POINTER(p)   ((PVOID)((ULONG_PTR)(p) & (ULONG_PTR)0x01))
#define PROTECT_HEAP_STRUCTURES(HeapRoot)
#define UNPROTECT_HEAP_STRUCTURES(HeapRoot)
#define DPH_DEBUG_INTERNAL_VALIDATION   0x0001
#define DPH_DEBUG_RESERVED_2   0x0002
#define DPH_DEBUG_RESERVED_4   0x0004
#define DPH_DEBUG_RESERVED_8   0x0008
#define DPH_DEBUG_DECOMMIT_RANGES   0x0010
#define DPH_DEBUG_BREAK_FOR_SIZE_ZERO   0x0020
#define DPH_DEBUG_BREAK_FOR_NULL_FREE   0x0040
#define DPH_DEBUG_NEVER_FREE   0x0080
#define DPH_DEBUG_SLOW_CHECKS   0x0100
#define BUMP_GLOBAL_COUNTER(n)   InterlockedIncrement(&(RtlpDphGlobalCounter[n]))
#define BUMP_SIZE_COUNTER(Size)
#define MAX_GLOBAL_COUNTER_INDEX   15
#define MAX_SIZE_COUNTER_INDEX   64

Typedefs

typedef _DPH_TARGET_DLL DPH_TARGET_DLL
typedef _DPH_TARGET_DLLPDPH_TARGET_DLL

Functions

int __cdecl sprintf (char *, const char *,...)
PVOID RtlpDphNormalHeapAllocate (PDPH_HEAP_ROOT Heap, ULONG Flags, SIZE_T Size)
BOOLEAN RtlpDphNormalHeapFree (PDPH_HEAP_ROOT Heap, ULONG Flags, PVOID Block)
PVOID RtlpDphNormalHeapReAllocate (PDPH_HEAP_ROOT Heap, ULONG Flags, PVOID OldBlock, SIZE_T Size)
SIZE_T RtlpDphNormalHeapSize (PDPH_HEAP_ROOT Heap, ULONG Flags, PVOID Block)
BOOLEAN RtlpDphNormalHeapSetUserFlags (IN PDPH_HEAP_ROOT Heap, IN ULONG Flags, IN PVOID Address, IN ULONG UserFlagsReset, IN ULONG UserFlagsSet)
BOOLEAN RtlpDphNormalHeapSetUserValue (IN PDPH_HEAP_ROOT Heap, IN ULONG Flags, IN PVOID Address, IN PVOID UserValue)
BOOLEAN RtlpDphNormalHeapGetUserInfo (IN PDPH_HEAP_ROOT Heap, IN ULONG Flags, IN PVOID Address, OUT PVOID *UserValue, OUT PULONG UserFlags)
BOOLEAN RtlpDphNormalHeapValidate (IN PDPH_HEAP_ROOT Heap, IN ULONG Flags, IN PVOID Address)
VOID RtlpDphReportCorruptedBlock (PVOID Block, ULONG Reason)
BOOLEAN RtlpDphIsNormalHeapBlock (PDPH_HEAP_ROOT Heap, PVOID Block, PULONG Reason, BOOLEAN CheckPattern)
BOOLEAN RtlpDphIsNormalFreeHeapBlock (PVOID Block, PULONG Reason, BOOLEAN CheckPattern)
BOOLEAN RtlpDphIsPageHeapBlock (PDPH_HEAP_ROOT Heap, PVOID Block, PULONG Reason, BOOLEAN CheckPattern)
BOOLEAN RtlpDphWriteNormalHeapBlockInformation (PDPH_HEAP_ROOT Heap, PVOID Block, SIZE_T RequestedSize, SIZE_T ActualSize)
BOOLEAN RtlpDphWritePageHeapBlockInformation (PDPH_HEAP_ROOT Heap, PVOID Block, SIZE_T RequestedSize, SIZE_T ActualSize)
VOID RtlpDphInitializeDelayedFreeQueue ()
VOID RtlpDphAddToDelayedFreeQueue (PDPH_BLOCK_INFORMATION Info)
BOOLEAN RtlpDphNeedToTrimDelayedFreeQueue (PSIZE_T TrimSize)
VOID RtlpDphTrimDelayedFreeQueue (SIZE_T TrimSize, ULONG Flags)
VOID RtlpDphFreeDelayedBlocksFromHeap (PVOID PageHeap, PVOID NormalHeap)
 RtlpDphShouldAllocateInPageHeap (PDPH_HEAP_ROOT Heap, SIZE_T Size)
PRTL_TRACE_BLOCK RtlpDphLogStackTrace (ULONG FramesToSkip)
VOID RtlpDebugPageHeapBreak (IN PCH Text)
BOOLEAN RtlpDebugPageHeapAssert (IN PCH Text)
VOID RtlpDebugPageHeapEnterCritSect (IN PDPH_HEAP_ROOT HeapRoot, IN ULONG Flags)
INLINE VOID RtlpDebugPageHeapLeaveCritSect (IN PDPH_HEAP_ROOT HeapRoot)
VOID RtlpDebugPageHeapException (IN ULONG ExceptionCode)
PVOID RtlpDebugPageHeapPointerFromHandle (IN PVOID HeapHandle)
PCCH RtlpDebugPageHeapProtectionText (IN ULONG Access, IN OUT PCHAR Buffer)
BOOLEAN RtlpDebugPageHeapRobustProtectVM (IN PVOID VirtualBase, IN SIZE_T VirtualSize, IN ULONG NewAccess, IN BOOLEAN Recursion)
INLINE BOOLEAN RtlpDebugPageHeapProtectVM (IN PVOID VirtualBase, IN SIZE_T VirtualSize, IN ULONG NewAccess)
INLINE PVOID RtlpDebugPageHeapAllocateVM (IN SIZE_T nSize)
INLINE BOOLEAN RtlpDebugPageHeapReleaseVM (IN PVOID pVirtual)
INLINE BOOLEAN RtlpDebugPageHeapCommitVM (IN PVOID pVirtual, IN SIZE_T nSize)
INLINE BOOLEAN RtlpDebugPageHeapDecommitVM (IN PVOID pVirtual, IN SIZE_T nSize)
VOID RtlpDphTargetDllsLogicInitialize ()
VOID RtlpDphTargetDllsLoadCallBack (PUNICODE_STRING Name, PVOID Address, ULONG Size)
const WCHAR * RtlpDphIsDllTargeted (const WCHAR *Name)
VOID RtlpDphInternalValidatePageHeap (PDPH_HEAP_ROOT Heap, PUCHAR ExemptAddress, SIZE_T ExemptSize)
PDPH_HEAP_BLOCK RtlpDebugPageHeapTakeNodeFromUnusedList (IN PDPH_HEAP_ROOT pHeap)
VOID RtlpDebugPageHeapReturnNodeToUnusedList (IN PDPH_HEAP_ROOT pHeap, IN PDPH_HEAP_BLOCK pNode)
PDPH_HEAP_BLOCK RtlpDebugPageHeapFindBusyMem (IN PDPH_HEAP_ROOT pHeap, IN PVOID pUserMem, OUT PDPH_HEAP_BLOCK *pPrevAlloc)
VOID RtlpDebugPageHeapRemoveFromAvailableList (IN PDPH_HEAP_ROOT pHeap, IN PDPH_HEAP_BLOCK pNode, IN PDPH_HEAP_BLOCK pPrev)
VOID RtlpDebugPageHeapPlaceOnFreeList (IN PDPH_HEAP_ROOT pHeap, IN PDPH_HEAP_BLOCK pAlloc)
VOID RtlpDebugPageHeapRemoveFromFreeList (IN PDPH_HEAP_ROOT pHeap, IN PDPH_HEAP_BLOCK pNode, IN PDPH_HEAP_BLOCK pPrev)
VOID RtlpDebugPageHeapPlaceOnVirtualList (IN PDPH_HEAP_ROOT pHeap, IN PDPH_HEAP_BLOCK pNode)
VOID RtlpDebugPageHeapPlaceOnBusyList (IN PDPH_HEAP_ROOT pHeap, IN PDPH_HEAP_BLOCK pNode)
VOID RtlpDebugPageHeapRemoveFromBusyList (IN PDPH_HEAP_ROOT pHeap, IN PDPH_HEAP_BLOCK pNode, IN PDPH_HEAP_BLOCK pPrev)
PDPH_HEAP_BLOCK RtlpDebugPageHeapSearchAvailableMemListForBestFit (IN PDPH_HEAP_ROOT pHeap, IN SIZE_T nSize, OUT PDPH_HEAP_BLOCK *pPrevAvailNode)
VOID RtlpDebugPageHeapCoalesceNodeIntoAvailable (IN PDPH_HEAP_ROOT pHeap, IN PDPH_HEAP_BLOCK pNode)
VOID RtlpDebugPageHeapCoalesceFreeIntoAvailable (IN PDPH_HEAP_ROOT pHeap, IN ULONG nLeaveOnFreeList)
BOOLEAN RtlpDebugPageHeapGrowVirtual (IN PDPH_HEAP_ROOT pHeap, IN SIZE_T nSize)
PDPH_HEAP_BLOCK RtlpDebugPageHeapFindAvailableMem (IN PDPH_HEAP_ROOT pHeap, IN SIZE_T nSize, OUT PDPH_HEAP_BLOCK *pPrevAvailNode, IN BOOLEAN bGrowVirtual)
VOID RtlpDebugPageHeapPlaceOnPoolList (IN PDPH_HEAP_ROOT pHeap, IN PDPH_HEAP_BLOCK pNode)
VOID RtlpDebugPageHeapAddNewPool (IN PDPH_HEAP_ROOT pHeap, IN PVOID pVirtual, IN SIZE_T nSize, IN BOOLEAN bAddToPoolList)
PDPH_HEAP_BLOCK RtlpDebugPageHeapAllocateNode (IN PDPH_HEAP_ROOT pHeap)
VOID RtlpDebugPageHeapProtectStructures (IN PDPH_HEAP_ROOT pHeap)
VOID RtlpDebugPageHeapUnProtectStructures (IN PDPH_HEAP_ROOT pHeap)
PVOID RtlpDebugPageHeapCreate (IN ULONG Flags, IN PVOID HeapBase OPTIONAL, IN SIZE_T ReserveSize OPTIONAL, IN SIZE_T CommitSize OPTIONAL, IN PVOID Lock OPTIONAL, IN PRTL_HEAP_PARAMETERS Parameters OPTIONAL)
PVOID RtlpDebugPageHeapAllocate (IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
BOOLEAN RtlpDebugPageHeapFree (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID Address)
PVOID RtlpDebugPageHeapReAllocate (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID Address, IN SIZE_T Size)
PVOID RtlpDebugPageHeapDestroy (IN PVOID HeapHandle)
SIZE_T RtlpDebugPageHeapSize (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID Address)
ULONG RtlpDebugPageHeapGetProcessHeaps (ULONG NumberOfHeaps, PVOID *ProcessHeaps)
ULONG RtlpDebugPageHeapCompact (IN PVOID HeapHandle, IN ULONG Flags)
BOOLEAN RtlpDebugPageHeapValidate (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID Address)
NTSTATUS RtlpDebugPageHeapWalk (IN PVOID HeapHandle, IN OUT PRTL_HEAP_WALK_ENTRY Entry)
BOOLEAN RtlpDebugPageHeapLock (IN PVOID HeapHandle)
BOOLEAN RtlpDebugPageHeapUnlock (IN PVOID HeapHandle)
BOOLEAN RtlpDebugPageHeapSetUserValue (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID Address, IN PVOID UserValue)
BOOLEAN RtlpDebugPageHeapGetUserInfo (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID Address, OUT PVOID *UserValue, OUT PULONG UserFlags)
BOOLEAN RtlpDebugPageHeapSetUserFlags (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID Address, IN ULONG UserFlagsReset, IN ULONG UserFlagsSet)
BOOLEAN RtlpDebugPageHeapSerialize (IN PVOID HeapHandle)
NTSTATUS RtlpDebugPageHeapExtend (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID Base, IN SIZE_T Size)
NTSTATUS RtlpDebugPageHeapZero (IN PVOID HeapHandle, IN ULONG Flags)
NTSTATUS RtlpDebugPageHeapReset (IN PVOID HeapHandle, IN ULONG Flags)
NTSTATUS RtlpDebugPageHeapUsage (IN PVOID HeapHandle, IN ULONG Flags, IN OUT PRTL_HEAP_USAGE Usage)
BOOLEAN RtlpDebugPageHeapIsLocked (IN PVOID HeapHandle)
PDPH_HEAP_BLOCK RtlpDphSearchBlockInList (PDPH_HEAP_BLOCK List, PUCHAR Address)

Variables

BOOLEAN RtlpDebugPageHeap
PCHAR RtlpDphVersion = "03/14/2000"
BOOLEAN RtlpDphHeapListHasBeenInitialized
RTL_CRITICAL_SECTION RtlpDphHeapListCriticalSection
PDPH_HEAP_ROOT RtlpDphHeapListHead
PDPH_HEAP_ROOT RtlpDphHeapListTail
ULONG RtlpDphHeapListCount
ULONG RtlpDphGlobalFlags = PAGE_HEAP_COLLECT_STACK_TRACES
ULONG RtlpDphSizeRangeStart
ULONG RtlpDphSizeRangeEnd
ULONG RtlpDphDllRangeStart
ULONG RtlpDphDllRangeEnd
ULONG RtlpDphRandomProbability
WCHAR RtlpDphTargetDlls [512]
UNICODE_STRING RtlpDphTargetDllsUnicode
ULONG RtlpDphDebugLevel
ULONG RtlpDphGlobalCounter [MAX_GLOBAL_COUNTER_INDEX+1]
ULONG RtlpDphSizeCounter [MAX_SIZE_COUNTER_INDEX+1]
SIZE_T RtlpDphDelayedFreeCacheSize = 256 * PAGE_SIZE
SIZE_T RtlpDphTraceDatabaseMaximumSize = 256 * PAGE_SIZE
PRTL_TRACE_DATABASE RtlpDphTraceDatabase
RTL_CRITICAL_SECTION RtlpDphDelayedFreeQueueLock
SIZE_T RtlpDphMemoryUsedByDelayedFreeBlocks
SIZE_T RtlpDphNumberOfDelayedFreeBlocks
LIST_ENTRY RtlpDphDelayedFreeQueue
RTL_CRITICAL_SECTION RtlpDphTargetDllsLock
LIST_ENTRY RtlpDphTargetDllsList
BOOLEAN RtlpDphTargetDllsInitialized
PVOID RtlpDphLastValidationStack
PVOID RtlpDphCurrentValidationStack


Define Documentation

#define BIAS_POINTER  )     ((PVOID)((ULONG_PTR)(p) | (ULONG_PTR)0x01))
 

Definition at line 162 of file heappage.c.

#define BUMP_GLOBAL_COUNTER n   )     InterlockedIncrement(&(RtlpDphGlobalCounter[n]))
 

Definition at line 273 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapReAllocate(), RtlpDphNormalHeapAllocate(), RtlpDphNormalHeapFree(), and RtlpDphNormalHeapReAllocate().

#define BUMP_SIZE_COUNTER Size   ) 
 

Value:

if (Size/128 <= MAX_SIZE_COUNTER_INDEX) { \ InterlockedIncrement(&(RtlpDphSizeCounter[Size/128])); \ } \ else { \ InterlockedIncrement(&(RtlpDphSizeCounter[MAX_SIZE_COUNTER_INDEX])); \ }

Definition at line 275 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapReAllocate(), RtlpDphNormalHeapAllocate(), and RtlpDphNormalHeapReAllocate().

#define DEBUG_ASSERT  )     DEBUG_CODE( RETAIL_ASSERT( a ))
 

Definition at line 114 of file heappage.c.

Referenced by RtlpDebugPageHeapAddNewPool(), RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCoalesceFreeIntoAvailable(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapFindAvailableMem(), RtlpDebugPageHeapProtectStructures(), RtlpDebugPageHeapReAllocate(), RtlpDebugPageHeapUnProtectStructures(), RtlpDphIsNormalFreeHeapBlock(), RtlpDphIsNormalHeapBlock(), and RtlpDphIsPageHeapBlock().

#define DEBUG_CODE  ) 
 

Definition at line 108 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapDestroy(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapReAllocate(), and RtlpDebugPageHeapValidate().

#define DEQUEUE_NODE Node,
Prev,
Head,
Tail   ) 
 

Value:

{ \ PVOID Next = (Node)->pNextAlloc; \ if ((Head) == (Node)) \ (Head) = Next; \ if ((Tail) == (Node)) \ (Tail) = (Prev); \ if ((Prev) != (NULL)) \ (Prev)->pNextAlloc = Next; \ }

Definition at line 148 of file heappage.c.

Referenced by RtlpDebugPageHeapRemoveFromAvailableList(), RtlpDebugPageHeapRemoveFromBusyList(), RtlpDebugPageHeapRemoveFromFreeList(), and RtlpDebugPageHeapTakeNodeFromUnusedList().

#define DPH_DEBUG_BREAK_FOR_NULL_FREE   0x0040
 

Definition at line 259 of file heappage.c.

Referenced by RtlpDebugPageHeapFree().

#define DPH_DEBUG_BREAK_FOR_SIZE_ZERO   0x0020
 

Definition at line 258 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), and RtlpDebugPageHeapReAllocate().

#define DPH_DEBUG_DECOMMIT_RANGES   0x0010
 

Definition at line 257 of file heappage.c.

Referenced by RtlpDebugPageHeapCommitVM(), and RtlpDebugPageHeapDecommitVM().

#define DPH_DEBUG_INTERNAL_VALIDATION   0x0001
 

Definition at line 253 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapFree(), and RtlpDebugPageHeapReAllocate().

#define DPH_DEBUG_NEVER_FREE   0x0080
 

Definition at line 260 of file heappage.c.

Referenced by RtlpDphNormalHeapFree().

#define DPH_DEBUG_RESERVED_2   0x0002
 

Definition at line 254 of file heappage.c.

#define DPH_DEBUG_RESERVED_4   0x0004
 

Definition at line 255 of file heappage.c.

#define DPH_DEBUG_RESERVED_8   0x0008
 

Definition at line 256 of file heappage.c.

#define DPH_DEBUG_SLOW_CHECKS   0x0100
 

Definition at line 261 of file heappage.c.

#define DPH_HEAP_SIGNATURE   0xFFEEDDCC
 

Definition at line 90 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapPointerFromHandle().

#define ENQUEUE_HEAD Node,
Head,
Tail   ) 
 

Value:

{ \ (Node)->pNextAlloc = (Head); \ if ((Head) == NULL ) \ (Tail) = (Node); \ (Head) = (Node); \ }

Definition at line 133 of file heappage.c.

Referenced by RtlpDebugPageHeapPlaceOnBusyList(), RtlpDebugPageHeapPlaceOnVirtualList(), and RtlpDebugPageHeapReturnNodeToUnusedList().

#define ENQUEUE_TAIL Node,
Head,
Tail   ) 
 

Value:

{ \ if ((Tail) == NULL ) \ (Head) = (Node); \ else \ (Tail)->pNextAlloc = (Node); \ (Tail) = (Node); \ }

Definition at line 140 of file heappage.c.

Referenced by RtlpDebugPageHeapAddNewPool(), RtlpDebugPageHeapPlaceOnFreeList(), and RtlpDebugPageHeapPlaceOnPoolList().

#define FILL_BYTE   0xEE
 

Definition at line 91 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate().

#define HEAD_FILL_SIZE   0x10
 

Definition at line 92 of file heappage.c.

#define HEAP_HANDLE_FROM_ROOT HeapRoot   )     ((PVOID)(((PCHAR)(HeapRoot)) - PAGE_SIZE ))
 

Definition at line 116 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapGetProcessHeaps().

#define IF_GENERATE_EXCEPTION Flags,
Status   ) 
 

Value:

{ \ if (( Flags ) & HEAP_GENERATE_EXCEPTIONS ) \ RtlpDebugPageHeapException((ULONG)(Status)); \ }

Definition at line 119 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapReAllocate(), and RtlpDebugPageHeapSize().

#define INLINE   __inline
 

Definition at line 96 of file heappage.c.

#define IS_BIASED_POINTER  )     ((PVOID)((ULONG_PTR)(p) & (ULONG_PTR)0x01))
 

Definition at line 164 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), and RtlpDebugPageHeapReAllocate().

#define MAX_GLOBAL_COUNTER_INDEX   15
 

Definition at line 282 of file heappage.c.

#define MAX_SIZE_COUNTER_INDEX   64
 

Definition at line 283 of file heappage.c.

#define MIN_FREE_LIST_LENGTH   8
 

Definition at line 97 of file heappage.c.

Referenced by RtlpDebugPageHeapFindAvailableMem().

#define OUT_OF_VM_BREAK Flags,
szText   ) 
 

Value:

{ \ if (( Flags ) & HEAP_BREAK_WHEN_OUT_OF_VM ) \ RtlpDebugPageHeapBreak(( szText )); \ }

Definition at line 124 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapReAllocate().

#define POOL_SIZE   0x4000
 

Definition at line 95 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocateNode(), and RtlpDebugPageHeapCreate().

#define PROTECT_HEAP_STRUCTURES HeapRoot   ) 
 

Value:

{ \ if ((HeapRoot)->HeapFlags & HEAP_PROTECTION_ENABLED ) \ RtlpDebugPageHeapProtectStructures( (HeapRoot) ); \ }

Definition at line 170 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapGetUserInfo(), RtlpDebugPageHeapReAllocate(), RtlpDebugPageHeapSerialize(), RtlpDebugPageHeapSetUserFlags(), RtlpDebugPageHeapSetUserValue(), RtlpDebugPageHeapSize(), RtlpDebugPageHeapUsage(), and RtlpDebugPageHeapValidate().

#define RESERVE_SIZE   0x100000
 

Definition at line 93 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapGrowVirtual().

#define RETAIL_ASSERT  ) 
 

Value:

( (a) ? TRUE : \ RtlpDebugPageHeapAssert( "Page heap: assert: (" #a ")\n" ))

Definition at line 111 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapReAllocate().

#define ROUNDUP2 x,
n   )     ((( x ) + (( n ) - 1 )) & ~(( n ) - 1 ))
 

Definition at line 103 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapGrowVirtual(), RtlpDebugPageHeapRobustProtectVM(), RtlpDphIsPageHeapBlock(), and RtlpDphWritePageHeapBlockInformation().

#define UNBIAS_POINTER  )     ((PVOID)((ULONG_PTR)(p) & ~((ULONG_PTR)0x01)))
 

Definition at line 163 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), and RtlpDebugPageHeapReAllocate().

#define UNPROTECT_HEAP_STRUCTURES HeapRoot   ) 
 

Value:

{ \ if ((HeapRoot)->HeapFlags & HEAP_PROTECTION_ENABLED ) \ RtlpDebugPageHeapUnProtectStructures( (HeapRoot) ); \ }

Definition at line 175 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapDestroy(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapGetUserInfo(), RtlpDebugPageHeapReAllocate(), RtlpDebugPageHeapSerialize(), RtlpDebugPageHeapSetUserFlags(), RtlpDebugPageHeapSetUserValue(), RtlpDebugPageHeapSize(), RtlpDebugPageHeapUsage(), and RtlpDebugPageHeapValidate().

#define VM_UNIT_SIZE   0x10000
 

Definition at line 94 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapGrowVirtual().


Typedef Documentation

typedef struct _DPH_TARGET_DLL DPH_TARGET_DLL
 

typedef struct _DPH_TARGET_DLL * PDPH_TARGET_DLL
 

Referenced by RtlpDphTargetDllsLoadCallBack().


Function Documentation

VOID RtlpDebugPageHeapAddNewPool IN PDPH_HEAP_ROOT  pHeap,
IN PVOID  pVirtual,
IN SIZE_T  nSize,
IN BOOLEAN  bAddToPoolList
 

Definition at line 1518 of file heappage.c.

References DEBUG_ASSERT, ENQUEUE_TAIL, n, NULL, RtlpDebugPageHeapPlaceOnPoolList(), and RtlpDebugPageHeapTakeNodeFromUnusedList().

Referenced by RtlpDebugPageHeapAllocateNode(), and RtlpDebugPageHeapCreate().

01524 { 01525 PDPH_HEAP_BLOCK pNode, pFirst; 01526 ULONG n, nCount; 01527 01528 // 01529 // Assume pVirtual points to committed block of nSize bytes. 01530 // 01531 01532 pFirst = pVirtual; 01533 nCount = (ULONG)(nSize / sizeof( DPH_HEAP_BLOCK )); 01534 01535 for (n = nCount - 1, pNode = pFirst; n > 0; pNode++, n--) 01536 pNode->pNextAlloc = pNode + 1; 01537 01538 pNode->pNextAlloc = NULL; 01539 01540 // 01541 // Now link this list into the tail of the UnusedNodeList 01542 // 01543 01544 ENQUEUE_TAIL( pFirst, pHeap->pUnusedNodeListHead, pHeap->pUnusedNodeListTail ); 01545 01546 pHeap->pUnusedNodeListTail = pNode; 01547 01548 pHeap->nUnusedNodes += nCount; 01549 01550 if (bAddToPoolList) { 01551 01552 // 01553 // Now add an entry on the PoolList by taking a node from the 01554 // UnusedNodeList, which should be guaranteed to be non-empty 01555 // since we just added new nodes to it. 01556 // 01557 01558 pNode = RtlpDebugPageHeapTakeNodeFromUnusedList( pHeap ); 01559 01560 DEBUG_ASSERT( pNode != NULL ); 01561 01562 pNode->pVirtualBlock = pVirtual; 01563 pNode->nVirtualBlockSize = nSize; 01564 01565 RtlpDebugPageHeapPlaceOnPoolList( pHeap, pNode ); 01566 01567 } 01568 }

PVOID RtlpDebugPageHeapAllocate IN PVOID  HeapHandle,
IN ULONG  Flags,
IN SIZE_T  Size
 

Definition at line 2336 of file heappage.c.

References BUMP_GLOBAL_COUNTER, BUMP_SIZE_COUNTER, DbgPrint, DEBUG_ASSERT, DEBUG_CODE, DPH_DEBUG_BREAK_FOR_SIZE_ZERO, DPH_DEBUG_INTERNAL_VALIDATION, EXIT, FALSE, HEAP_NO_ALIGNMENT, HeapHandle, IF_GENERATE_EXCEPTION, IS_BIASED_POINTER, NULL, OUT_OF_VM_BREAK, PAGE_SIZE, PROTECT_HEAP_STRUCTURES, ROUNDUP2, RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapDecommitVM(), RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapFindAvailableMem(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPlaceOnBusyList(), RtlpDebugPageHeapPointerFromHandle(), RtlpDebugPageHeapProtectVM(), RtlpDebugPageHeapRemoveFromAvailableList(), RtlpDphDebugLevel, RtlpDphInternalValidatePageHeap(), RtlpDphLogStackTrace(), RtlpDphNormalHeapAllocate(), RtlpDphShouldAllocateInPageHeap(), RtlpDphTraceDatabase, RtlpDphWritePageHeapBlockInformation(), Size, TRUE, UNBIAS_POINTER, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlDebugAllocateHeap(), RtlpDebugPageHeapReAllocate(), RtlpDphDllcalloc(), RtlpDphDllGlobalAlloc(), RtlpDphDllHeapAlloc(), RtlpDphDllLocalAlloc(), RtlpDphDllmalloc(), RtlpDphDllNew(), RtlpDphDllNewArray(), and RtlpDphDllrealloc().

02341 { 02342 PDPH_HEAP_ROOT HeapRoot; 02343 PDPH_HEAP_BLOCK pAvailNode; 02344 PDPH_HEAP_BLOCK pPrevAvailNode; 02345 PDPH_HEAP_BLOCK pBusyNode; 02346 SIZE_T nBytesAllocate; 02347 SIZE_T nBytesAccess; 02348 SIZE_T nActual; 02349 PVOID pVirtual; 02350 PVOID pReturn; 02351 PUCHAR pBlockHeader; 02352 ULONG Reason; 02353 BOOLEAN ForcePageHeap = FALSE; 02354 02355 if (IS_BIASED_POINTER(HeapHandle)) { 02356 HeapHandle = UNBIAS_POINTER(HeapHandle); 02357 ForcePageHeap = TRUE; 02358 } 02359 02360 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 02361 if (HeapRoot == NULL) 02362 return NULL; 02363 02364 // 02365 // Is zero size allocation ? 02366 // 02367 02368 if (Size == 0) { 02369 02370 if ((RtlpDphDebugLevel & DPH_DEBUG_BREAK_FOR_SIZE_ZERO)) { 02371 02372 DbgPrint ("Page heap: request for zero sized block \n"); 02373 DbgBreakPoint(); 02374 } 02375 } 02376 02377 // 02378 // Get the heap lock. 02379 // 02380 02381 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 02382 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 02383 02384 // 02385 // We cannot validate the heap when a forced allocation into page heap 02386 // is requested due to accounting problems. Allocate is called in this way 02387 // from ReAllocate while the old node (just about to be freed) is in limbo 02388 // and is not accounted in any internal structure. 02389 // 02390 02391 if ((RtlpDphDebugLevel & DPH_DEBUG_INTERNAL_VALIDATION) && !ForcePageHeap) { 02392 RtlpDphInternalValidatePageHeap (HeapRoot, NULL, 0); 02393 } 02394 02395 Flags |= HeapRoot->HeapFlags; 02396 02397 // 02398 // Compute alloc statistics. Note that we need to 02399 // take the heap lock for this and unprotect the 02400 // heap structures. 02401 // 02402 02403 BUMP_GLOBAL_COUNTER (DPH_COUNTER_NO_OF_ALLOCS); 02404 BUMP_SIZE_COUNTER (Size); 02405 02406 HeapRoot->Counter[DPH_COUNTER_NO_OF_ALLOCS] += 1; 02407 02408 if (Size < 1024) { 02409 BUMP_GLOBAL_COUNTER (DPH_COUNTER_SIZE_BELOW_1K); 02410 HeapRoot->Counter[DPH_COUNTER_SIZE_BELOW_1K] += 1; 02411 } 02412 else if (Size < 4096) { 02413 BUMP_GLOBAL_COUNTER (DPH_COUNTER_SIZE_BELOW_4K); 02414 HeapRoot->Counter[DPH_COUNTER_SIZE_BELOW_4K] += 1; 02415 } 02416 else { 02417 BUMP_GLOBAL_COUNTER (DPH_COUNTER_SIZE_ABOVE_4K); 02418 HeapRoot->Counter[DPH_COUNTER_SIZE_ABOVE_4K] += 1; 02419 } 02420 02421 // 02422 // Figure out if we need to minimize memory impact. This 02423 // might trigger an allocation in the normal heap. 02424 // 02425 02426 if (! ForcePageHeap) { 02427 02428 if (! (RtlpDphShouldAllocateInPageHeap (HeapRoot, Size))) { 02429 02430 pReturn = RtlpDphNormalHeapAllocate ( 02431 HeapRoot, 02432 Flags, 02433 Size); 02434 02435 goto EXIT; 02436 } 02437 } 02438 02439 // 02440 // Check the heap a little bit on checked builds. 02441 // 02442 02443 DEBUG_CODE( RtlpDebugPageHeapVerifyIntegrity( HeapRoot )); 02444 02445 pReturn = NULL; 02446 02447 // 02448 // Validate requested size so we don't overflow 02449 // while rounding up size computations. We do this 02450 // after we've acquired the critsect so we can still 02451 // catch serialization problems. 02452 // 02453 02454 if (Size > 0x7FFF0000) { 02455 OUT_OF_VM_BREAK( Flags, "Page heap: Invalid allocation size\n" ); 02456 goto EXIT; 02457 } 02458 02459 // 02460 // Determine number of pages needed for READWRITE portion 02461 // of allocation and add an extra page for the NO_ACCESS 02462 // memory beyond the READWRITE page(s). 02463 // 02464 02465 nBytesAccess = ROUNDUP2( Size + sizeof(DPH_BLOCK_INFORMATION), PAGE_SIZE ); 02466 nBytesAllocate = nBytesAccess + PAGE_SIZE; 02467 02468 // 02469 // RtlpDebugPageHeapFindAvailableMem will first attempt to satisfy 02470 // the request from memory on the Available list. If that fails, 02471 // it will coalesce some of the Free list memory into the Available 02472 // list and try again. If that still fails, new VM is allocated and 02473 // added to the Available list. If that fails, the function will 02474 // finally give up and return NULL. 02475 // 02476 02477 pAvailNode = RtlpDebugPageHeapFindAvailableMem( 02478 HeapRoot, 02479 nBytesAllocate, 02480 &pPrevAvailNode, 02481 TRUE 02482 ); 02483 02484 if (pAvailNode == NULL) { 02485 OUT_OF_VM_BREAK( Flags, "Page heap: Unable to allocate virtual memory\n" ); 02486 goto EXIT; 02487 } 02488 02489 // 02490 // Now can't call AllocateNode until pAvailNode is 02491 // adjusted and/or removed from Avail list since AllocateNode 02492 // might adjust the Avail list. 02493 // 02494 02495 pVirtual = pAvailNode->pVirtualBlock; 02496 02497 if (nBytesAccess > 0) { 02498 02499 if ((HeapRoot->ExtraFlags & PAGE_HEAP_CATCH_BACKWARD_OVERRUNS)) { 02500 02501 if (! RtlpDebugPageHeapProtectVM( (PUCHAR)pVirtual + PAGE_SIZE, nBytesAccess, PAGE_READWRITE )) { 02502 goto EXIT; 02503 } 02504 } 02505 else { 02506 02507 if (! RtlpDebugPageHeapProtectVM( pVirtual, nBytesAccess, PAGE_READWRITE )) { 02508 goto EXIT; 02509 } 02510 } 02511 } 02512 02513 // 02514 // If we use uncommitted ranges we need to decommit the protection 02515 // page at the end. BAckward overruns flag disables smart memory 02516 // usage flag. 02517 // 02518 02519 if ((HeapRoot->ExtraFlags & PAGE_HEAP_CATCH_BACKWARD_OVERRUNS)) { 02520 02521 // nothing 02522 02523 } 02524 else { 02525 02526 if ((HeapRoot->ExtraFlags & PAGE_HEAP_SMART_MEMORY_USAGE)) { 02527 02528 RtlpDebugPageHeapDecommitVM ( 02529 (PCHAR)pVirtual + nBytesAccess, 02530 PAGE_SIZE); 02531 } 02532 } 02533 02534 // 02535 // pAvailNode (still on avail list) points to block large enough 02536 // to satisfy request, but it might be large enough to split 02537 // into two blocks -- one for request, remainder leave on 02538 // avail list. 02539 // 02540 02541 if (pAvailNode->nVirtualBlockSize > nBytesAllocate) { 02542 02543 // 02544 // Adjust pVirtualBlock and nVirtualBlock size of existing 02545 // node in avail list. The node will still be in correct 02546 // address space order on the avail list. This saves having 02547 // to remove and then re-add node to avail list. Note since 02548 // we're changing sizes directly, we need to adjust the 02549 // avail and busy list counters manually. 02550 // 02551 // Note: since we're leaving at least one page on the 02552 // available list, we are guaranteed that AllocateNode 02553 // will not fail. 02554 // 02555 02556 pAvailNode->pVirtualBlock += nBytesAllocate; 02557 pAvailNode->nVirtualBlockSize -= nBytesAllocate; 02558 HeapRoot->nAvailableAllocationBytesCommitted -= nBytesAllocate; 02559 02560 pBusyNode = RtlpDebugPageHeapAllocateNode( HeapRoot ); 02561 02562 DEBUG_ASSERT( pBusyNode != NULL ); 02563 02564 pBusyNode->pVirtualBlock = pVirtual; 02565 pBusyNode->nVirtualBlockSize = nBytesAllocate; 02566 02567 } 02568 02569 else { 02570 02571 // 02572 // Entire avail block is needed, so simply remove it from avail list. 02573 // 02574 02575 RtlpDebugPageHeapRemoveFromAvailableList( HeapRoot, pAvailNode, pPrevAvailNode ); 02576 02577 pBusyNode = pAvailNode; 02578 02579 } 02580 02581 // 02582 // Now pBusyNode points to our committed virtual block. 02583 // 02584 02585 if (HeapRoot->HeapFlags & HEAP_NO_ALIGNMENT) 02586 nActual = Size; 02587 else 02588 nActual = ROUNDUP2( Size, USER_ALIGNMENT ); 02589 02590 pBusyNode->nVirtualAccessSize = nBytesAccess; 02591 pBusyNode->nUserRequestedSize = Size; 02592 pBusyNode->nUserActualSize = nActual; 02593 02594 if ((HeapRoot->ExtraFlags & PAGE_HEAP_CATCH_BACKWARD_OVERRUNS)) { 02595 02596 pBusyNode->pUserAllocation = pBusyNode->pVirtualBlock 02597 + PAGE_SIZE; 02598 } 02599 else { 02600 02601 pBusyNode->pUserAllocation = pBusyNode->pVirtualBlock 02602 + pBusyNode->nVirtualAccessSize 02603 - nActual; 02604 } 02605 02606 pBusyNode->UserValue = NULL; 02607 pBusyNode->UserFlags = Flags & HEAP_SETTABLE_USER_FLAGS; 02608 02609 // 02610 // RtlpDebugPageHeapAllocate gets called from RtlDebugAllocateHeap, 02611 // which gets called from RtlAllocateHeapSlowly, which gets called 02612 // from RtlAllocateHeap. To keep from wasting lots of stack trace 02613 // storage, we'll skip the bottom 3 entries, leaving RtlAllocateHeap 02614 // as the first recorded entry. 02615 // 02616 02617 if ((HeapRoot->ExtraFlags & PAGE_HEAP_COLLECT_STACK_TRACES)) { 02618 02619 pBusyNode->StackTrace = RtlpDphLogStackTrace(3); 02620 02621 if (pBusyNode->StackTrace) { 02622 02623 RtlTraceDatabaseLock (RtlpDphTraceDatabase); 02624 pBusyNode->StackTrace->UserCount += 1; 02625 pBusyNode->StackTrace->UserSize += pBusyNode->nUserRequestedSize; 02626 pBusyNode->StackTrace->UserContext = HeapRoot; 02627 RtlTraceDatabaseUnlock (RtlpDphTraceDatabase); 02628 } 02629 } 02630 else { 02631 pBusyNode->StackTrace = NULL; 02632 } 02633 02634 RtlpDebugPageHeapPlaceOnBusyList( HeapRoot, pBusyNode ); 02635 02636 pReturn = pBusyNode->pUserAllocation; 02637 02638 // 02639 // For requests the specify HEAP_ZERO_MEMORY, we'll fill the 02640 // user-requested portion of the block with zeros. For requests 02641 // that don't specify HEAP_ZERO_MEMORY, we fill the whole user block 02642 // with DPH_PAGE_BLOCK_INFIX. 02643 // 02644 02645 if ((Flags & HEAP_ZERO_MEMORY)) { 02646 02647 // 02648 // SilviuC: The call below can be saved if we have a way 02649 // to figure out if the memory for the block was freshly 02650 // virtual allocated (this is already zeroed). This has 02651 // an impact for large allocations. 02652 // 02653 02654 RtlZeroMemory( pBusyNode->pUserAllocation, Size ); 02655 } 02656 else { 02657 02658 RtlFillMemory( pBusyNode->pUserAllocation, Size, DPH_PAGE_BLOCK_INFIX); 02659 } 02660 02661 if ((HeapRoot->ExtraFlags & PAGE_HEAP_CATCH_BACKWARD_OVERRUNS)) { 02662 02663 // nothing 02664 02665 } 02666 else { 02667 02668 RtlpDphWritePageHeapBlockInformation ( 02669 HeapRoot, 02670 pBusyNode->pUserAllocation, 02671 Size, 02672 nBytesAccess); 02673 } 02674 02675 EXIT: 02676 02677 if ((RtlpDphDebugLevel & DPH_DEBUG_INTERNAL_VALIDATION) && !ForcePageHeap) { 02678 RtlpDphInternalValidatePageHeap (HeapRoot, NULL, 0); 02679 } 02680 02681 PROTECT_HEAP_STRUCTURES( HeapRoot ); 02682 DEBUG_CODE( RtlpDebugPageHeapVerifyIntegrity( HeapRoot )); 02683 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 02684 02685 if (pReturn == NULL) { 02686 IF_GENERATE_EXCEPTION( Flags, STATUS_NO_MEMORY ); 02687 } 02688 02689 return pReturn; 02690 }

PDPH_HEAP_BLOCK RtlpDebugPageHeapAllocateNode IN PDPH_HEAP_ROOT  pHeap  ) 
 

Definition at line 1571 of file heappage.c.

References DEBUG_ASSERT, DEBUG_CODE, EXIT, FALSE, NULL, PAGE_SIZE, POOL_SIZE, RESERVE_SIZE, RtlpDebugPageHeapAddNewPool(), RtlpDebugPageHeapAllocateVM(), RtlpDebugPageHeapCoalesceNodeIntoAvailable(), RtlpDebugPageHeapFindAvailableMem(), RtlpDebugPageHeapPlaceOnVirtualList(), RtlpDebugPageHeapProtectVM(), RtlpDebugPageHeapReleaseVM(), RtlpDebugPageHeapRemoveFromAvailableList(), RtlpDebugPageHeapReturnNodeToUnusedList(), RtlpDebugPageHeapTakeNodeFromUnusedList(), TRUE, and VM_UNIT_SIZE.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapGrowVirtual().

01574 { 01575 PDPH_HEAP_BLOCK pNode, pPrev, pReturn; 01576 PUCHAR pVirtual; 01577 SIZE_T nVirtual; 01578 SIZE_T nRequest; 01579 01580 DEBUG_ASSERT( ! pHeap->InsideAllocateNode ); 01581 DEBUG_CODE( pHeap->InsideAllocateNode = TRUE ); 01582 01583 pReturn = NULL; 01584 01585 if (pHeap->pUnusedNodeListHead == NULL) { 01586 01587 // 01588 // We're out of nodes -- allocate new node pool 01589 // from AvailableList. Set bGrowVirtual to FALSE 01590 // since growing virtual will require new nodes, causing 01591 // recursion. Note that simply calling FindAvailableMem 01592 // might return some nodes to the pUnusedNodeList, even if 01593 // the call fails, so we'll check that the UnusedNodeList 01594 // is still empty before we try to use or allocate more 01595 // memory. 01596 // 01597 01598 nRequest = POOL_SIZE; 01599 01600 pNode = RtlpDebugPageHeapFindAvailableMem( 01601 pHeap, 01602 nRequest, 01603 &pPrev, 01604 FALSE 01605 ); 01606 01607 if (( pHeap->pUnusedNodeListHead == NULL ) && ( pNode == NULL )) { 01608 01609 // 01610 // Reduce request size to PAGE_SIZE and see if 01611 // we can find at least a page on the available 01612 // list. 01613 // 01614 01615 nRequest = PAGE_SIZE; 01616 01617 pNode = RtlpDebugPageHeapFindAvailableMem( 01618 pHeap, 01619 nRequest, 01620 &pPrev, 01621 FALSE 01622 ); 01623 01624 } 01625 01626 if (pHeap->pUnusedNodeListHead == NULL) { 01627 01628 if (pNode == NULL) { 01629 01630 // 01631 // Insufficient memory on Available list. Try allocating a 01632 // new virtual block. 01633 // 01634 01635 nRequest = POOL_SIZE; 01636 nVirtual = RESERVE_SIZE; 01637 pVirtual = RtlpDebugPageHeapAllocateVM( nVirtual ); 01638 01639 if (pVirtual == NULL) { 01640 01641 // 01642 // Unable to allocate full RESERVE_SIZE block, 01643 // so reduce request to single VM unit (64K) 01644 // and try again. 01645 // 01646 01647 nVirtual = VM_UNIT_SIZE; 01648 pVirtual = RtlpDebugPageHeapAllocateVM( nVirtual ); 01649 01650 if (pVirtual == NULL) { 01651 01652 // 01653 // Can't allocate any VM. 01654 // 01655 01656 goto EXIT; 01657 } 01658 } 01659 } 01660 01661 else { 01662 01663 RtlpDebugPageHeapRemoveFromAvailableList( pHeap, pNode, pPrev ); 01664 01665 pVirtual = pNode->pVirtualBlock; 01666 nVirtual = pNode->nVirtualBlockSize; 01667 01668 } 01669 01670 // 01671 // We now have allocated VM referenced by pVirtual,nVirtual. 01672 // Make nRequest portion of VM accessible for new node pool. 01673 // 01674 01675 if (! RtlpDebugPageHeapProtectVM( pVirtual, nRequest, PAGE_READWRITE )) { 01676 01677 if (pNode == NULL) { 01678 RtlpDebugPageHeapReleaseVM( pVirtual ); 01679 } 01680 else { 01681 RtlpDebugPageHeapCoalesceNodeIntoAvailable( pHeap, pNode ); 01682 } 01683 01684 goto EXIT; 01685 } 01686 01687 // 01688 // Now we have accessible memory for new pool. Add the 01689 // new memory to the pool. If the new memory came from 01690 // AvailableList versus fresh VM, zero the memory first. 01691 // 01692 01693 if (pNode != NULL) { 01694 RtlZeroMemory( pVirtual, nRequest ); 01695 } 01696 01697 RtlpDebugPageHeapAddNewPool( pHeap, pVirtual, nRequest, TRUE ); 01698 01699 // 01700 // If any memory remaining, put it on available list. 01701 // 01702 01703 if (pNode == NULL) { 01704 01705 // 01706 // Memory came from new VM -- add appropriate list entries 01707 // for new VM and add remainder of VM to free list. 01708 // 01709 01710 pNode = RtlpDebugPageHeapTakeNodeFromUnusedList( pHeap ); 01711 DEBUG_ASSERT( pNode != NULL ); 01712 pNode->pVirtualBlock = pVirtual; 01713 pNode->nVirtualBlockSize = nVirtual; 01714 RtlpDebugPageHeapPlaceOnVirtualList( pHeap, pNode ); 01715 01716 pNode = RtlpDebugPageHeapTakeNodeFromUnusedList( pHeap ); 01717 DEBUG_ASSERT( pNode != NULL ); 01718 pNode->pVirtualBlock = pVirtual + nRequest; 01719 pNode->nVirtualBlockSize = nVirtual - nRequest; 01720 01721 RtlpDebugPageHeapCoalesceNodeIntoAvailable( pHeap, pNode ); 01722 01723 } 01724 01725 else { 01726 01727 if (pNode->nVirtualBlockSize > nRequest) { 01728 01729 pNode->pVirtualBlock += nRequest; 01730 pNode->nVirtualBlockSize -= nRequest; 01731 01732 RtlpDebugPageHeapCoalesceNodeIntoAvailable( pHeap, pNode ); 01733 } 01734 01735 else { 01736 01737 // 01738 // Used up entire available block -- return node to 01739 // unused list. 01740 // 01741 01742 RtlpDebugPageHeapReturnNodeToUnusedList( pHeap, pNode ); 01743 01744 } 01745 } 01746 } 01747 } 01748 01749 pReturn = RtlpDebugPageHeapTakeNodeFromUnusedList( pHeap ); 01750 DEBUG_ASSERT( pReturn != NULL ); 01751 01752 EXIT: 01753 01754 DEBUG_CODE( pHeap->InsideAllocateNode = FALSE ); 01755 return pReturn; 01756 }

INLINE PVOID RtlpDebugPageHeapAllocateVM IN SIZE_T  nSize  ) 
 

Definition at line 842 of file heappage.c.

References NT_SUCCESS, NTSTATUS(), NULL, and Status.

Referenced by RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapGrowVirtual().

00845 { 00846 NTSTATUS Status; 00847 PVOID pVirtual; 00848 00849 pVirtual = NULL; 00850 00851 Status = ZwAllocateVirtualMemory( NtCurrentProcess(), 00852 &pVirtual, 00853 0, 00854 &nSize, 00855 MEM_COMMIT, 00856 PAGE_NOACCESS ); 00857 00858 return NT_SUCCESS( Status ) ? pVirtual : NULL; 00859 }

BOOLEAN RtlpDebugPageHeapAssert IN PCH  Text  ) 
 

Definition at line 618 of file heappage.c.

References FALSE, and RtlpDebugPageHeapBreak().

00621 { 00622 RtlpDebugPageHeapBreak( Text ); 00623 return FALSE; 00624 }

VOID RtlpDebugPageHeapBreak IN PCH  Text  ) 
 

Definition at line 609 of file heappage.c.

References DbgPrint.

00612 { 00613 DbgPrint( Text ); 00614 DbgBreakPoint(); 00615 }

VOID RtlpDebugPageHeapCoalesceFreeIntoAvailable IN PDPH_HEAP_ROOT  pHeap,
IN ULONG  nLeaveOnFreeList
 

Definition at line 1322 of file heappage.c.

References DEBUG_ASSERT, NULL, RtlpDebugPageHeapCoalesceNodeIntoAvailable(), and RtlpDebugPageHeapRemoveFromFreeList().

Referenced by RtlpDebugPageHeapFindAvailableMem().

01326 { 01327 PDPH_HEAP_BLOCK pNode = pHeap->pFreeAllocationListHead; 01328 SIZE_T nFree = pHeap->nFreeAllocations; 01329 PDPH_HEAP_BLOCK pNext; 01330 01331 DEBUG_ASSERT( nFree >= nLeaveOnFreeList ); 01332 01333 while (( pNode ) && ( nFree-- > nLeaveOnFreeList )) { 01334 01335 pNext = pNode->pNextAlloc; // preserve next pointer across shuffling 01336 01337 RtlpDebugPageHeapRemoveFromFreeList( pHeap, pNode, NULL ); 01338 01339 RtlpDebugPageHeapCoalesceNodeIntoAvailable( pHeap, pNode ); 01340 01341 pNode = pNext; 01342 01343 } 01344 01345 DEBUG_ASSERT(( nFree = (volatile SIZE_T)( pHeap->nFreeAllocations )) >= nLeaveOnFreeList ); 01346 DEBUG_ASSERT(( pNode != NULL ) || ( nFree == 0 )); 01347 01348 }

VOID RtlpDebugPageHeapCoalesceNodeIntoAvailable IN PDPH_HEAP_ROOT  pHeap,
IN PDPH_HEAP_BLOCK  pNode
 

Definition at line 1211 of file heappage.c.

References NULL, and RtlpDebugPageHeapReturnNodeToUnusedList().

Referenced by RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCoalesceFreeIntoAvailable(), RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapGrowVirtual().

01215 { 01216 PDPH_HEAP_BLOCK pPrev; 01217 PDPH_HEAP_BLOCK pNext; 01218 PUCHAR pVirtual; 01219 SIZE_T nVirtual; 01220 01221 pPrev = NULL; 01222 pNext = pHeap->pAvailableAllocationListHead; 01223 01224 pVirtual = pNode->pVirtualBlock; 01225 nVirtual = pNode->nVirtualBlockSize; 01226 01227 pHeap->nAvailableAllocationBytesCommitted += nVirtual; 01228 pHeap->nAvailableAllocations += 1; 01229 01230 // 01231 // Walk list to insertion point. 01232 // 01233 01234 while (( pNext ) && ( pNext->pVirtualBlock < pVirtual )) { 01235 pPrev = pNext; 01236 pNext = pNext->pNextAlloc; 01237 } 01238 01239 if (pPrev) { 01240 01241 if (( pPrev->pVirtualBlock + pPrev->nVirtualBlockSize ) == pVirtual) { 01242 01243 // 01244 // pPrev and pNode are adjacent, so simply add size of 01245 // pNode entry to pPrev entry. 01246 // 01247 01248 pPrev->nVirtualBlockSize += nVirtual; 01249 01250 RtlpDebugPageHeapReturnNodeToUnusedList( pHeap, pNode ); 01251 01252 pHeap->nAvailableAllocations--; 01253 01254 pNode = pPrev; 01255 pVirtual = pPrev->pVirtualBlock; 01256 nVirtual = pPrev->nVirtualBlockSize; 01257 01258 } 01259 01260 else { 01261 01262 // 01263 // pPrev and pNode are not adjacent, so insert the pNode 01264 // block into the list after pPrev. 01265 // 01266 01267 pNode->pNextAlloc = pPrev->pNextAlloc; 01268 pPrev->pNextAlloc = pNode; 01269 01270 } 01271 } 01272 01273 else { 01274 01275 // 01276 // pNode should be inserted at head of list. 01277 // 01278 01279 pNode->pNextAlloc = pHeap->pAvailableAllocationListHead; 01280 pHeap->pAvailableAllocationListHead = pNode; 01281 01282 } 01283 01284 01285 if (pNext) { 01286 01287 if (( pVirtual + nVirtual ) == pNext->pVirtualBlock) { 01288 01289 // 01290 // pNode and pNext are adjacent, so simply add size of 01291 // pNext entry to pNode entry and remove pNext entry 01292 // from the list. 01293 // 01294 01295 pNode->nVirtualBlockSize += pNext->nVirtualBlockSize; 01296 01297 pNode->pNextAlloc = pNext->pNextAlloc; 01298 01299 if (pHeap->pAvailableAllocationListTail == pNext) { 01300 pHeap->pAvailableAllocationListTail = pNode; 01301 } 01302 01303 RtlpDebugPageHeapReturnNodeToUnusedList( pHeap, pNext ); 01304 01305 pHeap->nAvailableAllocations--; 01306 01307 } 01308 } 01309 01310 else { 01311 01312 // 01313 // pNode is tail of list. 01314 // 01315 01316 pHeap->pAvailableAllocationListTail = pNode; 01317 01318 } 01319 }

INLINE BOOLEAN RtlpDebugPageHeapCommitVM IN PVOID  pVirtual,
IN SIZE_T  nSize
 

Definition at line 877 of file heappage.c.

References DbgPrint, DPH_DEBUG_DECOMMIT_RANGES, FALSE, NT_SUCCESS, NTSTATUS(), PAGE_SIZE, RtlpDphDebugLevel, Status, and TRUE.

Referenced by RtlpDebugPageHeapFindAvailableMem().

00881 { 00882 PCHAR pStart, pEnd, pCurrent; 00883 NTSTATUS Status; 00884 SIZE_T CommitSize; 00885 BOOLEAN Failed = FALSE; 00886 00887 pStart = (PCHAR)((ULONG_PTR)pVirtual & ~(PAGE_SIZE - 1)); 00888 pEnd = (PCHAR)(((ULONG_PTR)pVirtual + nSize) & ~(PAGE_SIZE - 1)); 00889 00890 for (pCurrent = pStart; pCurrent < pEnd; pCurrent += PAGE_SIZE) { 00891 00892 CommitSize = PAGE_SIZE; 00893 00894 Status = ZwAllocateVirtualMemory( 00895 NtCurrentProcess(), 00896 &pCurrent, 00897 0, 00898 &CommitSize, 00899 MEM_COMMIT, 00900 PAGE_NOACCESS); 00901 00902 if (! NT_SUCCESS(Status)) { 00903 00904 // 00905 // The call can fail in low memory conditions. In this case we 00906 // try to recover and will probably fail the original allocation. 00907 // 00908 00909 if ((RtlpDphDebugLevel & DPH_DEBUG_DECOMMIT_RANGES)) { 00910 DbgPrint ("Page heap: Commit (%p) failed with %08X\n", pCurrent, Status); 00911 DbgBreakPoint(); 00912 } 00913 00914 Failed = TRUE; 00915 break; 00916 } 00917 } 00918 00919 00920 if (Failed) { 00921 00922 // 00923 // We need to roll back whatever succeeded. 00924 // 00925 00926 for (pCurrent -= PAGE_SIZE; pCurrent >= pStart && pCurrent < pEnd; pCurrent -= PAGE_SIZE) { 00927 00928 CommitSize = PAGE_SIZE; 00929 00930 Status = ZwFreeVirtualMemory( 00931 NtCurrentProcess(), 00932 &pCurrent, 00933 &CommitSize, 00934 MEM_DECOMMIT); 00935 00936 if (! NT_SUCCESS(Status)) { 00937 00938 // 00939 // There is now valid reason known to me for a correct free operation 00940 // failure. So, in this case we make a little bit of fuss about it. 00941 // 00942 00943 DbgPrint ("Page heap: Decommit (%p) failed with %08X\n", pCurrent, Status); 00944 00945 if ((RtlpDphDebugLevel & DPH_DEBUG_DECOMMIT_RANGES)) { 00946 DbgBreakPoint(); 00947 } 00948 } 00949 } 00950 } 00951 00952 if (Failed) { 00953 return FALSE; 00954 } 00955 else { 00956 return TRUE; 00957 } 00958 }

ULONG RtlpDebugPageHeapCompact IN PVOID  HeapHandle,
IN ULONG  Flags
 

Definition at line 3512 of file heappage.c.

References HeapHandle, NULL, RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapLeaveCritSect(), and RtlpDebugPageHeapPointerFromHandle().

Referenced by RtlDebugCompactHeap().

03516 { 03517 PDPH_HEAP_ROOT HeapRoot; 03518 03519 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03520 if (HeapRoot == NULL) 03521 return 0; 03522 03523 Flags |= HeapRoot->HeapFlags; 03524 03525 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 03526 03527 // 03528 // Don't do anything, but we did want to acquire the critsect 03529 // in case this was called with HEAP_NO_SERIALIZE while another 03530 // thread is in the heap code. 03531 // 03532 03533 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03534 03535 return 0; 03536 }

PVOID RtlpDebugPageHeapCreate IN ULONG  Flags,
IN PVOID HeapBase  OPTIONAL,
IN SIZE_T ReserveSize  OPTIONAL,
IN SIZE_T CommitSize  OPTIONAL,
IN PVOID Lock  OPTIONAL,
IN PRTL_HEAP_PARAMETERS Parameters  OPTIONAL
 

Definition at line 1997 of file heappage.c.

References DbgPrint, DEBUG_ASSERT, DEBUG_CODE, DPH_DEBUG_INTERNAL_VALIDATION, DPH_HEAP_SIGNATURE, FALSE, FILL_BYTE, HEAP_FLAG_PAGE_ALLOCS, HEAP_HANDLE_FROM_ROOT, HEAP_NO_ALIGNMENT, HeapHandle, IF_GENERATE_EXCEPTION, Lock, NtQueryPerformanceCounter(), NTSTATUS(), NULL, OUT_OF_VM_BREAK, PAGE_SIZE, POOL_SIZE, PROTECT_HEAP_STRUCTURES, RESERVE_SIZE, RETAIL_ASSERT, RtlCreateHeap(), RtlInitializeCriticalSection(), RtlInitUnicodeString(), RtlpDebugPageHeapAddNewPool(), RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapAllocateVM(), RtlpDebugPageHeapCoalesceNodeIntoAvailable(), RtlpDebugPageHeapPlaceOnPoolList(), RtlpDebugPageHeapPlaceOnVirtualList(), RtlpDebugPageHeapProtectVM(), RtlpDebugPageHeapReleaseVM(), RtlpDphDebugLevel, RtlpDphGlobalFlags, RtlpDphHeapListCount, RtlpDphHeapListCriticalSection, RtlpDphHeapListHasBeenInitialized, RtlpDphHeapListHead, RtlpDphHeapListTail, RtlpDphInitializeDelayedFreeQueue(), RtlpDphInternalValidatePageHeap(), RtlpDphLogStackTrace(), RtlpDphTargetDlls, RtlpDphTargetDllsLogicInitialize(), RtlpDphTargetDllsUnicode, RtlpDphTraceDatabase, RtlpDphTraceDatabaseMaximumSize, Size, Status, TRUE, UNPROTECT_HEAP_STRUCTURES, and VM_UNIT_SIZE.

Referenced by RtlCreateHeap().

02005 { 02006 SYSTEM_BASIC_INFORMATION SystemInfo; 02007 PDPH_HEAP_BLOCK Node; 02008 PDPH_HEAP_ROOT HeapRoot; 02009 PVOID HeapHandle; 02010 PUCHAR pVirtual; 02011 SIZE_T nVirtual; 02012 SIZE_T Size; 02013 NTSTATUS Status; 02014 02015 // 02016 // If `Parameters' is -1 then this is a recursive call to 02017 // RtlpDebugPageHeapCreate and we will return NULL so that 02018 // the normal heap manager will create a normal heap. 02019 // I agree this is a hack but we need this so that we maintain 02020 // a very loose dependency between the normal and page heap 02021 // manager. 02022 // 02023 02024 if ((SIZE_T)Parameters == (SIZE_T)-1) { 02025 return NULL; 02026 } 02027 02028 // 02029 // We don't handle heaps where HeapBase is already allocated 02030 // from user or where Lock is provided by user. 02031 // 02032 02033 DEBUG_ASSERT( HeapBase == NULL ); 02034 DEBUG_ASSERT( Lock == NULL ); 02035 02036 if (( HeapBase != NULL ) || ( Lock != NULL )) 02037 return NULL; 02038 02039 // 02040 // Note that we simply ignore ReserveSize, CommitSize, and 02041 // Parameters as we always have a growable heap with our 02042 // own thresholds, etc. 02043 // 02044 02045 ZwQuerySystemInformation( SystemBasicInformation, 02046 &SystemInfo, 02047 sizeof( SystemInfo ), 02048 NULL ); 02049 02050 RETAIL_ASSERT( SystemInfo.PageSize == PAGE_SIZE ); 02051 RETAIL_ASSERT( SystemInfo.AllocationGranularity == VM_UNIT_SIZE ); 02052 DEBUG_ASSERT(( PAGE_SIZE + POOL_SIZE + PAGE_SIZE ) < VM_UNIT_SIZE ); 02053 02054 nVirtual = RESERVE_SIZE; 02055 pVirtual = RtlpDebugPageHeapAllocateVM( nVirtual ); 02056 02057 if (pVirtual == NULL) { 02058 02059 nVirtual = VM_UNIT_SIZE; 02060 pVirtual = RtlpDebugPageHeapAllocateVM( nVirtual ); 02061 02062 if (pVirtual == NULL) { 02063 OUT_OF_VM_BREAK( Flags, "Page heap: Insufficient memory to create heap\n" ); 02064 IF_GENERATE_EXCEPTION( Flags, STATUS_NO_MEMORY ); 02065 return NULL; 02066 } 02067 } 02068 02069 if (! RtlpDebugPageHeapProtectVM( pVirtual, PAGE_SIZE + POOL_SIZE + PAGE_SIZE, PAGE_READWRITE )) { 02070 RtlpDebugPageHeapReleaseVM( pVirtual ); 02071 IF_GENERATE_EXCEPTION( Flags, STATUS_NO_MEMORY ); 02072 return NULL; 02073 } 02074 02075 // 02076 // Out of our initial allocation, the initial page is the fake 02077 // retail HEAP structure. The second page begins our DPH_HEAP 02078 // structure followed by (POOL_SIZE-sizeof(DPH_HEAP)) bytes for 02079 // the initial pool. The next page contains out CRIT_SECT 02080 // variable, which must always be READWRITE. Beyond that, the 02081 // remainder of the virtual allocation is placed on the available 02082 // list. 02083 // 02084 // |_____|___________________|_____|__ _ _ _ _ _ _ _ _ _ _ _ _ __| 02085 // 02086 // ^pVirtual 02087 // 02088 // ^FakeRetailHEAP 02089 // 02090 // ^HeapRoot 02091 // 02092 // ^InitialNodePool 02093 // 02094 // ^CRITICAL_SECTION 02095 // 02096 // ^AvailableSpace 02097 // 02098 // 02099 // 02100 // Our DPH_HEAP structure starts at the page following the 02101 // fake retail HEAP structure pointed to by the "heap handle". 02102 // For the fake HEAP structure, we'll fill it with 0xEEEEEEEE 02103 // except for the Heap->Flags and Heap->ForceFlags fields, 02104 // which we must set to include our HEAP_FLAG_PAGE_ALLOCS flag, 02105 // and then we'll make the whole page read-only. 02106 // 02107 02108 RtlFillMemory( pVirtual, PAGE_SIZE, FILL_BYTE ); 02109 02110 ((PHEAP)pVirtual)->Flags = Flags | HEAP_FLAG_PAGE_ALLOCS; 02111 ((PHEAP)pVirtual)->ForceFlags = Flags | HEAP_FLAG_PAGE_ALLOCS; 02112 02113 if (! RtlpDebugPageHeapProtectVM( pVirtual, PAGE_SIZE, PAGE_READONLY )) { 02114 RtlpDebugPageHeapReleaseVM( pVirtual ); 02115 IF_GENERATE_EXCEPTION( Flags, STATUS_NO_MEMORY ); 02116 return NULL; 02117 } 02118 02119 HeapRoot = (PDPH_HEAP_ROOT)( pVirtual + PAGE_SIZE ); 02120 02121 HeapRoot->Signature = DPH_HEAP_SIGNATURE; 02122 HeapRoot->HeapFlags = Flags; 02123 HeapRoot->HeapCritSect = (PVOID)((PCHAR)HeapRoot + POOL_SIZE ); 02124 02125 // 02126 // Copy the page heap global flags into per heap flags. 02127 // 02128 02129 HeapRoot->ExtraFlags = RtlpDphGlobalFlags; 02130 02131 // 02132 // If the PAGE_HEAP_UNALIGNED_ALLOCATIONS bit is set 02133 // in ExtraFlags we will set the HEAP_NO_ALIGNMENT flag 02134 // in the HeapFlags. This last bit controls if allocations 02135 // will be aligned or not. The reason we do this transfer is 02136 // that ExtraFlags can be set from the registry whereas the 02137 // normal HeapFlags cannot. 02138 // 02139 02140 if ((HeapRoot->ExtraFlags & PAGE_HEAP_UNALIGNED_ALLOCATIONS)) { 02141 HeapRoot->HeapFlags |= HEAP_NO_ALIGNMENT; 02142 } 02143 02144 // 02145 // Initialize the seed for the random generator used to decide 02146 // from where should we make allocations if random decision 02147 // flag is on. 02148 // 02149 02150 { 02151 LARGE_INTEGER PerformanceCounter; 02152 02153 PerformanceCounter.LowPart = 0xABCDDCBA; 02154 02155 NtQueryPerformanceCounter ( 02156 &PerformanceCounter, 02157 NULL); 02158 02159 HeapRoot->Seed = PerformanceCounter.LowPart; 02160 } 02161 02162 RtlZeroMemory (HeapRoot->Counter, sizeof(HeapRoot->Counter)); 02163 02164 // 02165 // Create the normal heap associated with the page heap. 02166 // The last parameter value (-1) is very important because 02167 // it stops the recursive call into page heap create. 02168 // 02169 02170 HeapRoot->NormalHeap = RtlCreateHeap( 02171 02172 Flags, 02173 HeapBase, 02174 ReserveSize, 02175 CommitSize, 02176 Lock, 02177 (PRTL_HEAP_PARAMETERS)-1 ); 02178 02179 // 02180 // Initialize heap lock. 02181 // 02182 02183 RtlInitializeCriticalSection( HeapRoot->HeapCritSect ); 02184 02185 // 02186 // On the page that contains our DPH_HEAP structure, use 02187 // the remaining memory beyond the DPH_HEAP structure as 02188 // pool for allocating heap nodes. 02189 // 02190 02191 RtlpDebugPageHeapAddNewPool( HeapRoot, 02192 HeapRoot + 1, 02193 POOL_SIZE - sizeof( DPH_HEAP_ROOT ), 02194 FALSE 02195 ); 02196 02197 // 02198 // Make initial PoolList entry by taking a node from the 02199 // UnusedNodeList, which should be guaranteed to be non-empty 02200 // since we just added new nodes to it. 02201 // 02202 02203 Node = RtlpDebugPageHeapAllocateNode( HeapRoot ); 02204 DEBUG_ASSERT( Node != NULL ); 02205 Node->pVirtualBlock = (PVOID)HeapRoot; 02206 Node->nVirtualBlockSize = POOL_SIZE; 02207 RtlpDebugPageHeapPlaceOnPoolList( HeapRoot, Node ); 02208 02209 // 02210 // Make VirtualStorageList entry for initial VM allocation 02211 // 02212 02213 Node = RtlpDebugPageHeapAllocateNode( HeapRoot ); 02214 DEBUG_ASSERT( Node != NULL ); 02215 Node->pVirtualBlock = pVirtual; 02216 Node->nVirtualBlockSize = nVirtual; 02217 RtlpDebugPageHeapPlaceOnVirtualList( HeapRoot, Node ); 02218 02219 // 02220 // Make AvailableList entry containing remainder of initial VM 02221 // and add to (create) the AvailableList. 02222 // 02223 02224 Node = RtlpDebugPageHeapAllocateNode( HeapRoot ); 02225 DEBUG_ASSERT( Node != NULL ); 02226 Node->pVirtualBlock = pVirtual + ( PAGE_SIZE + POOL_SIZE + PAGE_SIZE ); 02227 Node->nVirtualBlockSize = nVirtual - ( PAGE_SIZE + POOL_SIZE + PAGE_SIZE ); 02228 RtlpDebugPageHeapCoalesceNodeIntoAvailable( HeapRoot, Node ); 02229 02230 // 02231 // Get heap creation stack trace. 02232 // 02233 02234 HeapRoot->CreateStackTrace = RtlpDphLogStackTrace(1); 02235 02236 // 02237 // Initialize heap internal structure protection. 02238 // 02239 02240 HeapRoot->nUnProtectionReferenceCount = 1; // initialize 02241 02242 // 02243 // If this is the first heap creation in this process, then we 02244 // need to initialize the process heap list critical section, 02245 // the global delayed free queue for normal blocks and the 02246 // trace database. 02247 // 02248 02249 if (! RtlpDphHeapListHasBeenInitialized) { 02250 02251 RtlpDphHeapListHasBeenInitialized = TRUE; 02252 02253 RtlInitializeCriticalSection( &RtlpDphHeapListCriticalSection ); 02254 RtlpDphInitializeDelayedFreeQueue (); 02255 02256 // 02257 // Do not make fuss if the trace database creation fails. 02258 // This is something we can live with. 02259 // 02260 // The number of buckets is chosen to be a prime not too 02261 // close to a power of two (Knuth says so). Three possible 02262 // values are: 1567, 3089, 6263. 02263 // 02264 02265 RtlpDphTraceDatabase = RtlTraceDatabaseCreate ( 02266 6263, 02267 RtlpDphTraceDatabaseMaximumSize, 02268 0, 02269 0, 02270 NULL); 02271 02272 #if DBG 02273 if (RtlpDphTraceDatabase == NULL) { 02274 DbgPrint ("Page heap: warning: failed to create trace database for %p", 02275 HeapRoot); 02276 } 02277 #endif 02278 // 02279 // Create the Unicode string containing the target dlls. 02280 // If no target dlls have been specified the string will 02281 // be initialized with the empty string. 02282 // 02283 02284 RtlInitUnicodeString ( 02285 &RtlpDphTargetDllsUnicode, 02286 RtlpDphTargetDlls); 02287 02288 // 02289 // Initialize the target dlls logic 02290 // 02291 02292 RtlpDphTargetDllsLogicInitialize (); 02293 } 02294 02295 // 02296 // Add this heap entry to the process heap linked list. 02297 // 02298 02299 RtlEnterCriticalSection( &RtlpDphHeapListCriticalSection ); 02300 02301 if (RtlpDphHeapListHead == NULL) { 02302 RtlpDphHeapListHead = HeapRoot; 02303 RtlpDphHeapListTail = HeapRoot; 02304 } 02305 else { 02306 HeapRoot->pPrevHeapRoot = RtlpDphHeapListTail; 02307 UNPROTECT_HEAP_STRUCTURES(RtlpDphHeapListTail); 02308 RtlpDphHeapListTail->pNextHeapRoot = HeapRoot; 02309 PROTECT_HEAP_STRUCTURES(RtlpDphHeapListTail); 02310 RtlpDphHeapListTail = HeapRoot; 02311 } 02312 02313 PROTECT_HEAP_STRUCTURES( HeapRoot ); // now protected 02314 02315 RtlpDphHeapListCount += 1; 02316 02317 RtlLeaveCriticalSection( &RtlpDphHeapListCriticalSection ); 02318 02319 DEBUG_CODE( RtlpDebugPageHeapVerifyIntegrity( HeapRoot )); 02320 02321 DbgPrint( "Page heap: process 0x%X created heap @ %p (%p, flags 0x%X)\n", 02322 NtCurrentTeb()->ClientId.UniqueProcess, 02323 HEAP_HANDLE_FROM_ROOT( HeapRoot ), 02324 HeapRoot->NormalHeap, 02325 HeapRoot->ExtraFlags); 02326 02327 if ((RtlpDphDebugLevel & DPH_DEBUG_INTERNAL_VALIDATION)) { 02328 RtlpDphInternalValidatePageHeap (HeapRoot, NULL, 0); 02329 } 02330 02331 return HEAP_HANDLE_FROM_ROOT( HeapRoot ); // same as pVirtual 02332 02333 }

INLINE BOOLEAN RtlpDebugPageHeapDecommitVM IN PVOID  pVirtual,
IN SIZE_T  nSize
 

Definition at line 962 of file heappage.c.

References DbgPrint, DPH_DEBUG_DECOMMIT_RANGES, FALSE, NT_SUCCESS, NTSTATUS(), PAGE_SIZE, RtlpDphDebugLevel, Status, and TRUE.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapFree(), and RtlpDebugPageHeapReAllocate().

00966 { 00967 PCHAR pStart, pEnd, pCurrent; 00968 NTSTATUS Status; 00969 SIZE_T DecommitSize; 00970 BOOLEAN Failed = FALSE; 00971 00972 pStart = (PCHAR)((ULONG_PTR)pVirtual & ~(PAGE_SIZE - 1)); 00973 pEnd = (PCHAR)(((ULONG_PTR)pVirtual + nSize) & ~(PAGE_SIZE - 1)); 00974 00975 for (pCurrent = pStart; pCurrent < pEnd; pCurrent += PAGE_SIZE) { 00976 00977 DecommitSize = PAGE_SIZE; 00978 00979 Status = ZwFreeVirtualMemory( 00980 NtCurrentProcess(), 00981 &pCurrent, 00982 &DecommitSize, 00983 MEM_DECOMMIT); 00984 00985 if (! NT_SUCCESS(Status)) { 00986 00987 // 00988 // There is now valid reason known to me for a correct free operation 00989 // failure. So, in this case we make a little bit of fuss about it. 00990 // 00991 00992 DbgPrint ("Page heap: Decommit (%p) failed with %08X\n", pCurrent, Status); 00993 00994 if ((RtlpDphDebugLevel & DPH_DEBUG_DECOMMIT_RANGES)) { 00995 DbgBreakPoint(); 00996 } 00997 00998 Failed = TRUE; 00999 } 01000 } 01001 01002 if (Failed) { 01003 return FALSE; 01004 } 01005 else { 01006 return TRUE; 01007 } 01008 }

PVOID RtlpDebugPageHeapDestroy IN PVOID  HeapHandle  ) 
 

Definition at line 3259 of file heappage.c.

References DbgPrint, DEBUG_CODE, HeapHandle, NULL, RtlDeleteCriticalSection(), RtlDestroyHeap(), RtlpDebugPageHeapBreak(), RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapPointerFromHandle(), RtlpDebugPageHeapReleaseVM(), RtlpDphFreeDelayedBlocksFromHeap(), RtlpDphHeapListCount, RtlpDphHeapListCriticalSection, RtlpDphHeapListHead, RtlpDphHeapListTail, RtlpDphIsPageHeapBlock(), RtlpDphReportCorruptedBlock(), TRUE, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlDestroyHeap().

03262 { 03263 PDPH_HEAP_ROOT HeapRoot; 03264 PDPH_HEAP_ROOT PrevHeapRoot; 03265 PDPH_HEAP_ROOT NextHeapRoot; 03266 PDPH_HEAP_BLOCK Node; 03267 PDPH_HEAP_BLOCK Next; 03268 ULONG Flags; 03269 PUCHAR p; 03270 ULONG Reason; 03271 PVOID NormalHeap; 03272 03273 if (HeapHandle == RtlProcessHeap()) { 03274 RtlpDebugPageHeapBreak( "Page heap: Attempt to destroy process heap\n" ); 03275 return NULL; 03276 } 03277 03278 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03279 if (HeapRoot == NULL) 03280 return NULL; 03281 03282 Flags = HeapRoot->HeapFlags | HEAP_NO_SERIALIZE; 03283 03284 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 03285 DEBUG_CODE( RtlpDebugPageHeapVerifyIntegrity( HeapRoot )); 03286 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 03287 03288 // 03289 // Save normal heap pointer for later. 03290 // 03291 03292 NormalHeap = HeapRoot->NormalHeap; 03293 03294 // 03295 // Walk all busy allocations and check for tail fill corruption 03296 // 03297 03298 Node = HeapRoot->pBusyAllocationListHead; 03299 03300 while (Node) { 03301 03302 if (! (HeapRoot->ExtraFlags & PAGE_HEAP_CATCH_BACKWARD_OVERRUNS)) { 03303 if (! (RtlpDphIsPageHeapBlock (HeapRoot, Node->pUserAllocation, &Reason, TRUE))) { 03304 RtlpDphReportCorruptedBlock (Node->pUserAllocation, Reason); 03305 } 03306 } 03307 03308 Node = Node->pNextAlloc; 03309 } 03310 03311 // 03312 // Remove this heap entry from the process heap linked list. 03313 // 03314 03315 RtlEnterCriticalSection( &RtlpDphHeapListCriticalSection ); 03316 03317 if (HeapRoot->pPrevHeapRoot) { 03318 HeapRoot->pPrevHeapRoot->pNextHeapRoot = HeapRoot->pNextHeapRoot; 03319 } 03320 else { 03321 RtlpDphHeapListHead = HeapRoot->pNextHeapRoot; 03322 } 03323 03324 if (HeapRoot->pNextHeapRoot) { 03325 HeapRoot->pNextHeapRoot->pPrevHeapRoot = HeapRoot->pPrevHeapRoot; 03326 } 03327 else { 03328 RtlpDphHeapListTail = HeapRoot->pPrevHeapRoot; 03329 } 03330 03331 RtlpDphHeapListCount--; 03332 03333 RtlLeaveCriticalSection( &RtlpDphHeapListCriticalSection ); 03334 03335 03336 // 03337 // Must release critical section before deleting it; otherwise, 03338 // checked build Teb->CountOfOwnedCriticalSections gets out of sync. 03339 // 03340 03341 RtlLeaveCriticalSection( HeapRoot->HeapCritSect ); 03342 RtlDeleteCriticalSection( HeapRoot->HeapCritSect ); 03343 03344 // 03345 // This is weird. A virtual block might contain storage for 03346 // one of the nodes necessary to walk this list. In fact, 03347 // we're guaranteed that the root node contains at least one 03348 // virtual alloc node. 03349 // 03350 // Each time we alloc new VM, we make that the head of the 03351 // of the VM list, like a LIFO structure. I think we're ok 03352 // because no VM list node should be on a subsequently alloc'd 03353 // VM -- only a VM list entry might be on its own memory (as 03354 // is the case for the root node). We read pNode->pNextAlloc 03355 // before releasing the VM in case pNode existed on that VM. 03356 // I think this is safe -- as long as the VM list is LIFO and 03357 // we don't do any list reorganization. 03358 // 03359 03360 Node = HeapRoot->pVirtualStorageListHead; 03361 03362 while (Node) { 03363 Next = Node->pNextAlloc; 03364 if (! RtlpDebugPageHeapReleaseVM( Node->pVirtualBlock )) { 03365 RtlpDebugPageHeapBreak( "Page heap: Unable to release virtual memory\n" ); 03366 } 03367 Node = Next; 03368 } 03369 03370 // 03371 // Free all blocks in the delayed free queue that belong to the 03372 // normal heap just about to be destroyed. Note that this is 03373 // not a bug. The application freed the blocks correctly but 03374 // we delayed the free operation. 03375 // 03376 03377 RtlpDphFreeDelayedBlocksFromHeap (HeapRoot, NormalHeap); 03378 03379 // 03380 // Destroy normal heap. Note that this will not make a recursive 03381 // call into this function because this is not a page heap and 03382 // code in NT heap manager will detect this. 03383 // 03384 03385 RtlDestroyHeap (NormalHeap); 03386 03387 // 03388 // That's it. All the VM, including the root node, should now 03389 // be released. RtlDestroyHeap always returns NULL. 03390 // 03391 03392 DbgPrint( "Page heap: process 0x%X destroyed heap @ %p (%p)\n", 03393 NtCurrentTeb()->ClientId.UniqueProcess, 03394 HeapRoot, 03395 NormalHeap); 03396 03397 return NULL; 03398 }

VOID RtlpDebugPageHeapEnterCritSect IN PDPH_HEAP_ROOT  HeapRoot,
IN ULONG  Flags
 

Definition at line 627 of file heappage.c.

References RtlpDebugPageHeapBreak().

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCompact(), RtlpDebugPageHeapDestroy(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapGetUserInfo(), RtlpDebugPageHeapLock(), RtlpDebugPageHeapReAllocate(), RtlpDebugPageHeapSerialize(), RtlpDebugPageHeapSetUserFlags(), RtlpDebugPageHeapSetUserValue(), RtlpDebugPageHeapSize(), RtlpDebugPageHeapUsage(), and RtlpDebugPageHeapValidate().

00631 { 00632 if (Flags & HEAP_NO_SERIALIZE) { 00633 00634 if (! RtlTryEnterCriticalSection( HeapRoot->HeapCritSect )) { 00635 00636 if (HeapRoot->nRemoteLockAcquired == 0) { 00637 00638 // 00639 // Another thread owns the CritSect. This is an application 00640 // bug since multithreaded access to heap was attempted with 00641 // the HEAP_NO_SERIALIZE flag specified. 00642 // 00643 00644 RtlpDebugPageHeapBreak( "Page heap: Multithreaded access with HEAP_NO_SERIALIZE\n" ); 00645 00646 // 00647 // In the interest of allowing the errant app to continue, 00648 // we'll force serialization and continue. 00649 // 00650 00651 HeapRoot->HeapFlags &= ~HEAP_NO_SERIALIZE; 00652 00653 } 00654 00655 RtlEnterCriticalSection( HeapRoot->HeapCritSect ); 00656 00657 } 00658 } 00659 else { 00660 RtlEnterCriticalSection( HeapRoot->HeapCritSect ); 00661 } 00662 }

VOID RtlpDebugPageHeapException IN ULONG  ExceptionCode  ) 
 

Definition at line 674 of file heappage.c.

References NULL, RtlpDebugPageHeapException(), and RtlRaiseException().

Referenced by RtlpDebugPageHeapException().

00677 { 00678 EXCEPTION_RECORD ER; 00679 00680 ER.ExceptionCode = ExceptionCode; 00681 ER.ExceptionFlags = 0; 00682 ER.ExceptionRecord = NULL; 00683 ER.ExceptionAddress = RtlpDebugPageHeapException; 00684 ER.NumberParameters = 0; 00685 RtlRaiseException( &ER ); 00686 }

NTSTATUS RtlpDebugPageHeapExtend IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  Base,
IN SIZE_T  Size
 

Definition at line 3817 of file heappage.c.

Referenced by RtlExtendHeap().

03823 { 03824 return STATUS_SUCCESS; 03825 }

PDPH_HEAP_BLOCK RtlpDebugPageHeapFindAvailableMem IN PDPH_HEAP_ROOT  pHeap,
IN SIZE_T  nSize,
OUT PDPH_HEAP_BLOCK *  pPrevAvailNode,
IN BOOLEAN  bGrowVirtual
 

Definition at line 1358 of file heappage.c.

References DEBUG_ASSERT, MIN_FREE_LIST_LENGTH, NULL, PAGE_SIZE, RtlpDebugPageHeapCoalesceFreeIntoAvailable(), RtlpDebugPageHeapCommitVM(), RtlpDebugPageHeapGrowVirtual(), RtlpDebugPageHeapPlaceOnFreeList(), and RtlpDebugPageHeapSearchAvailableMemListForBestFit().

Referenced by RtlpDebugPageHeapAllocate(), and RtlpDebugPageHeapAllocateNode().

01364 { 01365 PDPH_HEAP_BLOCK pAvail; 01366 ULONG nLeaveOnFreeList; 01367 01368 // 01369 // If we use uncommitted ranges it is really important to 01370 // call FindAvailableMemory only with page aligned sizes. 01371 // 01372 01373 if ((pHeap->ExtraFlags & PAGE_HEAP_SMART_MEMORY_USAGE)) { 01374 DEBUG_ASSERT ((nSize & ~(PAGE_SIZE - 1)) == nSize); 01375 } 01376 01377 // 01378 // First search existing AvailableList for a "best-fit" block 01379 // (the smallest block that will satisfy the request). 01380 // 01381 01382 pAvail = RtlpDebugPageHeapSearchAvailableMemListForBestFit( 01383 pHeap, 01384 nSize, 01385 pPrevAvailNode 01386 ); 01387 01388 while (( pAvail == NULL ) && ( pHeap->nFreeAllocations > MIN_FREE_LIST_LENGTH )) { 01389 01390 // 01391 // Failed to find sufficient memory on AvailableList. Coalesce 01392 // 3/4 of the FreeList memory to the AvailableList and try again. 01393 // Continue this until we have sufficient memory in AvailableList, 01394 // or the FreeList length is reduced to MIN_FREE_LIST_LENGTH entries. 01395 // We don't shrink the FreeList length below MIN_FREE_LIST_LENGTH 01396 // entries to preserve the most recent MIN_FREE_LIST_LENGTH entries 01397 // for reference-after-freed purposes. 01398 // 01399 01400 nLeaveOnFreeList = pHeap->nFreeAllocations / 4; 01401 01402 if (nLeaveOnFreeList < MIN_FREE_LIST_LENGTH) 01403 nLeaveOnFreeList = MIN_FREE_LIST_LENGTH; 01404 01405 RtlpDebugPageHeapCoalesceFreeIntoAvailable( pHeap, nLeaveOnFreeList ); 01406 01407 pAvail = RtlpDebugPageHeapSearchAvailableMemListForBestFit( 01408 pHeap, 01409 nSize, 01410 pPrevAvailNode 01411 ); 01412 01413 } 01414 01415 01416 if (( pAvail == NULL ) && ( bGrowVirtual )) { 01417 01418 // 01419 // After coalescing FreeList into AvailableList, still don't have 01420 // enough memory (large enough block) to satisfy request, so we 01421 // need to allocate more VM. 01422 // 01423 01424 if (RtlpDebugPageHeapGrowVirtual( pHeap, nSize )) { 01425 01426 pAvail = RtlpDebugPageHeapSearchAvailableMemListForBestFit( 01427 pHeap, 01428 nSize, 01429 pPrevAvailNode 01430 ); 01431 01432 if (pAvail == NULL) { 01433 01434 // 01435 // Failed to satisfy request with more VM. If remainder 01436 // of free list combined with available list is larger 01437 // than the request, we might still be able to satisfy 01438 // the request by merging all of the free list onto the 01439 // available list. Note we lose our MIN_FREE_LIST_LENGTH 01440 // reference-after-freed insurance in this case, but it 01441 // is a rare case, and we'd prefer to satisfy the allocation. 01442 // 01443 01444 if (( pHeap->nFreeAllocationBytesCommitted + 01445 pHeap->nAvailableAllocationBytesCommitted ) >= nSize) { 01446 01447 RtlpDebugPageHeapCoalesceFreeIntoAvailable( pHeap, 0 ); 01448 01449 pAvail = RtlpDebugPageHeapSearchAvailableMemListForBestFit( 01450 pHeap, 01451 nSize, 01452 pPrevAvailNode 01453 ); 01454 } 01455 } 01456 } 01457 } 01458 01459 // 01460 // If we use uncommitted ranges we need to commit the memory 01461 // range now. Note that the memory will be committed but 01462 // the protection on it will be N/A. 01463 // 01464 01465 if (pAvail && (pHeap->ExtraFlags & PAGE_HEAP_SMART_MEMORY_USAGE)) { 01466 01467 BOOLEAN Success; 01468 01469 // 01470 // (SilviuC): The memory here might be already committed if we use 01471 // it for the first time. Whenever we allocate virtual memory to grow 01472 // the heap we commit it. This is the reason the consumption does not 01473 // decrease as spectacular as we expected. We need to fix it. 01474 // It affects 0x43 flags. 01475 // 01476 01477 Success = RtlpDebugPageHeapCommitVM (pAvail->pVirtualBlock, nSize); 01478 01479 if (!Success) { 01480 01481 // 01482 // We did not manage to commit memory for this block. This 01483 // can happen in low memory conditions. We need to return 01484 // the node back into free pool (together with virtual space 01485 // region taken) and fail the current call. 01486 // 01487 01488 RtlpDebugPageHeapPlaceOnFreeList( pHeap, pAvail ); 01489 01490 return NULL; 01491 } 01492 } 01493 01494 return pAvail; 01495 }

PDPH_HEAP_BLOCK RtlpDebugPageHeapFindBusyMem IN PDPH_HEAP_ROOT  pHeap,
IN PVOID  pUserMem,
OUT PDPH_HEAP_BLOCK *  pPrevAlloc
 

Definition at line 1053 of file heappage.c.

References NULL.

Referenced by RtlpDebugPageHeapFree(), RtlpDebugPageHeapGetUserInfo(), RtlpDebugPageHeapReAllocate(), RtlpDebugPageHeapSetUserFlags(), RtlpDebugPageHeapSetUserValue(), RtlpDebugPageHeapSize(), and RtlpDebugPageHeapValidate().

01058 { 01059 PDPH_HEAP_BLOCK pNode = pHeap->pBusyAllocationListHead; 01060 PDPH_HEAP_BLOCK pPrev = NULL; 01061 01062 while (pNode != NULL) { 01063 01064 if (pNode->pUserAllocation == pUserMem) { 01065 01066 if (pPrevAlloc) 01067 *pPrevAlloc = pPrev; 01068 01069 return pNode; 01070 } 01071 01072 pPrev = pNode; 01073 pNode = pNode->pNextAlloc; 01074 } 01075 01076 return NULL; 01077 }

BOOLEAN RtlpDebugPageHeapFree IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  Address
 

Definition at line 2693 of file heappage.c.

References BUMP_GLOBAL_COUNTER, DbgPrint, DEBUG_CODE, DPH_DEBUG_BREAK_FOR_NULL_FREE, DPH_DEBUG_INTERNAL_VALIDATION, EXIT, FALSE, HeapHandle, IF_GENERATE_EXCEPTION, NULL, PAGE_SIZE, PROTECT_HEAP_STRUCTURES, RtlpDebugPageHeapDecommitVM(), RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapFindBusyMem(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPlaceOnFreeList(), RtlpDebugPageHeapPointerFromHandle(), RtlpDebugPageHeapProtectVM(), RtlpDebugPageHeapRemoveFromBusyList(), RtlpDphDebugLevel, RtlpDphInternalValidatePageHeap(), RtlpDphIsPageHeapBlock(), RtlpDphLogStackTrace(), RtlpDphNormalHeapFree(), RtlpDphReportCorruptedBlock(), RtlpDphTraceDatabase, TRUE, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlDebugFreeHeap(), RtlpDphDllDelete(), RtlpDphDllDeleteArray(), RtlpDphDllfree(), RtlpDphDllGlobalFree(), RtlpDphDllHeapFree(), and RtlpDphDllLocalFree().

02698 { 02699 02700 PDPH_HEAP_ROOT HeapRoot; 02701 PDPH_HEAP_BLOCK Node, Prev; 02702 BOOLEAN Success; 02703 PCH p; 02704 ULONG Reason; 02705 02706 // 02707 // Check if null frees are of any concern. 02708 // 02709 02710 if (Address == NULL) { 02711 02712 if ((RtlpDphDebugLevel & DPH_DEBUG_BREAK_FOR_NULL_FREE)) { 02713 02714 DbgPrint ("Page heap: attempt to free null pointer \n"); 02715 DbgBreakPoint(); 02716 } 02717 02718 // 02719 // For C++ apps that delete NULL this is valid. 02720 // 02721 02722 return TRUE; 02723 } 02724 02725 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 02726 if (HeapRoot == NULL) 02727 return FALSE; 02728 02729 // 02730 // Acquire heap lock and unprotect heap structures. 02731 // 02732 02733 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 02734 DEBUG_CODE( RtlpDebugPageHeapVerifyIntegrity( HeapRoot )); 02735 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 02736 02737 if ((RtlpDphDebugLevel & DPH_DEBUG_INTERNAL_VALIDATION)) { 02738 RtlpDphInternalValidatePageHeap (HeapRoot, NULL, 0); 02739 } 02740 02741 Flags |= HeapRoot->HeapFlags; 02742 02743 // 02744 // Compute free statistics 02745 // 02746 02747 BUMP_GLOBAL_COUNTER (DPH_COUNTER_NO_OF_FREES); 02748 HeapRoot->Counter[DPH_COUNTER_NO_OF_FREES] += 1; 02749 02750 02751 Success = FALSE; 02752 02753 Node = RtlpDebugPageHeapFindBusyMem( HeapRoot, Address, &Prev ); 02754 02755 if (Node == NULL) { 02756 02757 // 02758 // No wonder we did not find the block in the page heap 02759 // structures because the block was probably allocated 02760 // from the normal heap. Or there is a real bug. 02761 // If there is a bug NormalHeapFree will break into debugger. 02762 // 02763 02764 Success = RtlpDphNormalHeapFree ( 02765 02766 HeapRoot, 02767 Flags, 02768 Address); 02769 02770 goto EXIT; 02771 } 02772 02773 // 02774 // If tail was allocated, make sure filler not overwritten 02775 // 02776 02777 if ((HeapRoot->ExtraFlags & PAGE_HEAP_CATCH_BACKWARD_OVERRUNS)) { 02778 02779 if (Node->nVirtualAccessSize > 0) { 02780 RtlpDebugPageHeapProtectVM( Node->pVirtualBlock + PAGE_SIZE, 02781 Node->nVirtualAccessSize, 02782 PAGE_NOACCESS ); 02783 } 02784 } 02785 else { 02786 02787 // 02788 // (SilviuC): This can be done at the beginning of the function. 02789 // 02790 02791 if (! (RtlpDphIsPageHeapBlock (HeapRoot, Address, &Reason, TRUE))) { 02792 02793 RtlpDphReportCorruptedBlock (Address, Reason); 02794 } 02795 02796 if (Node->nVirtualAccessSize > 0) { 02797 02798 // 02799 // Mark the block as freed. The information is gone if we 02800 // will decommit the region but will remain if smart memory 02801 // flag is not set and can help debug failures. 02802 // 02803 02804 { 02805 PDPH_BLOCK_INFORMATION Info = (PDPH_BLOCK_INFORMATION)(Node->pUserAllocation); 02806 02807 Info -= 1; 02808 Info->StartStamp -= 1; 02809 Info->EndStamp -= 1; 02810 } 02811 02812 RtlpDebugPageHeapProtectVM( Node->pVirtualBlock, 02813 Node->nVirtualAccessSize, 02814 PAGE_NOACCESS ); 02815 } 02816 } 02817 02818 RtlpDebugPageHeapRemoveFromBusyList( HeapRoot, Node, Prev ); 02819 02820 // 02821 // If we use uncommitted ranges we need to decommit the memory 02822 // range now for the allocation. Note that the next page (guard) 02823 // was already decommitted when we allocated the block. 02824 // 02825 02826 if ((HeapRoot->ExtraFlags & PAGE_HEAP_CATCH_BACKWARD_OVERRUNS)) { 02827 02828 // nothing 02829 02830 } 02831 else { 02832 02833 if ((HeapRoot->ExtraFlags & PAGE_HEAP_SMART_MEMORY_USAGE)) { 02834 02835 RtlpDebugPageHeapDecommitVM ( 02836 Node->pVirtualBlock, 02837 Node->nVirtualAccessSize); 02838 } 02839 } 02840 02841 02842 RtlpDebugPageHeapPlaceOnFreeList( HeapRoot, Node ); 02843 02844 // 02845 // RtlpDebugPageHeapFree gets called from RtlDebugFreeHeap, which 02846 // gets called from RtlFreeHeapSlowly, which gets called from 02847 // RtlFreeHeap. To keep from wasting lots of stack trace storage, 02848 // we'll skip the bottom 3 entries, leaving RtlFreeHeap as the 02849 // first recorded entry. 02850 // 02851 02852 if ((HeapRoot->ExtraFlags & PAGE_HEAP_COLLECT_STACK_TRACES)) { 02853 02854 if (Node->StackTrace) { 02855 02856 RtlTraceDatabaseLock (RtlpDphTraceDatabase); 02857 02858 if (Node->StackTrace->UserCount > 0) { 02859 Node->StackTrace->UserCount -= 1; 02860 } 02861 02862 if (Node->StackTrace->UserSize >= Node->nUserRequestedSize) { 02863 Node->StackTrace->UserSize -= Node->nUserRequestedSize; 02864 } 02865 02866 RtlTraceDatabaseUnlock (RtlpDphTraceDatabase); 02867 } 02868 02869 Node->StackTrace = RtlpDphLogStackTrace(3); 02870 } 02871 else { 02872 Node->StackTrace = NULL; 02873 } 02874 02875 Success = TRUE; 02876 02877 EXIT: 02878 02879 if ((RtlpDphDebugLevel & DPH_DEBUG_INTERNAL_VALIDATION)) { 02880 RtlpDphInternalValidatePageHeap (HeapRoot, NULL, 0); 02881 } 02882 02883 PROTECT_HEAP_STRUCTURES( HeapRoot ); 02884 DEBUG_CODE( RtlpDebugPageHeapVerifyIntegrity( HeapRoot )); 02885 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 02886 02887 if (! Success) { 02888 IF_GENERATE_EXCEPTION( Flags, STATUS_ACCESS_VIOLATION ); 02889 } 02890 02891 return Success; 02892 }

ULONG RtlpDebugPageHeapGetProcessHeaps ULONG  NumberOfHeaps,
PVOID *  ProcessHeaps
 

Definition at line 3458 of file heappage.c.

References Count, HEAP_HANDLE_FROM_ROOT, NULL, RtlInitializeCriticalSection(), RtlpDebugPageHeapBreak(), RtlpDphHeapListCount, RtlpDphHeapListCriticalSection, RtlpDphHeapListHasBeenInitialized, RtlpDphHeapListHead, and TRUE.

Referenced by RtlGetProcessHeaps().

03462 { 03463 PDPH_HEAP_ROOT HeapRoot; 03464 ULONG Count; 03465 03466 // 03467 // Although we'd expect GetProcessHeaps never to be called 03468 // before at least the very first heap creation, we should 03469 // still be safe and initialize the critical section if 03470 // necessary. 03471 // 03472 03473 if (! RtlpDphHeapListHasBeenInitialized) { 03474 RtlpDphHeapListHasBeenInitialized = TRUE; 03475 RtlInitializeCriticalSection( &RtlpDphHeapListCriticalSection ); 03476 } 03477 03478 RtlEnterCriticalSection( &RtlpDphHeapListCriticalSection ); 03479 03480 if (RtlpDphHeapListCount <= NumberOfHeaps) { 03481 03482 for (HeapRoot = RtlpDphHeapListHead, Count = 0; 03483 HeapRoot != NULL; 03484 HeapRoot = HeapRoot->pNextHeapRoot, Count += 1) { 03485 03486 *ProcessHeaps++ = HEAP_HANDLE_FROM_ROOT( HeapRoot ); 03487 } 03488 03489 if (Count != RtlpDphHeapListCount) { 03490 RtlpDebugPageHeapBreak( "Page heap: BUG: process heap list count wrong\n" ); 03491 } 03492 03493 } 03494 else { 03495 03496 // 03497 // User's buffer is too small. Return number of entries 03498 // necessary for subsequent call to succeed. Buffer 03499 // remains untouched. 03500 // 03501 03502 Count = RtlpDphHeapListCount; 03503 03504 } 03505 03506 RtlLeaveCriticalSection( &RtlpDphHeapListCriticalSection ); 03507 03508 return Count; 03509 }

BOOLEAN RtlpDebugPageHeapGetUserInfo IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  Address,
OUT PVOID *  UserValue,
OUT PULONG  UserFlags
 

Definition at line 3683 of file heappage.c.

References EXIT, FALSE, HeapHandle, NULL, PROTECT_HEAP_STRUCTURES, RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapFindBusyMem(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPointerFromHandle(), RtlpDphNormalHeapGetUserInfo(), TRUE, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlDebugGetUserInfoHeap().

03690 { 03691 PDPH_HEAP_ROOT HeapRoot; 03692 PDPH_HEAP_BLOCK Node; 03693 BOOLEAN Success; 03694 03695 Success = FALSE; 03696 03697 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03698 if ( HeapRoot == NULL ) 03699 return Success; 03700 03701 Flags |= HeapRoot->HeapFlags; 03702 03703 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 03704 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 03705 03706 Node = RtlpDebugPageHeapFindBusyMem( HeapRoot, Address, NULL ); 03707 03708 if ( Node == NULL ) { 03709 03710 // 03711 // If we cannot find the node in page heap structures it might be 03712 // because it has been allocated from normal heap. 03713 // 03714 03715 Success = RtlpDphNormalHeapGetUserInfo ( 03716 HeapRoot, 03717 Flags, 03718 Address, 03719 UserValue, 03720 UserFlags); 03721 03722 goto EXIT; 03723 } 03724 else { 03725 if ( UserValue != NULL ) 03726 *UserValue = Node->UserValue; 03727 if ( UserFlags != NULL ) 03728 *UserFlags = Node->UserFlags; 03729 Success = TRUE; 03730 } 03731 03732 EXIT: 03733 PROTECT_HEAP_STRUCTURES( HeapRoot ); 03734 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03735 03736 return Success; 03737 }

BOOLEAN RtlpDebugPageHeapGrowVirtual IN PDPH_HEAP_ROOT  pHeap,
IN SIZE_T  nSize
 

Definition at line 1759 of file heappage.c.

References FALSE, NULL, RESERVE_SIZE, ROUNDUP2, RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapAllocateVM(), RtlpDebugPageHeapCoalesceNodeIntoAvailable(), RtlpDebugPageHeapPlaceOnVirtualList(), RtlpDebugPageHeapReturnNodeToUnusedList(), TRUE, and VM_UNIT_SIZE.

Referenced by RtlpDebugPageHeapFindAvailableMem().

01763 { 01764 PDPH_HEAP_BLOCK pVirtualNode; 01765 PDPH_HEAP_BLOCK pAvailNode; 01766 PVOID pVirtual; 01767 SIZE_T nVirtual; 01768 01769 pVirtualNode = RtlpDebugPageHeapAllocateNode( pHeap ); 01770 01771 if (pVirtualNode == NULL) { 01772 return FALSE; 01773 } 01774 01775 pAvailNode = RtlpDebugPageHeapAllocateNode( pHeap ); 01776 01777 if (pAvailNode == NULL) { 01778 RtlpDebugPageHeapReturnNodeToUnusedList( pHeap, pVirtualNode ); 01779 return FALSE; 01780 } 01781 01782 nSize = ROUNDUP2( nSize, VM_UNIT_SIZE ); 01783 nVirtual = ( nSize > RESERVE_SIZE ) ? nSize : RESERVE_SIZE; 01784 pVirtual = RtlpDebugPageHeapAllocateVM( nVirtual ); 01785 01786 if (( pVirtual == NULL ) && ( nSize < RESERVE_SIZE )) { 01787 nVirtual = nSize; 01788 pVirtual = RtlpDebugPageHeapAllocateVM( nVirtual ); 01789 } 01790 01791 if (pVirtual == NULL) { 01792 RtlpDebugPageHeapReturnNodeToUnusedList( pHeap, pVirtualNode ); 01793 RtlpDebugPageHeapReturnNodeToUnusedList( pHeap, pAvailNode ); 01794 return FALSE; 01795 } 01796 01797 pVirtualNode->pVirtualBlock = pVirtual; 01798 pVirtualNode->nVirtualBlockSize = nVirtual; 01799 RtlpDebugPageHeapPlaceOnVirtualList( pHeap, pVirtualNode ); 01800 01801 pAvailNode->pVirtualBlock = pVirtual; 01802 pAvailNode->nVirtualBlockSize = nVirtual; 01803 RtlpDebugPageHeapCoalesceNodeIntoAvailable( pHeap, pAvailNode ); 01804 01805 return TRUE; 01806 }

BOOLEAN RtlpDebugPageHeapIsLocked IN PVOID  HeapHandle  ) 
 

Definition at line 3883 of file heappage.c.

References FALSE, HeapHandle, NULL, RtlpDebugPageHeapPointerFromHandle(), and TRUE.

Referenced by RtlpHeapIsLocked().

03886 { 03887 PDPH_HEAP_ROOT HeapRoot; 03888 03889 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03890 if ( HeapRoot == NULL ) 03891 return FALSE; 03892 03893 if ( RtlTryEnterCriticalSection( HeapRoot->HeapCritSect )) { 03894 RtlLeaveCriticalSection( HeapRoot->HeapCritSect ); 03895 return FALSE; 03896 } 03897 else { 03898 return TRUE; 03899 } 03900 }

INLINE VOID RtlpDebugPageHeapLeaveCritSect IN PDPH_HEAP_ROOT  HeapRoot  ) 
 

Definition at line 666 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCompact(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapGetUserInfo(), RtlpDebugPageHeapReAllocate(), RtlpDebugPageHeapSerialize(), RtlpDebugPageHeapSetUserFlags(), RtlpDebugPageHeapSetUserValue(), RtlpDebugPageHeapSize(), RtlpDebugPageHeapUnlock(), RtlpDebugPageHeapUsage(), and RtlpDebugPageHeapValidate().

00669 { 00670 RtlLeaveCriticalSection( HeapRoot->HeapCritSect ); 00671 }

BOOLEAN RtlpDebugPageHeapLock IN PVOID  HeapHandle  ) 
 

Definition at line 3595 of file heappage.c.

References FALSE, HeapHandle, NULL, RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapPointerFromHandle(), and TRUE.

Referenced by RtlLockHeap().

03598 { 03599 PDPH_HEAP_ROOT HeapRoot; 03600 03601 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03602 03603 if (HeapRoot == NULL) { 03604 return FALSE; 03605 } 03606 03607 RtlpDebugPageHeapEnterCritSect( HeapRoot, HeapRoot->HeapFlags ); 03608 03609 return TRUE; 03610 }

VOID RtlpDebugPageHeapPlaceOnBusyList IN PDPH_HEAP_ROOT  pHeap,
IN PDPH_HEAP_BLOCK  pNode
 

Definition at line 1145 of file heappage.c.

References ENQUEUE_HEAD.

Referenced by RtlpDebugPageHeapAllocate(), and RtlpDebugPageHeapReAllocate().

01149 { 01150 // 01151 // BusyAllocationList is LIFO to achieve better temporal locality 01152 // of reference (older allocations are farther down the list). 01153 // 01154 01155 ENQUEUE_HEAD( pNode, pHeap->pBusyAllocationListHead, pHeap->pBusyAllocationListTail ); 01156 01157 pHeap->nBusyAllocations += 1; 01158 pHeap->nBusyAllocationBytesCommitted += pNode->nVirtualBlockSize; 01159 pHeap->nBusyAllocationBytesAccessible += pNode->nVirtualAccessSize; 01160 }

VOID RtlpDebugPageHeapPlaceOnFreeList IN PDPH_HEAP_ROOT  pHeap,
IN PDPH_HEAP_BLOCK  pAlloc
 

Definition at line 1093 of file heappage.c.

References ENQUEUE_TAIL, and NULL.

Referenced by RtlpDebugPageHeapFindAvailableMem(), RtlpDebugPageHeapFree(), and RtlpDebugPageHeapReAllocate().

01097 { 01098 // 01099 // FreeAllocationList is stored FIFO to enhance finding 01100 // reference-after-freed bugs by keeping previously freed 01101 // allocations on the free list as long as possible. 01102 // 01103 01104 pAlloc->pNextAlloc = NULL; 01105 01106 ENQUEUE_TAIL( pAlloc, pHeap->pFreeAllocationListHead, pHeap->pFreeAllocationListTail ); 01107 01108 pHeap->nFreeAllocations += 1; 01109 pHeap->nFreeAllocationBytesCommitted += pAlloc->nVirtualBlockSize; 01110 }

VOID RtlpDebugPageHeapPlaceOnPoolList IN PDPH_HEAP_ROOT  pHeap,
IN PDPH_HEAP_BLOCK  pNode
 

Definition at line 1498 of file heappage.c.

References ENQUEUE_TAIL, and NULL.

Referenced by RtlpDebugPageHeapAddNewPool(), and RtlpDebugPageHeapCreate().

01502 { 01503 01504 // 01505 // NodePoolList is FIFO. 01506 // 01507 01508 pNode->pNextAlloc = NULL; 01509 01510 ENQUEUE_TAIL( pNode, pHeap->pNodePoolListHead, pHeap->pNodePoolListTail ); 01511 01512 pHeap->nNodePoolBytes += pNode->nVirtualBlockSize; 01513 pHeap->nNodePools += 1; 01514 01515 }

VOID RtlpDebugPageHeapPlaceOnVirtualList IN PDPH_HEAP_ROOT  pHeap,
IN PDPH_HEAP_BLOCK  pNode
 

Definition at line 1128 of file heappage.c.

References ENQUEUE_HEAD.

Referenced by RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapGrowVirtual().

01132 { 01133 // 01134 // VirtualStorageList is LIFO so that releasing VM blocks will 01135 // occur in exact reverse order. 01136 // 01137 01138 ENQUEUE_HEAD( pNode, pHeap->pVirtualStorageListHead, pHeap->pVirtualStorageListTail ); 01139 01140 pHeap->nVirtualStorageRanges += 1; 01141 pHeap->nVirtualStorageBytes += pNode->nVirtualBlockSize; 01142 }

PVOID RtlpDebugPageHeapPointerFromHandle IN PVOID  HeapHandle  ) 
 

Definition at line 689 of file heappage.c.

References DPH_HEAP_SIGNATURE, EXCEPTION_EXECUTE_HANDLER, HEAP_FLAG_PAGE_ALLOCS, HeapHandle, NULL, PAGE_SIZE, and RtlpDebugPageHeapBreak().

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCompact(), RtlpDebugPageHeapDestroy(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapGetUserInfo(), RtlpDebugPageHeapIsLocked(), RtlpDebugPageHeapLock(), RtlpDebugPageHeapReAllocate(), RtlpDebugPageHeapSerialize(), RtlpDebugPageHeapSetUserFlags(), RtlpDebugPageHeapSetUserValue(), RtlpDebugPageHeapSize(), RtlpDebugPageHeapUnlock(), RtlpDebugPageHeapUsage(), and RtlpDebugPageHeapValidate().

00692 { 00693 try { 00694 if (((PHEAP)(HeapHandle))->ForceFlags & HEAP_FLAG_PAGE_ALLOCS) { 00695 00696 PDPH_HEAP_ROOT HeapRoot = (PVOID)(((PCHAR)(HeapHandle)) + PAGE_SIZE ); 00697 00698 if (HeapRoot->Signature == DPH_HEAP_SIGNATURE) { 00699 return HeapRoot; 00700 } 00701 } 00702 } 00703 except( EXCEPTION_EXECUTE_HANDLER ) { 00704 } 00705 00706 RtlpDebugPageHeapBreak( "Page heap: Bad heap handle\n" ); 00707 return NULL; 00708 }

PCCH RtlpDebugPageHeapProtectionText IN ULONG  Access,
IN OUT PCHAR  Buffer
 

Definition at line 711 of file heappage.c.

References Buffer, and sprintf().

Referenced by RtlpDebugPageHeapRobustProtectVM().

00715 { 00716 switch (Access) { 00717 case PAGE_NOACCESS: return "PAGE_NOACCESS"; 00718 case PAGE_READONLY: return "PAGE_READONLY"; 00719 case PAGE_READWRITE: return "PAGE_READWRITE"; 00720 case PAGE_WRITECOPY: return "PAGE_WRITECOPY"; 00721 case PAGE_EXECUTE: return "PAGE_EXECUTE"; 00722 case PAGE_EXECUTE_READ: return "PAGE_EXECUTE_READ"; 00723 case PAGE_EXECUTE_READWRITE: return "PAGE_EXECUTE_READWRITE"; 00724 case PAGE_EXECUTE_WRITECOPY: return "PAGE_EXECUTE_WRITECOPY"; 00725 case PAGE_GUARD: return "PAGE_GUARD"; 00726 case 0: return "UNKNOWN"; 00727 default: sprintf( Buffer, "0x%08X", Access ); 00728 return Buffer; 00729 } 00730 }

VOID RtlpDebugPageHeapProtectStructures IN PDPH_HEAP_ROOT  pHeap  ) 
 

Definition at line 1809 of file heappage.c.

References DEBUG_ASSERT, HEAP_PROTECTION_ENABLED, NULL, and RtlpDebugPageHeapProtectVM().

01812 { 01813 PDPH_HEAP_BLOCK pNode; 01814 01815 // 01816 // Assume CritSect is owned so we're the only thread twiddling 01817 // the protection. 01818 // 01819 01820 DEBUG_ASSERT( pHeap->HeapFlags & HEAP_PROTECTION_ENABLED ); 01821 01822 if (--pHeap->nUnProtectionReferenceCount == 0) { 01823 01824 pNode = pHeap->pNodePoolListHead; 01825 01826 while (pNode != NULL) { 01827 01828 RtlpDebugPageHeapProtectVM( pNode->pVirtualBlock, 01829 pNode->nVirtualBlockSize, 01830 PAGE_READONLY ); 01831 01832 pNode = pNode->pNextAlloc; 01833 01834 } 01835 } 01836 }

INLINE BOOLEAN RtlpDebugPageHeapProtectVM IN PVOID  VirtualBase,
IN SIZE_T  VirtualSize,
IN ULONG  NewAccess
 

Definition at line 831 of file heappage.c.

References FALSE, and RtlpDebugPageHeapRobustProtectVM().

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapProtectStructures(), RtlpDebugPageHeapReAllocate(), and RtlpDebugPageHeapUnProtectStructures().

00836 { 00837 return RtlpDebugPageHeapRobustProtectVM( VirtualBase, VirtualSize, NewAccess, FALSE ); 00838 }

PVOID RtlpDebugPageHeapReAllocate IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  Address,
IN SIZE_T  Size
 

Definition at line 2895 of file heappage.c.

References BIAS_POINTER, BUMP_GLOBAL_COUNTER, BUMP_SIZE_COUNTER, DbgPrint, DEBUG_ASSERT, DEBUG_CODE, DPH_DEBUG_BREAK_FOR_SIZE_ZERO, DPH_DEBUG_INTERNAL_VALIDATION, EXCEPTION_EXECUTE_HANDLER, EXIT, FALSE, HeapHandle, IF_GENERATE_EXCEPTION, IS_BIASED_POINTER, NULL, OUT_OF_VM_BREAK, PROTECT_HEAP_STRUCTURES, RETAIL_ASSERT, RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapDecommitVM(), RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapFindBusyMem(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPlaceOnBusyList(), RtlpDebugPageHeapPlaceOnFreeList(), RtlpDebugPageHeapPointerFromHandle(), RtlpDebugPageHeapProtectVM(), RtlpDebugPageHeapRemoveFromBusyList(), RtlpDphDebugLevel, RtlpDphInternalValidatePageHeap(), RtlpDphIsPageHeapBlock(), RtlpDphLogStackTrace(), RtlpDphNormalHeapAllocate(), RtlpDphNormalHeapReAllocate(), RtlpDphReportCorruptedBlock(), RtlpDphShouldAllocateInPageHeap(), RtlpDphTraceDatabase, Size, TRUE, UNBIAS_POINTER, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlDebugReAllocateHeap(), RtlpDphDllGlobalReAlloc(), RtlpDphDllHeapReAlloc(), RtlpDphDllLocalReAlloc(), and RtlpDphDllrealloc().

02901 { 02902 PDPH_HEAP_ROOT HeapRoot; 02903 PDPH_HEAP_BLOCK OldNode, OldPrev, NewNode; 02904 PVOID NewAddress; 02905 PUCHAR p; 02906 SIZE_T CopyDataSize; 02907 ULONG SaveFlags; 02908 BOOLEAN ReallocInNormalHeap = FALSE; 02909 ULONG Reason; 02910 BOOLEAN ForcePageHeap = FALSE; 02911 BOOLEAN OriginalAllocationInPageHeap = FALSE; 02912 02913 if (IS_BIASED_POINTER(HeapHandle)) { 02914 HeapHandle = UNBIAS_POINTER(HeapHandle); 02915 ForcePageHeap = TRUE; 02916 } 02917 02918 // 02919 // Is zero size allocation ? 02920 // 02921 02922 if (Size == 0) { 02923 02924 if ((RtlpDphDebugLevel & DPH_DEBUG_BREAK_FOR_SIZE_ZERO)) { 02925 02926 DbgPrint ("Page heap: request for zero sized block \n"); 02927 DbgBreakPoint(); 02928 } 02929 } 02930 02931 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 02932 if (HeapRoot == NULL) 02933 return NULL; 02934 02935 // 02936 // Get heap lock and unprotect heap structures. 02937 // 02938 02939 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 02940 DEBUG_CODE( RtlpDebugPageHeapVerifyIntegrity( HeapRoot )); 02941 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 02942 02943 if ((RtlpDphDebugLevel & DPH_DEBUG_INTERNAL_VALIDATION)) { 02944 RtlpDphInternalValidatePageHeap (HeapRoot, NULL, 0); 02945 } 02946 02947 Flags |= HeapRoot->HeapFlags; 02948 02949 // 02950 // Compute realloc statistics 02951 // 02952 02953 BUMP_GLOBAL_COUNTER (DPH_COUNTER_NO_OF_REALLOCS); 02954 BUMP_SIZE_COUNTER (Size); 02955 02956 HeapRoot->Counter[DPH_COUNTER_NO_OF_REALLOCS] += 1; 02957 02958 if (Size < 1024) { 02959 BUMP_GLOBAL_COUNTER (DPH_COUNTER_SIZE_BELOW_1K); 02960 HeapRoot->Counter[DPH_COUNTER_SIZE_BELOW_1K] += 1; 02961 } 02962 else if (Size < 4096) { 02963 BUMP_GLOBAL_COUNTER (DPH_COUNTER_SIZE_BELOW_4K); 02964 HeapRoot->Counter[DPH_COUNTER_SIZE_BELOW_4K] += 1; 02965 } 02966 else { 02967 BUMP_GLOBAL_COUNTER (DPH_COUNTER_SIZE_ABOVE_4K); 02968 HeapRoot->Counter[DPH_COUNTER_SIZE_ABOVE_4K] += 1; 02969 } 02970 02971 02972 NewAddress = NULL; 02973 02974 // 02975 // Check Flags for non-moveable reallocation and fail it 02976 // unconditionally. Apps that specify this flag should be 02977 // prepared to deal with failure anyway. 02978 // 02979 02980 if (Flags & HEAP_REALLOC_IN_PLACE_ONLY) { 02981 goto EXIT; 02982 } 02983 02984 // 02985 // Validate requested size so we don't overflow 02986 // while rounding up size computations. We do this 02987 // after we've acquired the critsect so we can still 02988 // catch serialization problems. 02989 // 02990 02991 if (Size > 0x7FFF0000) { 02992 OUT_OF_VM_BREAK( Flags, "Page heap: Invalid allocation size\n" ); 02993 goto EXIT; 02994 } 02995 02996 OldNode = RtlpDebugPageHeapFindBusyMem( HeapRoot, Address, &OldPrev ); 02997 02998 if (OldNode) { 02999 OriginalAllocationInPageHeap = TRUE; 03000 } 03001 03002 if (OldNode == NULL) { 03003 03004 // 03005 // No wonder we did not find the block in the page heap 03006 // structures because the block was probably allocated 03007 // from the normal heap. Or there is a real bug. If there 03008 // is a bug NormalHeapReAllocate will break into debugger. 03009 // 03010 03011 NewAddress = RtlpDphNormalHeapReAllocate ( 03012 03013 HeapRoot, 03014 Flags, 03015 Address, 03016 Size); 03017 03018 goto EXIT; 03019 } 03020 03021 // 03022 // If tail was allocated, make sure filler not overwritten 03023 // 03024 03025 if ((HeapRoot->ExtraFlags & PAGE_HEAP_CATCH_BACKWARD_OVERRUNS)) { 03026 03027 // nothing 03028 } 03029 else { 03030 03031 // 03032 // (SilviuC): This can be done at the beginning of the function. 03033 // 03034 03035 if (! (RtlpDphIsPageHeapBlock (HeapRoot, Address, &Reason, TRUE))) { 03036 03037 RtlpDphReportCorruptedBlock (Address, Reason); 03038 } 03039 } 03040 03041 // 03042 // Before allocating a new block, remove the old block from 03043 // the busy list. When we allocate the new block, the busy 03044 // list pointers will change, possibly leaving our acquired 03045 // Prev pointer invalid. 03046 // 03047 03048 RtlpDebugPageHeapRemoveFromBusyList( HeapRoot, OldNode, OldPrev ); 03049 03050 // 03051 // Allocate new memory for new requested size. Use try/except 03052 // to trap exception if Flags caused out-of-memory exception. 03053 // 03054 03055 try { 03056 03057 if (!ForcePageHeap && !(RtlpDphShouldAllocateInPageHeap (HeapRoot, Size))) { 03058 03059 NewAddress = RtlpDphNormalHeapAllocate ( 03060 HeapRoot, 03061 Flags, 03062 Size); 03063 03064 ReallocInNormalHeap = TRUE; 03065 } 03066 else { 03067 03068 // 03069 // Force the allocation in page heap by biasing 03070 // the heap handle. Validate the heap here since when we use 03071 // biased pointers validation inside Allocate is disabled. 03072 // 03073 03074 if ((RtlpDphDebugLevel & DPH_DEBUG_INTERNAL_VALIDATION)) { 03075 RtlpDphInternalValidatePageHeap (HeapRoot, OldNode->pVirtualBlock, OldNode->nVirtualBlockSize); 03076 } 03077 03078 NewAddress = RtlpDebugPageHeapAllocate( 03079 BIAS_POINTER(HeapHandle), 03080 Flags, 03081 Size); 03082 03083 03084 if ((RtlpDphDebugLevel & DPH_DEBUG_INTERNAL_VALIDATION)) { 03085 RtlpDphInternalValidatePageHeap (HeapRoot, OldNode->pVirtualBlock, OldNode->nVirtualBlockSize); 03086 } 03087 03088 ReallocInNormalHeap = FALSE; 03089 } 03090 } 03091 except( EXCEPTION_EXECUTE_HANDLER ) { 03092 } 03093 03094 // 03095 // We managed to make a new allocation (normal or page heap). 03096 // Now we need to copy from old to new all sorts of stuff 03097 // (contents, user flags/values). 03098 // 03099 03100 if (NewAddress) { 03101 03102 // 03103 // Copy old block contents into the new node. 03104 // 03105 03106 CopyDataSize = OldNode->nUserRequestedSize; 03107 03108 if (CopyDataSize > Size) { 03109 CopyDataSize = Size; 03110 } 03111 03112 if (CopyDataSize > 0) { 03113 03114 RtlCopyMemory( 03115 NewAddress, 03116 Address, 03117 CopyDataSize 03118 ); 03119 } 03120 03121 // 03122 // If new allocation was done in page heap we need to detect the new node 03123 // and copy over user flags/values. 03124 // 03125 03126 if (! ReallocInNormalHeap) { 03127 03128 NewNode = RtlpDebugPageHeapFindBusyMem( HeapRoot, NewAddress, NULL ); 03129 03130 // 03131 // This block could not be in normal heap therefore from this 03132 // respect the call above should always succeed. 03133 // 03134 03135 DEBUG_ASSERT( NewNode != NULL ); 03136 03137 NewNode->UserValue = OldNode->UserValue; 03138 NewNode->UserFlags = ( Flags & HEAP_SETTABLE_USER_FLAGS ) ? 03139 ( Flags & HEAP_SETTABLE_USER_FLAGS ) : 03140 OldNode->UserFlags; 03141 03142 } 03143 03144 // 03145 // We need to cover the case where old allocation was in page heap. 03146 // In this case we still need to cleanup the old node and 03147 // insert it back in free list. Actually the way the code is written 03148 // we take this code path only if original allocation was in page heap. 03149 // This is the reason for the assert. 03150 // 03151 03152 03153 RETAIL_ASSERT (OriginalAllocationInPageHeap); 03154 03155 if (OriginalAllocationInPageHeap) { 03156 03157 if (OldNode->nVirtualAccessSize > 0) { 03158 RtlpDebugPageHeapProtectVM( OldNode->pVirtualBlock, 03159 OldNode->nVirtualAccessSize, 03160 PAGE_NOACCESS ); 03161 } 03162 03163 // 03164 // If we use uncommitted ranges we need to decommit the memory 03165 // range now. Note that the next page (guard) was already decommitted 03166 // when we made the allocation. 03167 // 03168 03169 if ((HeapRoot->ExtraFlags & PAGE_HEAP_CATCH_BACKWARD_OVERRUNS)) { 03170 03171 // nothing 03172 03173 } 03174 else { 03175 03176 if ((HeapRoot->ExtraFlags & PAGE_HEAP_SMART_MEMORY_USAGE)) { 03177 03178 RtlpDebugPageHeapDecommitVM ( 03179 OldNode->pVirtualBlock, 03180 OldNode->nVirtualAccessSize); 03181 } 03182 } 03183 03184 RtlpDebugPageHeapPlaceOnFreeList( HeapRoot, OldNode ); 03185 03186 // 03187 // RtlpDebugPageHeapReAllocate gets called from RtlDebugReAllocateHeap, 03188 // which gets called from RtlReAllocateHeap. To keep from wasting 03189 // lots of stack trace storage, we'll skip the bottom 2 entries, 03190 // leaving RtlReAllocateHeap as the first recorded entry in the 03191 // freed stack trace. 03192 // 03193 // Note. For realloc we need to do the accounting for free in the 03194 // trace block. The accounting for alloc is done in the real 03195 // alloc operation which always happens for page heap reallocs. 03196 // 03197 03198 if ((HeapRoot->ExtraFlags & PAGE_HEAP_COLLECT_STACK_TRACES)) { 03199 03200 if (OldNode->StackTrace) { 03201 03202 RtlTraceDatabaseLock (RtlpDphTraceDatabase); 03203 03204 if (OldNode->StackTrace->UserCount > 0) { 03205 OldNode->StackTrace->UserCount -= 1; 03206 } 03207 03208 if (OldNode->StackTrace->UserSize >= OldNode->nUserRequestedSize) { 03209 OldNode->StackTrace->UserSize -= OldNode->nUserRequestedSize; 03210 } 03211 03212 RtlTraceDatabaseUnlock (RtlpDphTraceDatabase); 03213 } 03214 03215 OldNode->StackTrace = RtlpDphLogStackTrace(2); 03216 } 03217 else { 03218 OldNode->StackTrace = NULL; 03219 } 03220 } 03221 } 03222 03223 else { 03224 03225 // 03226 // Failed to allocate a new block. Return old block to busy list. 03227 // 03228 03229 if (OriginalAllocationInPageHeap) { 03230 03231 RtlpDebugPageHeapPlaceOnBusyList( HeapRoot, OldNode ); 03232 } 03233 03234 } 03235 03236 EXIT: 03237 03238 if ((RtlpDphDebugLevel & DPH_DEBUG_INTERNAL_VALIDATION)) { 03239 RtlpDphInternalValidatePageHeap (HeapRoot, NULL, 0); 03240 } 03241 03242 PROTECT_HEAP_STRUCTURES( HeapRoot ); 03243 DEBUG_CODE( RtlpDebugPageHeapVerifyIntegrity( HeapRoot )); 03244 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03245 03246 if (NewAddress == NULL) { 03247 IF_GENERATE_EXCEPTION( Flags, STATUS_NO_MEMORY ); 03248 } 03249 03250 return NewAddress; 03251 }

INLINE BOOLEAN RtlpDebugPageHeapReleaseVM IN PVOID  pVirtual  ) 
 

Definition at line 863 of file heappage.c.

References NT_SUCCESS.

Referenced by RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapDestroy().

00866 { 00867 SIZE_T nSize = 0; 00868 00869 return NT_SUCCESS( ZwFreeVirtualMemory( NtCurrentProcess(), 00870 &pVirtual, 00871 &nSize, 00872 MEM_RELEASE )); 00873 }

VOID RtlpDebugPageHeapRemoveFromAvailableList IN PDPH_HEAP_ROOT  pHeap,
IN PDPH_HEAP_BLOCK  pNode,
IN PDPH_HEAP_BLOCK  pPrev
 

Definition at line 1080 of file heappage.c.

References DEQUEUE_NODE.

Referenced by RtlpDebugPageHeapAllocate(), and RtlpDebugPageHeapAllocateNode().

01085 { 01086 DEQUEUE_NODE( pNode, pPrev, pHeap->pAvailableAllocationListHead, pHeap->pAvailableAllocationListTail ); 01087 01088 pHeap->nAvailableAllocations -= 1; 01089 pHeap->nAvailableAllocationBytesCommitted -= pNode->nVirtualBlockSize; 01090 }

VOID RtlpDebugPageHeapRemoveFromBusyList IN PDPH_HEAP_ROOT  pHeap,
IN PDPH_HEAP_BLOCK  pNode,
IN PDPH_HEAP_BLOCK  pPrev
 

Definition at line 1163 of file heappage.c.

References DEQUEUE_NODE.

Referenced by RtlpDebugPageHeapFree(), and RtlpDebugPageHeapReAllocate().

01168 { 01169 DEQUEUE_NODE( pNode, pPrev, pHeap->pBusyAllocationListHead, pHeap->pBusyAllocationListTail ); 01170 01171 pHeap->nBusyAllocations -= 1; 01172 pHeap->nBusyAllocationBytesCommitted -= pNode->nVirtualBlockSize; 01173 pHeap->nBusyAllocationBytesAccessible -= pNode->nVirtualAccessSize; 01174 }

VOID RtlpDebugPageHeapRemoveFromFreeList IN PDPH_HEAP_ROOT  pHeap,
IN PDPH_HEAP_BLOCK  pNode,
IN PDPH_HEAP_BLOCK  pPrev
 

Definition at line 1113 of file heappage.c.

References DEQUEUE_NODE, and NULL.

Referenced by RtlpDebugPageHeapCoalesceFreeIntoAvailable().

01118 { 01119 DEQUEUE_NODE( pNode, pPrev, pHeap->pFreeAllocationListHead, pHeap->pFreeAllocationListTail ); 01120 01121 pHeap->nFreeAllocations -= 1; 01122 pHeap->nFreeAllocationBytesCommitted -= pNode->nVirtualBlockSize; 01123 01124 pNode->StackTrace = NULL; 01125 }

NTSTATUS RtlpDebugPageHeapReset IN PVOID  HeapHandle,
IN ULONG  Flags
 

Definition at line 3837 of file heappage.c.

03841 { 03842 return STATUS_SUCCESS; 03843 }

VOID RtlpDebugPageHeapReturnNodeToUnusedList IN PDPH_HEAP_ROOT  pHeap,
IN PDPH_HEAP_BLOCK  pNode
 

Definition at line 1038 of file heappage.c.

References ENQUEUE_HEAD.

Referenced by RtlpDebugPageHeapAllocateNode(), RtlpDebugPageHeapCoalesceNodeIntoAvailable(), and RtlpDebugPageHeapGrowVirtual().

01042 { 01043 // 01044 // UnusedNodeList is LIFO with most recent entry at head of list. 01045 // 01046 01047 ENQUEUE_HEAD( pNode, pHeap->pUnusedNodeListHead, pHeap->pUnusedNodeListTail ); 01048 01049 pHeap->nUnusedNodes += 1; 01050 }

BOOLEAN RtlpDebugPageHeapRobustProtectVM IN PVOID  VirtualBase,
IN SIZE_T  VirtualSize,
IN ULONG  NewAccess,
IN BOOLEAN  Recursion
 

Definition at line 737 of file heappage.c.

References CHAR, DbgPrint, FALSE, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, ROUNDUP2, RtlpDebugPageHeapProtectionText(), Status, and TRUE.

Referenced by RtlpDebugPageHeapProtectVM().

00743 { 00744 PVOID CopyOfVirtualBase = VirtualBase; 00745 SIZE_T CopyOfVirtualSize = VirtualSize; 00746 ULONG OldAccess; 00747 NTSTATUS Status; 00748 00749 Status = ZwProtectVirtualMemory( 00750 NtCurrentProcess(), 00751 &CopyOfVirtualBase, 00752 &CopyOfVirtualSize, 00753 NewAccess, 00754 &OldAccess 00755 ); 00756 00757 if (NT_SUCCESS( Status )) 00758 return TRUE; 00759 00760 if (! Recursion) { 00761 00762 // 00763 // We failed to change the protection on a range of memory. 00764 // This can happen if if the range of memory spans more than 00765 // one adjancent blocks allocated by separate calls to 00766 // ZwAllocateVirtualMemory. It also seems fails occasionally 00767 // for reasons unknown to me, but always when attempting to 00768 // change the protection on more than one page in a single call. 00769 // So, fall back to changing pages individually in this range. 00770 // This should be rare, so it should not be a performance problem. 00771 // 00772 00773 PCHAR VirtualExtent = (PCHAR)ROUNDUP2((ULONG_PTR)((PCHAR)VirtualBase + VirtualSize ), PAGE_SIZE ); 00774 PCHAR VirtualPage = (PCHAR)((ULONG_PTR)VirtualBase & ~( PAGE_SIZE - 1 )); 00775 BOOLEAN SuccessAll = TRUE; 00776 BOOLEAN SuccessOne; 00777 00778 while (VirtualPage < VirtualExtent) { 00779 00780 SuccessOne = RtlpDebugPageHeapRobustProtectVM( 00781 VirtualPage, 00782 PAGE_SIZE, 00783 NewAccess, 00784 TRUE 00785 ); 00786 00787 if (! SuccessOne) { 00788 SuccessAll = FALSE; 00789 } 00790 00791 VirtualPage += PAGE_SIZE; 00792 00793 } 00794 00795 return SuccessAll; // TRUE if all succeeded, FALSE if any failed 00796 } 00797 00798 else { 00799 00800 MEMORY_BASIC_INFORMATION mbi; 00801 CHAR OldProtectionText[ 12 ]; // big enough for "0x12345678" 00802 CHAR NewProtectionText[ 12 ]; // big enough for "0x12345678" 00803 00804 mbi.Protect = 0; // in case ZwQueryVirtualMemory fails 00805 00806 ZwQueryVirtualMemory( 00807 NtCurrentProcess(), 00808 VirtualBase, 00809 MemoryBasicInformation, 00810 &mbi, 00811 sizeof( mbi ), 00812 NULL 00813 ); 00814 00815 DbgPrint( 00816 "Page heap: Failed changing VM at %08X size 0x%X\n" 00817 " from %s to %s (Status %08X)\n", 00818 VirtualBase, 00819 VirtualSize, 00820 RtlpDebugPageHeapProtectionText( mbi.Protect, OldProtectionText ), 00821 RtlpDebugPageHeapProtectionText( NewAccess, NewProtectionText ), 00822 Status 00823 ); 00824 } 00825 00826 return FALSE; 00827 }

PDPH_HEAP_BLOCK RtlpDebugPageHeapSearchAvailableMemListForBestFit IN PDPH_HEAP_ROOT  pHeap,
IN SIZE_T  nSize,
OUT PDPH_HEAP_BLOCK *  pPrevAvailNode
 

Definition at line 1177 of file heappage.c.

References NULL.

Referenced by RtlpDebugPageHeapFindAvailableMem().

01182 { 01183 PDPH_HEAP_BLOCK pAvail, pFound, pAvailPrev, pFoundPrev; 01184 SIZE_T nAvail, nFound; 01185 01186 nFound = 0x7FFFFFFF; 01187 pFound = NULL; 01188 pFoundPrev = NULL; 01189 pAvailPrev = NULL; 01190 pAvail = pHeap->pAvailableAllocationListHead; 01191 01192 while (( pAvail != NULL ) && ( nFound > nSize )) { 01193 01194 nAvail = pAvail->nVirtualBlockSize; 01195 01196 if (( nAvail >= nSize ) && ( nAvail < nFound )) { 01197 nFound = nAvail; 01198 pFound = pAvail; 01199 pFoundPrev = pAvailPrev; 01200 } 01201 01202 pAvailPrev = pAvail; 01203 pAvail = pAvail->pNextAlloc; 01204 } 01205 01206 *pPrevAvailNode = pFoundPrev; 01207 return pFound; 01208 }

BOOLEAN RtlpDebugPageHeapSerialize IN PVOID  HeapHandle  ) 
 

Definition at line 3795 of file heappage.c.

References FALSE, HeapHandle, NULL, PROTECT_HEAP_STRUCTURES, RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPointerFromHandle(), TRUE, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlpSerializeHeap().

03798 { 03799 PDPH_HEAP_ROOT HeapRoot; 03800 03801 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03802 if ( HeapRoot == NULL ) 03803 return FALSE; 03804 03805 RtlpDebugPageHeapEnterCritSect( HeapRoot, 0 ); 03806 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 03807 03808 HeapRoot->HeapFlags &= ~HEAP_NO_SERIALIZE; 03809 03810 PROTECT_HEAP_STRUCTURES( HeapRoot ); 03811 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03812 03813 return TRUE; 03814 }

BOOLEAN RtlpDebugPageHeapSetUserFlags IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  Address,
IN ULONG  UserFlagsReset,
IN ULONG  UserFlagsSet
 

Definition at line 3740 of file heappage.c.

References EXIT, FALSE, HeapHandle, NULL, PROTECT_HEAP_STRUCTURES, RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapFindBusyMem(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPointerFromHandle(), RtlpDphNormalHeapSetUserFlags(), TRUE, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlDebugSetUserFlagsHeap().

03747 { 03748 PDPH_HEAP_ROOT HeapRoot; 03749 PDPH_HEAP_BLOCK Node; 03750 BOOLEAN Success; 03751 03752 Success = FALSE; 03753 03754 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03755 if ( HeapRoot == NULL ) 03756 return Success; 03757 03758 Flags |= HeapRoot->HeapFlags; 03759 03760 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 03761 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 03762 03763 Node = RtlpDebugPageHeapFindBusyMem( HeapRoot, Address, NULL ); 03764 03765 if ( Node == NULL ) { 03766 03767 // 03768 // If we cannot find the node in page heap structures it might be 03769 // because it has been allocated from normal heap. 03770 // 03771 03772 Success = RtlpDphNormalHeapSetUserFlags ( 03773 HeapRoot, 03774 Flags, 03775 Address, 03776 UserFlagsReset, 03777 UserFlagsSet); 03778 03779 goto EXIT; 03780 } 03781 else { 03782 Node->UserFlags &= ~( UserFlagsReset ); 03783 Node->UserFlags |= UserFlagsSet; 03784 Success = TRUE; 03785 } 03786 03787 EXIT: 03788 PROTECT_HEAP_STRUCTURES( HeapRoot ); 03789 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03790 03791 return Success; 03792 }

BOOLEAN RtlpDebugPageHeapSetUserValue IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  Address,
IN PVOID  UserValue
 

Definition at line 3631 of file heappage.c.

References EXIT, FALSE, HeapHandle, NULL, PROTECT_HEAP_STRUCTURES, RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapFindBusyMem(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPointerFromHandle(), RtlpDphNormalHeapSetUserValue(), TRUE, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlDebugSetUserValueHeap().

03637 { 03638 PDPH_HEAP_ROOT HeapRoot; 03639 PDPH_HEAP_BLOCK Node; 03640 BOOLEAN Success; 03641 03642 Success = FALSE; 03643 03644 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03645 if ( HeapRoot == NULL ) 03646 return Success; 03647 03648 Flags |= HeapRoot->HeapFlags; 03649 03650 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 03651 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 03652 03653 Node = RtlpDebugPageHeapFindBusyMem( HeapRoot, Address, NULL ); 03654 03655 if ( Node == NULL ) { 03656 03657 // 03658 // If we cannot find the node in page heap structures it might be 03659 // because it has been allocated from normal heap. 03660 // 03661 03662 Success = RtlpDphNormalHeapSetUserValue ( 03663 HeapRoot, 03664 Flags, 03665 Address, 03666 UserValue); 03667 03668 goto EXIT; 03669 } 03670 else { 03671 Node->UserValue = UserValue; 03672 Success = TRUE; 03673 } 03674 03675 EXIT: 03676 PROTECT_HEAP_STRUCTURES( HeapRoot ); 03677 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03678 03679 return Success; 03680 }

SIZE_T RtlpDebugPageHeapSize IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  Address
 

Definition at line 3401 of file heappage.c.

References EXIT, HeapHandle, IF_GENERATE_EXCEPTION, NULL, PROTECT_HEAP_STRUCTURES, RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapFindBusyMem(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPointerFromHandle(), RtlpDphNormalHeapSize(), Size, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlDebugSizeHeap().

03406 { 03407 PDPH_HEAP_ROOT HeapRoot; 03408 PDPH_HEAP_BLOCK Node; 03409 SIZE_T Size; 03410 03411 Size = -1; 03412 03413 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03414 if (HeapRoot == NULL) { 03415 return Size; 03416 } 03417 03418 Flags |= HeapRoot->HeapFlags; 03419 03420 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 03421 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 03422 03423 Node = RtlpDebugPageHeapFindBusyMem( HeapRoot, Address, NULL ); 03424 03425 if (Node == NULL) { 03426 03427 // 03428 // No wonder we did not find the block in the page heap 03429 // structures because the block was probably allocated 03430 // from the normal heap. Or there is a real bug. If there 03431 // is a bug NormalHeapSize will break into debugger. 03432 // 03433 03434 Size = RtlpDphNormalHeapSize ( 03435 03436 HeapRoot, 03437 Flags, 03438 Address); 03439 03440 goto EXIT; 03441 } 03442 else { 03443 Size = Node->nUserRequestedSize; 03444 } 03445 03446 EXIT: 03447 PROTECT_HEAP_STRUCTURES( HeapRoot ); 03448 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03449 03450 if (Size == -1) { 03451 IF_GENERATE_EXCEPTION( Flags, STATUS_ACCESS_VIOLATION ); 03452 } 03453 03454 return Size; 03455 }

PDPH_HEAP_BLOCK RtlpDebugPageHeapTakeNodeFromUnusedList IN PDPH_HEAP_ROOT  pHeap  ) 
 

Definition at line 1015 of file heappage.c.

References DEQUEUE_NODE, and NULL.

Referenced by RtlpDebugPageHeapAddNewPool(), and RtlpDebugPageHeapAllocateNode().

01018 { 01019 PDPH_HEAP_BLOCK pNode = pHeap->pUnusedNodeListHead; 01020 PDPH_HEAP_BLOCK pPrev = NULL; 01021 01022 // 01023 // UnusedNodeList is LIFO with most recent entry at head of list. 01024 // 01025 01026 if (pNode) { 01027 01028 DEQUEUE_NODE( pNode, pPrev, pHeap->pUnusedNodeListHead, pHeap->pUnusedNodeListTail ); 01029 01030 pHeap->nUnusedNodes -= 1; 01031 01032 } 01033 01034 return pNode; 01035 }

BOOLEAN RtlpDebugPageHeapUnlock IN PVOID  HeapHandle  ) 
 

Definition at line 3613 of file heappage.c.

References FALSE, HeapHandle, NULL, RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPointerFromHandle(), and TRUE.

Referenced by RtlUnlockHeap().

03616 { 03617 PDPH_HEAP_ROOT HeapRoot; 03618 03619 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03620 03621 if (HeapRoot == NULL) { 03622 return FALSE; 03623 } 03624 03625 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03626 03627 return TRUE; 03628 }

VOID RtlpDebugPageHeapUnProtectStructures IN PDPH_HEAP_ROOT  pHeap  ) 
 

Definition at line 1839 of file heappage.c.

References DEBUG_ASSERT, HEAP_PROTECTION_ENABLED, NULL, and RtlpDebugPageHeapProtectVM().

01842 { 01843 PDPH_HEAP_BLOCK pNode; 01844 01845 DEBUG_ASSERT( pHeap->HeapFlags & HEAP_PROTECTION_ENABLED ); 01846 01847 if (pHeap->nUnProtectionReferenceCount == 0) { 01848 01849 pNode = pHeap->pNodePoolListHead; 01850 01851 while (pNode != NULL) { 01852 01853 RtlpDebugPageHeapProtectVM( pNode->pVirtualBlock, 01854 pNode->nVirtualBlockSize, 01855 PAGE_READWRITE ); 01856 01857 pNode = pNode->pNextAlloc; 01858 01859 } 01860 } 01861 01862 pHeap->nUnProtectionReferenceCount += 1; 01863 }

NTSTATUS RtlpDebugPageHeapUsage IN PVOID  HeapHandle,
IN ULONG  Flags,
IN OUT PRTL_HEAP_USAGE  Usage
 

Definition at line 3846 of file heappage.c.

References HeapHandle, NULL, PROTECT_HEAP_STRUCTURES, RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPointerFromHandle(), UNPROTECT_HEAP_STRUCTURES, and Usage().

Referenced by RtlDebugUsageHeap().

03851 { 03852 PDPH_HEAP_ROOT HeapRoot; 03853 03854 // 03855 // Partial implementation since this information is kind of meaningless. 03856 // 03857 03858 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03859 if ( HeapRoot == NULL ) 03860 return STATUS_INVALID_PARAMETER; 03861 03862 if ( Usage->Length != sizeof( RTL_HEAP_USAGE )) 03863 return STATUS_INFO_LENGTH_MISMATCH; 03864 03865 memset( Usage, 0, sizeof( RTL_HEAP_USAGE )); 03866 Usage->Length = sizeof( RTL_HEAP_USAGE ); 03867 03868 RtlpDebugPageHeapEnterCritSect( HeapRoot, 0 ); 03869 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 03870 03871 Usage->BytesAllocated = HeapRoot->nBusyAllocationBytesAccessible; 03872 Usage->BytesCommitted = HeapRoot->nVirtualStorageBytes; 03873 Usage->BytesReserved = HeapRoot->nVirtualStorageBytes; 03874 Usage->BytesReservedMaximum = HeapRoot->nVirtualStorageBytes; 03875 03876 PROTECT_HEAP_STRUCTURES( HeapRoot ); 03877 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03878 03879 return STATUS_SUCCESS; 03880 }

BOOLEAN RtlpDebugPageHeapValidate IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  Address
 

Definition at line 3539 of file heappage.c.

References DEBUG_CODE, FALSE, HeapHandle, NULL, PROTECT_HEAP_STRUCTURES, RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapFindBusyMem(), RtlpDebugPageHeapLeaveCritSect(), RtlpDebugPageHeapPointerFromHandle(), RtlpDphNormalHeapValidate(), TRUE, and UNPROTECT_HEAP_STRUCTURES.

Referenced by RtlValidateHeap().

03544 { 03545 PDPH_HEAP_ROOT HeapRoot; 03546 PDPH_HEAP_BLOCK Node; 03547 BOOLEAN Result = FALSE; 03548 03549 HeapRoot = RtlpDebugPageHeapPointerFromHandle( HeapHandle ); 03550 if (HeapRoot == NULL) 03551 return FALSE; 03552 03553 Flags |= HeapRoot->HeapFlags; 03554 03555 RtlpDebugPageHeapEnterCritSect( HeapRoot, Flags ); 03556 DEBUG_CODE( RtlpDebugPageHeapVerifyIntegrity( HeapRoot )); 03557 UNPROTECT_HEAP_STRUCTURES( HeapRoot ); 03558 03559 Node = Address ? RtlpDebugPageHeapFindBusyMem( HeapRoot, Address, NULL ) : NULL; 03560 03561 if (Node == NULL) { 03562 03563 Result = RtlpDphNormalHeapValidate ( 03564 HeapRoot, 03565 Flags, 03566 Address); 03567 } 03568 03569 PROTECT_HEAP_STRUCTURES( HeapRoot ); 03570 RtlpDebugPageHeapLeaveCritSect( HeapRoot ); 03571 03572 if (Address) { 03573 if (Node) { 03574 return TRUE; 03575 } 03576 else { 03577 return Result; 03578 } 03579 } 03580 else { 03581 return TRUE; 03582 } 03583 }

NTSTATUS RtlpDebugPageHeapWalk IN PVOID  HeapHandle,
IN OUT PRTL_HEAP_WALK_ENTRY  Entry
 

Definition at line 3586 of file heappage.c.

Referenced by RtlWalkHeap().

03590 { 03591 return STATUS_NOT_IMPLEMENTED; 03592 }

NTSTATUS RtlpDebugPageHeapZero IN PVOID  HeapHandle,
IN ULONG  Flags
 

Definition at line 3828 of file heappage.c.

Referenced by RtlDebugZeroHeap().

03832 { 03833 return STATUS_SUCCESS; 03834 }

VOID RtlpDphAddToDelayedFreeQueue PDPH_BLOCK_INFORMATION  Info  ) 
 

Definition at line 4831 of file heappage.c.

References RtlpDphDelayedFreeQueue, RtlpDphDelayedFreeQueueLock, RtlpDphMemoryUsedByDelayedFreeBlocks, and RtlpDphNumberOfDelayedFreeBlocks.

Referenced by RtlpDphNormalHeapFree().

04834 { 04835 RtlEnterCriticalSection (&RtlpDphDelayedFreeQueueLock); 04836 04837 InsertTailList (&(RtlpDphDelayedFreeQueue), &(Info->FreeQueue)); 04838 04839 RtlpDphMemoryUsedByDelayedFreeBlocks += Info->ActualSize; 04840 RtlpDphNumberOfDelayedFreeBlocks += 1; 04841 04842 RtlLeaveCriticalSection (&RtlpDphDelayedFreeQueueLock); 04843 }

VOID RtlpDphFreeDelayedBlocksFromHeap PVOID  PageHeap,
PVOID  NormalHeap
 

Definition at line 4961 of file heappage.c.

References FreeQueue(), RtlFreeHeap, RtlpDphDelayedFreeQueue, RtlpDphDelayedFreeQueueLock, RtlpDphIsNormalFreeHeapBlock(), RtlpDphMemoryUsedByDelayedFreeBlocks, RtlpDphNumberOfDelayedFreeBlocks, RtlpDphReportCorruptedBlock(), and TRUE.

Referenced by RtlpDebugPageHeapDestroy().

04965 { 04966 ULONG Reason; 04967 PDPH_BLOCK_INFORMATION Block; 04968 PLIST_ENTRY Current; 04969 PLIST_ENTRY Next; 04970 04971 RtlEnterCriticalSection (&RtlpDphDelayedFreeQueueLock); 04972 04973 for (Current = RtlpDphDelayedFreeQueue.Flink; 04974 Current != &RtlpDphDelayedFreeQueue; 04975 Current = Next) { 04976 04977 Next = Current->Flink; 04978 04979 Block = CONTAINING_RECORD (Current, DPH_BLOCK_INFORMATION, FreeQueue); 04980 04981 if (Block->Heap != PageHeap) { 04982 continue; 04983 } 04984 04985 // 04986 // We need to delete this block; 04987 // 04988 04989 RemoveEntryList (Current); 04990 Block = CONTAINING_RECORD (Current, DPH_BLOCK_INFORMATION, FreeQueue); 04991 04992 // 04993 // Prevent probing of this field during RtlpDphIsNormalFreeBlock. 04994 // 04995 04996 Block->Heap = 0; 04997 04998 // 04999 // Check if the block about to be freed was touched. 05000 // 05001 05002 if (! RtlpDphIsNormalFreeHeapBlock(Block + 1, &Reason, TRUE)) { 05003 05004 RtlpDphReportCorruptedBlock (Block + 1, Reason); 05005 } 05006 05007 RtlpDphMemoryUsedByDelayedFreeBlocks -= Block->ActualSize; 05008 RtlpDphNumberOfDelayedFreeBlocks -= 1; 05009 05010 // 05011 // (SilviuC): Not sure what flags to use here. Zero should work 05012 // but I have to investigate. 05013 // 05014 05015 RtlFreeHeap (NormalHeap, 0, Block); 05016 } 05017 05018 RtlLeaveCriticalSection (&RtlpDphDelayedFreeQueueLock); 05019 }

VOID RtlpDphInitializeDelayedFreeQueue  ) 
 

Definition at line 4819 of file heappage.c.

References RtlInitializeCriticalSection(), RtlpDphDelayedFreeQueue, RtlpDphDelayedFreeQueueLock, RtlpDphMemoryUsedByDelayedFreeBlocks, and RtlpDphNumberOfDelayedFreeBlocks.

Referenced by RtlpDebugPageHeapCreate().

04821 { 04822 RtlInitializeCriticalSection (&RtlpDphDelayedFreeQueueLock); 04823 InitializeListHead (&RtlpDphDelayedFreeQueue); 04824 04825 RtlpDphMemoryUsedByDelayedFreeBlocks = 0; 04826 RtlpDphNumberOfDelayedFreeBlocks = 0; 04827 }

VOID RtlpDphInternalValidatePageHeap PDPH_HEAP_ROOT  Heap,
PUCHAR  ExemptAddress,
SIZE_T  ExemptSize
 

Definition at line 5197 of file heappage.c.

References DbgPrint, FALSE, NULL, PAGE_SIZE, RtlpDphCurrentValidationStack, RtlpDphLastValidationStack, RtlpDphLogStackTrace(), RtlpDphSearchBlockInList(), and TRUE.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapFree(), and RtlpDebugPageHeapReAllocate().

05202 { 05203 PDPH_HEAP_BLOCK Range; 05204 PDPH_HEAP_BLOCK Node; 05205 PUCHAR Address; 05206 BOOLEAN FoundLeak; 05207 05208 RtlpDphLastValidationStack = RtlpDphCurrentValidationStack; 05209 RtlpDphCurrentValidationStack = RtlpDphLogStackTrace (0); 05210 FoundLeak = FALSE; 05211 05212 for (Range = Heap->pVirtualStorageListHead; 05213 Range != NULL; 05214 Range = Range->pNextAlloc) { 05215 05216 Address = Range->pVirtualBlock; 05217 05218 while (Address < Range->pVirtualBlock + Range->nVirtualBlockSize) { 05219 05220 // 05221 // Ignore DPH_HEAP_ROOT structures. 05222 // 05223 05224 if ((Address >= (PUCHAR)Heap - PAGE_SIZE) && (Address < (PUCHAR)Heap + 5 * PAGE_SIZE)) { 05225 Address += PAGE_SIZE; 05226 continue; 05227 } 05228 05229 // 05230 // Ignore exempt region (temporarily out of all structures). 05231 // 05232 05233 if ((Address >= ExemptAddress) && (Address < ExemptAddress + ExemptSize)) { 05234 Address += PAGE_SIZE; 05235 continue; 05236 } 05237 05238 Node = RtlpDphSearchBlockInList (Heap->pBusyAllocationListHead, Address); 05239 05240 if (Node) { 05241 Address += Node->nVirtualBlockSize; 05242 continue; 05243 } 05244 05245 Node = RtlpDphSearchBlockInList (Heap->pFreeAllocationListHead, Address); 05246 05247 if (Node) { 05248 Address += Node->nVirtualBlockSize; 05249 continue; 05250 } 05251 05252 Node = RtlpDphSearchBlockInList (Heap->pAvailableAllocationListHead, Address); 05253 05254 if (Node) { 05255 Address += Node->nVirtualBlockSize; 05256 continue; 05257 } 05258 05259 Node = RtlpDphSearchBlockInList (Heap->pNodePoolListHead, Address); 05260 05261 if (Node) { 05262 Address += Node->nVirtualBlockSize; 05263 continue; 05264 } 05265 05266 DbgPrint ("Block @ %p has been leaked \n", Address); 05267 FoundLeak = TRUE; 05268 05269 Address += PAGE_SIZE; 05270 } 05271 } 05272 05273 if (FoundLeak) { 05274 05275 DbgPrint ("Page heap: Last stack @ %p, Current stack @ %p \n", 05276 RtlpDphLastValidationStack, 05277 RtlpDphCurrentValidationStack); 05278 05279 DbgBreakPoint (); 05280 } 05281 }

const WCHAR * RtlpDphIsDllTargeted const WCHAR *  Name  ) 
 

Definition at line 5143 of file heappage.c.

References Name, NULL, RtlpDphTargetDllsUnicode, and RtlUpcaseUnicodeChar().

Referenced by LdrpDphInitializeTargetDll(), and RtlpDphTargetDllsLoadCallBack().

05146 { 05147 const WCHAR * All; 05148 ULONG I, J; 05149 05150 All = RtlpDphTargetDllsUnicode.Buffer; 05151 05152 for (I = 0; All[I]; I += 1) { 05153 05154 for (J = 0; All[I+J] && Name[J]; J += 1) { 05155 if (RtlUpcaseUnicodeChar(All[I+J]) != RtlUpcaseUnicodeChar(Name[J])) { 05156 break; 05157 } 05158 } 05159 05160 if (Name[J]) { 05161 continue; 05162 } 05163 else { 05164 // we got to the end of string 05165 return &(All[I]); 05166 } 05167 } 05168 05169 return NULL; 05170 }

BOOLEAN RtlpDphIsNormalFreeHeapBlock PVOID  Block,
PULONG  Reason,
BOOLEAN  CheckPattern
 

Definition at line 4193 of file heappage.c.

References DEBUG_ASSERT, EXCEPTION_EXECUTE_HANDLER, FALSE, NULL, and TRUE.

Referenced by RtlpDphFreeDelayedBlocksFromHeap(), and RtlpDphTrimDelayedFreeQueue().

04198 { 04199 PDPH_BLOCK_INFORMATION Info; 04200 BOOLEAN Corrupted = FALSE; 04201 PUCHAR Current; 04202 PUCHAR FillStart; 04203 PUCHAR FillEnd; 04204 04205 DEBUG_ASSERT (Reason != NULL); 04206 *Reason = 0; 04207 04208 Info = (PDPH_BLOCK_INFORMATION)Block - 1; 04209 04210 try { 04211 04212 // 04213 // If heap pointer is null we will just ignore this field. 04214 // This can happen during heap destroy operations where 04215 // the page heap got destroyed but the normal heap is still 04216 // alive. 04217 // 04218 04219 if (Info->StartStamp != DPH_NORMAL_BLOCK_START_STAMP_FREE) { 04220 *Reason |= DPH_ERROR_CORRUPTED_START_STAMP; 04221 Corrupted = TRUE; 04222 } 04223 04224 if (Info->EndStamp != DPH_NORMAL_BLOCK_END_STAMP_FREE) { 04225 *Reason |= DPH_ERROR_CORRUPTED_END_STAMP; 04226 Corrupted = TRUE; 04227 } 04228 04229 // 04230 // Check the block suffix byte pattern. 04231 // 04232 04233 if (CheckPattern) { 04234 04235 FillStart = (PUCHAR)Block + Info->RequestedSize; 04236 FillEnd = FillStart + USER_ALIGNMENT; 04237 04238 for (Current = FillStart; Current < FillEnd; Current++) { 04239 04240 if (*Current != DPH_NORMAL_BLOCK_SUFFIX) { 04241 04242 *Reason |= DPH_ERROR_CORRUPTED_SUFFIX_PATTERN; 04243 Corrupted = TRUE; 04244 break; 04245 } 04246 } 04247 } 04248 04249 // 04250 // Check the block infix byte pattern. 04251 // 04252 04253 if (CheckPattern) { 04254 04255 FillStart = (PUCHAR)Block; 04256 FillEnd = FillStart 04257 + ((Info->RequestedSize > USER_ALIGNMENT) ? USER_ALIGNMENT : Info->RequestedSize); 04258 04259 for (Current = FillStart; Current < FillEnd; Current++) { 04260 04261 if (*Current != DPH_FREE_BLOCK_INFIX) { 04262 04263 *Reason |= DPH_ERROR_CORRUPTED_INFIX_PATTERN; 04264 Corrupted = TRUE; 04265 break; 04266 } 04267 } 04268 } 04269 } 04270 except (EXCEPTION_EXECUTE_HANDLER) { 04271 04272 *Reason |= DPH_ERROR_RAISED_EXCEPTION; 04273 Corrupted = TRUE; 04274 } 04275 04276 if (Corrupted) { 04277 return FALSE; 04278 } 04279 else { 04280 return TRUE; 04281 } 04282 }

BOOLEAN RtlpDphIsNormalHeapBlock PDPH_HEAP_ROOT  Heap,
PVOID  Block,
PULONG  Reason,
BOOLEAN  CheckPattern
 

Definition at line 4123 of file heappage.c.

References DEBUG_ASSERT, EXCEPTION_EXECUTE_HANDLER, FALSE, NULL, and TRUE.

Referenced by RtlpDphNormalHeapFree(), RtlpDphNormalHeapGetUserInfo(), RtlpDphNormalHeapReAllocate(), RtlpDphNormalHeapSetUserFlags(), RtlpDphNormalHeapSetUserValue(), RtlpDphNormalHeapSize(), and RtlpDphNormalHeapValidate().

04129 { 04130 PDPH_BLOCK_INFORMATION Info; 04131 BOOLEAN Corrupted = FALSE; 04132 PUCHAR Current; 04133 PUCHAR FillStart; 04134 PUCHAR FillEnd; 04135 04136 DEBUG_ASSERT (Reason != NULL); 04137 *Reason = 0; 04138 04139 Info = (PDPH_BLOCK_INFORMATION)Block - 1; 04140 04141 try { 04142 04143 if (Info->Heap != Heap) { 04144 *Reason |= DPH_ERROR_CORRUPTED_HEAP_POINTER; 04145 Corrupted = TRUE; 04146 } 04147 04148 if (Info->StartStamp != DPH_NORMAL_BLOCK_START_STAMP_ALLOCATED) { 04149 *Reason |= DPH_ERROR_CORRUPTED_START_STAMP; 04150 Corrupted = TRUE; 04151 } 04152 04153 if (Info->EndStamp != DPH_NORMAL_BLOCK_END_STAMP_ALLOCATED) { 04154 *Reason |= DPH_ERROR_CORRUPTED_END_STAMP; 04155 Corrupted = TRUE; 04156 } 04157 04158 // 04159 // Check the block suffix byte pattern. 04160 // 04161 04162 if (CheckPattern) { 04163 04164 FillStart = (PUCHAR)Block + Info->RequestedSize; 04165 FillEnd = FillStart + USER_ALIGNMENT; 04166 04167 for (Current = FillStart; Current < FillEnd; Current++) { 04168 04169 if (*Current != DPH_NORMAL_BLOCK_SUFFIX) { 04170 04171 *Reason |= DPH_ERROR_CORRUPTED_SUFFIX_PATTERN; 04172 Corrupted = TRUE; 04173 break; 04174 } 04175 } 04176 } 04177 } 04178 except (EXCEPTION_EXECUTE_HANDLER) { 04179 04180 *Reason |= DPH_ERROR_RAISED_EXCEPTION; 04181 Corrupted = TRUE; 04182 } 04183 04184 if (Corrupted) { 04185 return FALSE; 04186 } 04187 else { 04188 return TRUE; 04189 } 04190 }

BOOLEAN RtlpDphIsPageHeapBlock PDPH_HEAP_ROOT  Heap,
PVOID  Block,
PULONG  Reason,
BOOLEAN  CheckPattern
 

Definition at line 4049 of file heappage.c.

References DEBUG_ASSERT, EXCEPTION_EXECUTE_HANDLER, FALSE, NULL, PAGE_SIZE, ROUNDUP2, and TRUE.

Referenced by RtlpDebugPageHeapDestroy(), RtlpDebugPageHeapFree(), and RtlpDebugPageHeapReAllocate().

04055 { 04056 PDPH_BLOCK_INFORMATION Info; 04057 BOOLEAN Corrupted = FALSE; 04058 PUCHAR Current; 04059 PUCHAR FillStart; 04060 PUCHAR FillEnd; 04061 04062 DEBUG_ASSERT (Reason != NULL); 04063 *Reason = 0; 04064 04065 try { 04066 04067 Info = (PDPH_BLOCK_INFORMATION)Block - 1; 04068 04069 // 04070 // Start checking ... 04071 // 04072 04073 if (Info->StartStamp != DPH_PAGE_BLOCK_START_STAMP_ALLOCATED) { 04074 *Reason |= DPH_ERROR_CORRUPTED_START_STAMP; 04075 Corrupted = TRUE; 04076 } 04077 04078 if (Info->EndStamp != DPH_PAGE_BLOCK_END_STAMP_ALLOCATED) { 04079 *Reason |= DPH_ERROR_CORRUPTED_END_STAMP; 04080 Corrupted = TRUE; 04081 } 04082 04083 if (Info->Heap != Heap) { 04084 *Reason |= DPH_ERROR_CORRUPTED_HEAP_POINTER; 04085 Corrupted = TRUE; 04086 } 04087 04088 // 04089 // Check the block suffix byte pattern. 04090 // 04091 04092 if (CheckPattern) { 04093 04094 FillStart = (PUCHAR)Block + Info->RequestedSize; 04095 FillEnd = (PUCHAR)ROUNDUP2((ULONG_PTR)FillStart, PAGE_SIZE); 04096 04097 for (Current = FillStart; Current < FillEnd; Current++) { 04098 04099 if (*Current != DPH_PAGE_BLOCK_SUFFIX) { 04100 04101 *Reason |= DPH_ERROR_CORRUPTED_SUFFIX_PATTERN; 04102 Corrupted = TRUE; 04103 break; 04104 } 04105 } 04106 } 04107 } 04108 except (EXCEPTION_EXECUTE_HANDLER) { 04109 04110 *Reason |= DPH_ERROR_RAISED_EXCEPTION; 04111 Corrupted = TRUE; 04112 } 04113 04114 if (Corrupted) { 04115 return FALSE; 04116 } 04117 else { 04118 return TRUE; 04119 } 04120 }

PRTL_TRACE_BLOCK RtlpDphLogStackTrace ULONG  FramesToSkip  ) 
 

Definition at line 5026 of file heappage.c.

References Count, FALSE, NULL, RtlCaptureStackBackTrace(), and RtlpDphTraceDatabase.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapReAllocate(), RtlpDphInternalValidatePageHeap(), RtlpDphNormalHeapFree(), RtlpDphWriteNormalHeapBlockInformation(), and RtlpDphWritePageHeapBlockInformation().

05029 { 05030 PVOID Trace [DPH_MAX_STACK_LENGTH]; 05031 ULONG Hash; 05032 ULONG Count; 05033 PRTL_TRACE_BLOCK Block; 05034 BOOLEAN Result; 05035 05036 Count = RtlCaptureStackBackTrace ( 05037 1 + FramesToSkip, 05038 DPH_MAX_STACK_LENGTH, 05039 Trace, 05040 &Hash); 05041 05042 if (Count == 0 || RtlpDphTraceDatabase == NULL) { 05043 return NULL; 05044 } 05045 05046 Result = RtlTraceDatabaseAdd ( 05047 RtlpDphTraceDatabase, 05048 Count, 05049 Trace, 05050 &Block); 05051 05052 if (Result == FALSE) { 05053 return NULL; 05054 } 05055 else { 05056 return Block; 05057 } 05058 }

BOOLEAN RtlpDphNeedToTrimDelayedFreeQueue PSIZE_T  TrimSize  ) 
 

Definition at line 4846 of file heappage.c.

References FALSE, PAGE_SIZE, RtlpDphDelayedFreeCacheSize, RtlpDphDelayedFreeQueueLock, RtlpDphMemoryUsedByDelayedFreeBlocks, and TRUE.

Referenced by RtlpDphNormalHeapFree().

04849 { 04850 BOOLEAN Result; 04851 04852 RtlEnterCriticalSection (&RtlpDphDelayedFreeQueueLock); 04853 04854 if (RtlpDphMemoryUsedByDelayedFreeBlocks > RtlpDphDelayedFreeCacheSize) { 04855 04856 *TrimSize = RtlpDphMemoryUsedByDelayedFreeBlocks - RtlpDphDelayedFreeCacheSize; 04857 04858 if (*TrimSize < PAGE_SIZE) { 04859 *TrimSize = PAGE_SIZE; 04860 } 04861 04862 Result = TRUE; 04863 } 04864 else { 04865 04866 Result = FALSE; 04867 } 04868 04869 RtlLeaveCriticalSection (&RtlpDphDelayedFreeQueueLock); 04870 return Result; 04871 }

PVOID RtlpDphNormalHeapAllocate PDPH_HEAP_ROOT  Heap,
ULONG  Flags,
SIZE_T  Size
 

Definition at line 4403 of file heappage.c.

References BUMP_GLOBAL_COUNTER, BUMP_SIZE_COUNTER, NULL, RtlAllocateHeap, RtlpDphWriteNormalHeapBlockInformation(), and Size.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapReAllocate(), and RtlpDphNormalHeapReAllocate().

04408 { 04409 PVOID Block; 04410 PDPH_BLOCK_INFORMATION Info; 04411 ULONG Hash; 04412 SIZE_T ActualSize; 04413 SIZE_T RequestedSize; 04414 ULONG Reason; 04415 04416 BUMP_GLOBAL_COUNTER (DPH_COUNTER_NO_OF_NORMAL_ALLOCS); 04417 BUMP_SIZE_COUNTER (Size); 04418 04419 Heap->Counter[DPH_COUNTER_NO_OF_NORMAL_ALLOCS] += 1; 04420 04421 RequestedSize = Size; 04422 ActualSize = Size + sizeof(DPH_BLOCK_INFORMATION) + USER_ALIGNMENT; 04423 04424 Block = RtlAllocateHeap ( 04425 Heap->NormalHeap, 04426 Flags, 04427 ActualSize); 04428 04429 if (Block == NULL) { 04430 04431 // 04432 // (SilviuC): If we have memory pressure we might want 04433 // to trim the delayed free queues. We do not do this 04434 // right now because the threshold is kind of small. 04435 // 04436 04437 return NULL; 04438 } 04439 04440 RtlpDphWriteNormalHeapBlockInformation ( 04441 Heap, 04442 (PDPH_BLOCK_INFORMATION)Block + 1, 04443 RequestedSize, 04444 ActualSize); 04445 04446 if (! (Flags & HEAP_ZERO_MEMORY)) { 04447 04448 RtlFillMemory ((PDPH_BLOCK_INFORMATION)Block + 1, 04449 RequestedSize, 04450 DPH_NORMAL_BLOCK_INFIX); 04451 } 04452 04453 return (PVOID)((PDPH_BLOCK_INFORMATION)Block + 1); 04454 }

BOOLEAN RtlpDphNormalHeapFree PDPH_HEAP_ROOT  Heap,
ULONG  Flags,
PVOID  Block
 

Definition at line 4458 of file heappage.c.

References BUMP_GLOBAL_COUNTER, DPH_DEBUG_NEVER_FREE, FALSE, NULL, RtlpDphAddToDelayedFreeQueue(), RtlpDphDebugLevel, RtlpDphIsNormalHeapBlock(), RtlpDphLogStackTrace(), RtlpDphNeedToTrimDelayedFreeQueue(), RtlpDphReportCorruptedBlock(), RtlpDphTraceDatabase, RtlpDphTrimDelayedFreeQueue(), and TRUE.

Referenced by RtlpDebugPageHeapFree(), and RtlpDphNormalHeapReAllocate().

04463 { 04464 PDPH_BLOCK_INFORMATION Info; 04465 BOOLEAN Success; 04466 ULONG Reason; 04467 ULONG Hash; 04468 SIZE_T TrimSize; 04469 04470 BUMP_GLOBAL_COUNTER (DPH_COUNTER_NO_OF_NORMAL_FREES); 04471 Heap->Counter[DPH_COUNTER_NO_OF_NORMAL_FREES] += 1; 04472 04473 Info = (PDPH_BLOCK_INFORMATION)Block - 1; 04474 04475 if (! RtlpDphIsNormalHeapBlock(Heap, Block, &Reason, TRUE)) { 04476 04477 RtlpDphReportCorruptedBlock (Block, Reason); 04478 04479 return FALSE; 04480 } 04481 04482 // 04483 // Save the free stack trace. 04484 // 04485 04486 if ((Heap->ExtraFlags & PAGE_HEAP_COLLECT_STACK_TRACES)) { 04487 04488 if (Info->StackTrace) { 04489 04490 RtlTraceDatabaseLock (RtlpDphTraceDatabase); 04491 ((PRTL_TRACE_BLOCK)(Info->StackTrace))->UserCount -= 1; 04492 ((PRTL_TRACE_BLOCK)(Info->StackTrace))->UserSize -= Info->RequestedSize; 04493 RtlTraceDatabaseUnlock (RtlpDphTraceDatabase); 04494 } 04495 04496 Info->StackTrace = RtlpDphLogStackTrace (3); 04497 } 04498 else { 04499 Info->StackTrace = NULL; 04500 } 04501 04502 // 04503 // Mark the block as freed. 04504 // 04505 04506 Info->StartStamp -= 1; 04507 Info->EndStamp -= 1; 04508 04509 // 04510 // Wipe out all the information in the block so that it cannot 04511 // be used while free. The pattern looks like a kernel pointer 04512 // and if we are lucky enough the buggy code might use a value 04513 // from the block as a pointer and instantly access violate. 04514 // 04515 04516 RtlFillMemory ( 04517 Info + 1, 04518 Info->RequestedSize, 04519 DPH_FREE_BLOCK_INFIX); 04520 04521 // 04522 // It is useful during debugging sessions to not free at 04523 // all so that you can detect use after free, etc. 04524 // 04525 04526 if ((RtlpDphDebugLevel & DPH_DEBUG_NEVER_FREE)) { 04527 04528 return TRUE; 04529 } 04530 04531 // 04532 // Add block to the delayed free queue. 04533 // 04534 04535 RtlpDphAddToDelayedFreeQueue (Info); 04536 04537 // 04538 // If we are over the threshold we need to really free 04539 // some of the guys. 04540 // 04541 // (SilviuC): should make this threshold more fine tuned. 04542 // 04543 04544 Success = TRUE; 04545 04546 if (RtlpDphNeedToTrimDelayedFreeQueue(&TrimSize)) { 04547 04548 RtlpDphTrimDelayedFreeQueue (TrimSize, Flags); 04549 } 04550 04551 return Success; 04552 }

BOOLEAN RtlpDphNormalHeapGetUserInfo IN PDPH_HEAP_ROOT  Heap,
IN ULONG  Flags,
IN PVOID  Address,
OUT PVOID *  UserValue,
OUT PULONG  UserFlags
 

Definition at line 4722 of file heappage.c.

References FALSE, RtlGetUserInfoHeap(), RtlpDphIsNormalHeapBlock(), and RtlpDphReportCorruptedBlock().

Referenced by RtlpDebugPageHeapGetUserInfo().

04729 { 04730 BOOLEAN Success; 04731 ULONG Reason; 04732 04733 if (! RtlpDphIsNormalHeapBlock(Heap, Address, &Reason, FALSE)) { 04734 04735 RtlpDphReportCorruptedBlock (Address, Reason); 04736 04737 return FALSE; 04738 } 04739 04740 Success = RtlGetUserInfoHeap ( 04741 Heap->NormalHeap, 04742 Flags, 04743 (PDPH_BLOCK_INFORMATION)Address - 1, 04744 UserValue, 04745 UserFlags); 04746 04747 return Success; 04748 }

PVOID RtlpDphNormalHeapReAllocate PDPH_HEAP_ROOT  Heap,
ULONG  Flags,
PVOID  OldBlock,
SIZE_T  Size
 

Definition at line 4556 of file heappage.c.

References BUMP_GLOBAL_COUNTER, BUMP_SIZE_COUNTER, NULL, RtlpDphIsNormalHeapBlock(), RtlpDphNormalHeapAllocate(), RtlpDphNormalHeapFree(), RtlpDphReportCorruptedBlock(), Size, and TRUE.

Referenced by RtlpDebugPageHeapReAllocate().

04562 { 04563 PVOID Block; 04564 PDPH_BLOCK_INFORMATION Info; 04565 ULONG Hash; 04566 SIZE_T CopySize; 04567 ULONG Reason; 04568 04569 BUMP_GLOBAL_COUNTER (DPH_COUNTER_NO_OF_NORMAL_REALLOCS); 04570 BUMP_SIZE_COUNTER (Size); 04571 04572 Heap->Counter[DPH_COUNTER_NO_OF_NORMAL_REALLOCS] += 1; 04573 04574 Info = (PDPH_BLOCK_INFORMATION)OldBlock - 1; 04575 04576 if (! RtlpDphIsNormalHeapBlock(Heap, OldBlock, &Reason, TRUE)) { 04577 04578 RtlpDphReportCorruptedBlock (OldBlock, Reason); 04579 04580 return NULL; 04581 } 04582 04583 // 04584 // Note that this operation will bump the counters for 04585 // normal allocations. Decided to leave this situation 04586 // as it is. 04587 // 04588 04589 Block = RtlpDphNormalHeapAllocate (Heap, Flags, Size); 04590 04591 if (Block == NULL) { 04592 return NULL; 04593 } 04594 04595 // 04596 // Copy old block stuff into the new block and then 04597 // free old block. 04598 // 04599 04600 if (Size < Info->RequestedSize) { 04601 CopySize = Size; 04602 } 04603 else { 04604 CopySize = Info->RequestedSize; 04605 } 04606 04607 RtlCopyMemory (Block, OldBlock, CopySize); 04608 04609 // 04610 // Free the old guy. 04611 // 04612 04613 RtlpDphNormalHeapFree (Heap, Flags, OldBlock); 04614 04615 return Block; 04616 }

BOOLEAN RtlpDphNormalHeapSetUserFlags IN PDPH_HEAP_ROOT  Heap,
IN ULONG  Flags,
IN PVOID  Address,
IN ULONG  UserFlagsReset,
IN ULONG  UserFlagsSet
 

Definition at line 4664 of file heappage.c.

References FALSE, RtlpDphIsNormalHeapBlock(), RtlpDphReportCorruptedBlock(), and RtlSetUserFlagsHeap().

Referenced by RtlpDebugPageHeapSetUserFlags().

04671 { 04672 BOOLEAN Success; 04673 ULONG Reason; 04674 04675 if (! RtlpDphIsNormalHeapBlock(Heap, Address, &Reason, FALSE)) { 04676 04677 RtlpDphReportCorruptedBlock (Address, Reason); 04678 04679 return FALSE; 04680 } 04681 04682 Success = RtlSetUserFlagsHeap ( 04683 Heap->NormalHeap, 04684 Flags, 04685 (PDPH_BLOCK_INFORMATION)Address - 1, 04686 UserFlagsReset, 04687 UserFlagsSet); 04688 04689 return Success; 04690 }

BOOLEAN RtlpDphNormalHeapSetUserValue IN PDPH_HEAP_ROOT  Heap,
IN ULONG  Flags,
IN PVOID  Address,
IN PVOID  UserValue
 

Definition at line 4694 of file heappage.c.

References FALSE, RtlpDphIsNormalHeapBlock(), RtlpDphReportCorruptedBlock(), and RtlSetUserValueHeap().

Referenced by RtlpDebugPageHeapSetUserValue().

04700 { 04701 BOOLEAN Success; 04702 ULONG Reason; 04703 04704 if (! RtlpDphIsNormalHeapBlock(Heap, Address, &Reason, FALSE)) { 04705 04706 RtlpDphReportCorruptedBlock (Address, Reason); 04707 04708 return FALSE; 04709 } 04710 04711 Success = RtlSetUserValueHeap ( 04712 Heap->NormalHeap, 04713 Flags, 04714 (PDPH_BLOCK_INFORMATION)Address - 1, 04715 UserValue); 04716 04717 return Success; 04718 }

SIZE_T RtlpDphNormalHeapSize PDPH_HEAP_ROOT  Heap,
ULONG  Flags,
PVOID  Block
 

Definition at line 4620 of file heappage.c.

References DbgPrint, FALSE, RtlpDphIsNormalHeapBlock(), and RtlSizeHeap().

Referenced by RtlpDebugPageHeapSize().

04625 { 04626 PDPH_BLOCK_INFORMATION Info; 04627 SIZE_T Result; 04628 ULONG Reason; 04629 04630 Info = (PDPH_BLOCK_INFORMATION)Block - 1; 04631 04632 if (! RtlpDphIsNormalHeapBlock(Heap, Block, &Reason, FALSE)) { 04633 04634 // 04635 // We cannot stop here for a wrong block. 04636 // The users might use this function to validate 04637 // if a block belongs to the heap or not. However 04638 // they should use HeapValidate for that. 04639 // 04640 04641 #if DBG 04642 DbgPrint ("Page heap: warning: HeapSize called with " 04643 "invalid block @ %p (reason %0X) \n", Block, Reason); 04644 #endif 04645 04646 return (SIZE_T)-1; 04647 } 04648 04649 Result = RtlSizeHeap ( 04650 Heap->NormalHeap, 04651 Flags, 04652 Info); 04653 04654 if (Result == (SIZE_T)-1) { 04655 return Result; 04656 } 04657 else { 04658 return Result - sizeof(*Info) - USER_ALIGNMENT; 04659 } 04660 }

BOOLEAN RtlpDphNormalHeapValidate IN PDPH_HEAP_ROOT  Heap,
IN ULONG  Flags,
IN PVOID  Address
 

Definition at line 4752 of file heappage.c.

References DbgPrint, FALSE, NULL, RtlpDphIsNormalHeapBlock(), RtlValidateHeap(), and TRUE.

Referenced by RtlpDebugPageHeapValidate().

04757 { 04758 BOOLEAN Success; 04759 ULONG Reason; 04760 04761 if (Address == NULL) { 04762 04763 // 04764 // Validation for the whole heap. 04765 // 04766 04767 Success = RtlValidateHeap ( 04768 Heap->NormalHeap, 04769 Flags, 04770 Address); 04771 } 04772 else { 04773 04774 // 04775 // Validation for a heap block. 04776 // 04777 04778 if (! RtlpDphIsNormalHeapBlock(Heap, Address, &Reason, TRUE)) { 04779 04780 // 04781 // We cannot break in this case because the function might indeed 04782 // be called with invalid block. 04783 // 04784 // (SilviuC): we will leave this as a warning and delete it only 04785 // if it becomes annoying. 04786 // 04787 04788 #if DBG 04789 DbgPrint ("Page heap: warning: validate called with " 04790 "invalid block @ %p (reason %0X) \n", Address, Reason); 04791 #endif 04792 04793 return FALSE; 04794 } 04795 04796 Success = RtlValidateHeap ( 04797 Heap->NormalHeap, 04798 Flags, 04799 (PDPH_BLOCK_INFORMATION)Address - 1); 04800 } 04801 04802 return Success; 04803 }

VOID RtlpDphReportCorruptedBlock PVOID  Block,
ULONG  Reason
 

Definition at line 4016 of file heappage.c.

References DbgPrint.

Referenced by RtlpDebugPageHeapDestroy(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapReAllocate(), RtlpDphFreeDelayedBlocksFromHeap(), RtlpDphNormalHeapFree(), RtlpDphNormalHeapGetUserInfo(), RtlpDphNormalHeapReAllocate(), RtlpDphNormalHeapSetUserFlags(), RtlpDphNormalHeapSetUserValue(), and RtlpDphTrimDelayedFreeQueue().

04020 { 04021 DbgPrint ("Page heap: block @ %p is corrupted (reason %0X) \n", Block, Reason); 04022 04023 if ((Reason & DPH_ERROR_CORRUPTED_INFIX_PATTERN)) { 04024 DbgPrint ("Page heap: reason: corrupted infix pattern for freed block \n"); 04025 } 04026 if ((Reason & DPH_ERROR_CORRUPTED_START_STAMP)) { 04027 DbgPrint ("Page heap: reason: corrupted start stamp \n"); 04028 } 04029 if ((Reason & DPH_ERROR_CORRUPTED_END_STAMP)) { 04030 DbgPrint ("Page heap: reason: corrupted end stamp \n"); 04031 } 04032 if ((Reason & DPH_ERROR_CORRUPTED_HEAP_POINTER)) { 04033 DbgPrint ("Page heap: reason: corrupted heap pointer \n"); 04034 } 04035 if ((Reason & DPH_ERROR_CORRUPTED_PREFIX_PATTERN)) { 04036 DbgPrint ("Page heap: reason: corrupted prefix pattern \n"); 04037 } 04038 if ((Reason & DPH_ERROR_CORRUPTED_SUFFIX_PATTERN)) { 04039 DbgPrint ("Page heap: reason: corrupted suffix pattern \n"); 04040 } 04041 if ((Reason & DPH_ERROR_RAISED_EXCEPTION)) { 04042 DbgPrint ("Page heap: reason: raised exception while probing \n"); 04043 } 04044 04045 DbgBreakPoint (); 04046 }

PDPH_HEAP_BLOCK RtlpDphSearchBlockInList PDPH_HEAP_BLOCK  List,
PUCHAR  Address
 

Definition at line 5177 of file heappage.c.

References List, and NULL.

Referenced by RtlpDphInternalValidatePageHeap().

05181 { 05182 PDPH_HEAP_BLOCK Current; 05183 05184 for (Current = List; Current; Current = Current->pNextAlloc) { 05185 if (Current->pVirtualBlock == Address) { 05186 return Current; 05187 } 05188 } 05189 05190 return NULL; 05191 }

RtlpDphShouldAllocateInPageHeap PDPH_HEAP_ROOT  Heap,
SIZE_T  Size
 

Definition at line 3906 of file heappage.c.

References Count, FALSE, Index, NTSTATUS(), RtlCaptureStackBackTrace(), RtlpDphDllRangeEnd, RtlpDphDllRangeStart, RtlpDphRandomProbability, RtlpDphSizeRangeEnd, RtlpDphSizeRangeStart, RtlRandom(), Size, Status, and TRUE.

Referenced by RtlpDebugPageHeapAllocate(), and RtlpDebugPageHeapReAllocate().

03910 { 03911 SYSTEM_PERFORMANCE_INFORMATION PerfInfo; 03912 NTSTATUS Status; 03913 ULONG Random; 03914 ULONG Percentage; 03915 03916 // 03917 // If page heap is not enabled => normal heap. 03918 // 03919 03920 if (! (HeapRoot->ExtraFlags & PAGE_HEAP_ENABLE_PAGE_HEAP)) { 03921 return FALSE; 03922 } 03923 03924 // 03925 // If in size range => page heap 03926 // 03927 03928 else if ((HeapRoot->ExtraFlags & PAGE_HEAP_USE_SIZE_RANGE)) { 03929 03930 if (Size >= RtlpDphSizeRangeStart && Size <= RtlpDphSizeRangeEnd) { 03931 return TRUE; 03932 } 03933 else { 03934 return FALSE; 03935 } 03936 } 03937 03938 // 03939 // If in dll range => page heap 03940 // 03941 03942 else if ((HeapRoot->ExtraFlags & PAGE_HEAP_USE_DLL_RANGE)) { 03943 03944 PVOID StackTrace[32]; 03945 ULONG Count; 03946 ULONG Index; 03947 ULONG Hash; 03948 03949 Count = RtlCaptureStackBackTrace ( 03950 1, 03951 32, 03952 StackTrace, 03953 &Hash); 03954 03955 // 03956 // (SilviuC): should read DllRange as PVOIDs 03957 // 03958 03959 for (Index = 0; Index < Count; Index += 1) { 03960 if (PtrToUlong(StackTrace[Index]) >= RtlpDphDllRangeStart 03961 && PtrToUlong(StackTrace[Index]) <= RtlpDphDllRangeEnd) { 03962 03963 return TRUE; 03964 } 03965 } 03966 03967 return FALSE; 03968 } 03969 03970 // 03971 // If randomly decided => page heap 03972 // 03973 03974 else if ((HeapRoot->ExtraFlags & PAGE_HEAP_USE_RANDOM_DECISION)) { 03975 03976 Random = RtlRandom (& (HeapRoot->Seed)); 03977 03978 if ((Random % 100) < RtlpDphRandomProbability) { 03979 return TRUE; 03980 } 03981 else { 03982 return FALSE; 03983 } 03984 } 03985 03986 // 03987 // If call not generated from one of the target dlls => normal heap 03988 // 03989 03990 else if ((HeapRoot->ExtraFlags & PAGE_HEAP_USE_DLL_NAMES)) { 03991 03992 // We return false. The calls generated from target 03993 // dlls will never get into this function and therefore 03994 // we just return false signalling that we do not want 03995 // page heap verification for the rest of the world. 03996 // 03997 return FALSE; 03998 } 03999 04000 // 04001 // For all other cases we will allocate in the page heap. 04002 // 04003 04004 else { 04005 return TRUE; 04006 } 04007 }

VOID RtlpDphTargetDllsLoadCallBack PUNICODE_STRING  Name,
PVOID  Address,
ULONG  Size
 

Definition at line 5087 of file heappage.c.

References DbgPrint, Name, NULL, PDPH_TARGET_DLL, RtlAllocateHeap, RtlCreateUnicodeString(), RtlFreeHeap, RtlpDphIsDllTargeted(), RtlpDphTargetDllsInitialized, RtlpDphTargetDllsList, RtlpDphTargetDllsLock, and Size.

05098 { 05099 PDPH_TARGET_DLL Descriptor; 05100 05101 // 05102 // Get out if we are in some weird condition. 05103 // 05104 05105 if (! RtlpDphTargetDllsInitialized) { 05106 return; 05107 } 05108 05109 if (! RtlpDphIsDllTargeted (Name->Buffer)) { 05110 return; 05111 } 05112 05113 Descriptor = RtlAllocateHeap (RtlProcessHeap(), 0, sizeof *Descriptor); 05114 05115 if (Descriptor == NULL) { 05116 return; 05117 } 05118 05119 if (! RtlCreateUnicodeString (&(Descriptor->Name), Name->Buffer)) { 05120 RtlFreeHeap (RtlProcessHeap(), 0, Descriptor); 05121 return; 05122 } 05123 05124 Descriptor->StartAddress = Address; 05125 Descriptor->EndAddress = (PUCHAR)Address + Size; 05126 05127 RtlEnterCriticalSection (&RtlpDphTargetDllsLock); 05128 InsertTailList (&(RtlpDphTargetDllsList), &(Descriptor->List)); 05129 RtlLeaveCriticalSection (&RtlpDphTargetDllsLock); 05130 05131 // 05132 // SilviuC: This message should be printed only if a target 05133 // dll has been identified. 05134 // 05135 05136 DbgPrint("Page heap: loaded target dll %ws [%p - %p]\n", 05137 Descriptor->Name.Buffer, 05138 Descriptor->StartAddress, 05139 Descriptor->EndAddress); 05140 }

VOID RtlpDphTargetDllsLogicInitialize  ) 
 

Definition at line 5078 of file heappage.c.

References RtlInitializeCriticalSection(), RtlpDphTargetDllsInitialized, RtlpDphTargetDllsList, RtlpDphTargetDllsLock, and TRUE.

Referenced by RtlpDebugPageHeapCreate().

05080 { 05081 RtlInitializeCriticalSection (&RtlpDphTargetDllsLock); 05082 InitializeListHead (&RtlpDphTargetDllsList); 05083 RtlpDphTargetDllsInitialized = TRUE; 05084 }

VOID RtlpDphTrimDelayedFreeQueue SIZE_T  TrimSize,
ULONG  Flags
 

Definition at line 4874 of file heappage.c.

References FreeQueue(), RtlFreeHeap, RtlpDphDelayedFreeCacheSize, RtlpDphDelayedFreeQueue, RtlpDphDelayedFreeQueueLock, RtlpDphIsNormalFreeHeapBlock(), RtlpDphMemoryUsedByDelayedFreeBlocks, RtlpDphNumberOfDelayedFreeBlocks, RtlpDphReportCorruptedBlock(), and TRUE.

Referenced by RtlpDphNormalHeapFree().

04880 : 04881 04882 This routine trims the delayed free queue (global per process). 04883 If trim size is zero it will trim up to a global threshold 04884 (RtlpDphDelayedFreeCacheSize) otherwise uses `TrimSize'. 04885 04886 Note. This function might become a little bit of a bottleneck 04887 because it is called by every free operation. Because of this 04888 it is better to always call RtlpDphNeedToTrimDelayedFreeQueue 04889 first. 04890 04891 Arguments: 04892 04893 TrimSize: amount to trim (in bytes). If zero it trims down to 04894 a global threshold. 04895 04896 Flags: flags for free operation. 04897 04898 Return Value: 04899 04900 None. 04901 04902 Environment: 04903 04904 Called from RtlpDphNormalXxx (normal heap management) routines. 04905 04906 --*/ 04907 04908 { 04909 ULONG Reason; 04910 SIZE_T CurrentTrimmed = 0; 04911 PDPH_BLOCK_INFORMATION QueueBlock; 04912 PLIST_ENTRY ListEntry; 04913 04914 RtlEnterCriticalSection (&RtlpDphDelayedFreeQueueLock); 04915 04916 if (TrimSize == 0) { 04917 if (RtlpDphMemoryUsedByDelayedFreeBlocks > RtlpDphDelayedFreeCacheSize) { 04918 04919 TrimSize = RtlpDphMemoryUsedByDelayedFreeBlocks - RtlpDphDelayedFreeCacheSize; 04920 } 04921 } 04922 04923 while (TRUE) { 04924 04925 // 04926 // Did we achieve our trimming goal? 04927 // 04928 04929 if (CurrentTrimmed >= TrimSize) { 04930 break; 04931 } 04932 04933 // 04934 // The list can get empty since we remove blocks from it. 04935 // 04936 04937 if (IsListEmpty(&RtlpDphDelayedFreeQueue)) { 04938 break; 04939 } 04940 04941 ListEntry = RemoveHeadList (&RtlpDphDelayedFreeQueue); 04942 QueueBlock = CONTAINING_RECORD (ListEntry, DPH_BLOCK_INFORMATION, FreeQueue); 04943 04944 if (! RtlpDphIsNormalFreeHeapBlock(QueueBlock + 1, &Reason, TRUE)) { 04945 04946 RtlpDphReportCorruptedBlock (QueueBlock + 1, Reason); 04947 } 04948 04949 RtlpDphMemoryUsedByDelayedFreeBlocks -= QueueBlock->ActualSize; 04950 RtlpDphNumberOfDelayedFreeBlocks -= 1; 04951 CurrentTrimmed += QueueBlock->ActualSize; 04952 04953 RtlFreeHeap (((PDPH_HEAP_ROOT)(QueueBlock->Heap))->NormalHeap, Flags, QueueBlock); 04954 } 04955 04956 RtlLeaveCriticalSection (&RtlpDphDelayedFreeQueueLock); 04957 }

BOOLEAN RtlpDphWriteNormalHeapBlockInformation PDPH_HEAP_ROOT  Heap,
PVOID  Block,
SIZE_T  RequestedSize,
SIZE_T  ActualSize
 

Definition at line 4334 of file heappage.c.

References NULL, RtlpDphLogStackTrace(), RtlpDphTraceDatabase, and TRUE.

Referenced by RtlpDphNormalHeapAllocate().

04340 { 04341 PDPH_BLOCK_INFORMATION Info; 04342 PUCHAR FillStart; 04343 PUCHAR FillEnd; 04344 ULONG Hash; 04345 ULONG Reason; 04346 04347 Info = (PDPH_BLOCK_INFORMATION)Block - 1; 04348 04349 // 04350 // Size and stamp information 04351 // 04352 04353 Info->Heap = Heap; 04354 Info->RequestedSize = RequestedSize; 04355 Info->ActualSize = ActualSize; 04356 Info->StartStamp = DPH_NORMAL_BLOCK_START_STAMP_ALLOCATED; 04357 Info->EndStamp = DPH_NORMAL_BLOCK_END_STAMP_ALLOCATED; 04358 04359 Info->FreeQueue.Blink = NULL; 04360 Info->FreeQueue.Flink = NULL; 04361 04362 // 04363 // Fill the block suffix pattern. 04364 // We fill only USER_ALIGNMENT bytes. 04365 // 04366 04367 FillStart = (PUCHAR)Block + RequestedSize; 04368 FillEnd = FillStart + USER_ALIGNMENT; 04369 04370 RtlFillMemory (FillStart, FillEnd - FillStart, DPH_NORMAL_BLOCK_SUFFIX); 04371 04372 // 04373 // Capture stack trace 04374 // 04375 04376 if ((Heap->ExtraFlags & PAGE_HEAP_COLLECT_STACK_TRACES)) { 04377 04378 Info->StackTrace = RtlpDphLogStackTrace (4); 04379 04380 if (Info->StackTrace) { 04381 04382 RtlTraceDatabaseLock (RtlpDphTraceDatabase); 04383 ((PRTL_TRACE_BLOCK)(Info->StackTrace))->UserCount += 1; 04384 ((PRTL_TRACE_BLOCK)(Info->StackTrace))->UserSize += RequestedSize; 04385 ((PRTL_TRACE_BLOCK)(Info->StackTrace))->UserContext = Heap; 04386 RtlTraceDatabaseUnlock (RtlpDphTraceDatabase); 04387 } 04388 04389 } 04390 else { 04391 Info->StackTrace = NULL; 04392 } 04393 04394 return TRUE; 04395 }

BOOLEAN RtlpDphWritePageHeapBlockInformation PDPH_HEAP_ROOT  Heap,
PVOID  Block,
SIZE_T  RequestedSize,
SIZE_T  ActualSize
 

Definition at line 4285 of file heappage.c.

References NULL, PAGE_SIZE, ROUNDUP2, RtlpDphLogStackTrace(), and TRUE.

Referenced by RtlpDebugPageHeapAllocate().

04291 { 04292 PDPH_BLOCK_INFORMATION Info; 04293 PUCHAR FillStart; 04294 PUCHAR FillEnd; 04295 ULONG Hash; 04296 04297 // 04298 // Size and stamp information 04299 // 04300 04301 Info = (PDPH_BLOCK_INFORMATION)Block - 1; 04302 04303 Info->Heap = Heap; 04304 Info->RequestedSize = RequestedSize; 04305 Info->ActualSize = ActualSize; 04306 Info->StartStamp = DPH_PAGE_BLOCK_START_STAMP_ALLOCATED; 04307 Info->EndStamp = DPH_PAGE_BLOCK_END_STAMP_ALLOCATED; 04308 04309 // 04310 // Fill the block suffix pattern. 04311 // We fill up to USER_ALIGNMENT bytes. 04312 // 04313 04314 FillStart = (PUCHAR)Block + RequestedSize; 04315 FillEnd = (PUCHAR)ROUNDUP2((ULONG_PTR)FillStart, PAGE_SIZE); 04316 04317 RtlFillMemory (FillStart, FillEnd - FillStart, DPH_PAGE_BLOCK_SUFFIX); 04318 04319 // 04320 // Capture stack trace 04321 // 04322 04323 if ((Heap->ExtraFlags & PAGE_HEAP_COLLECT_STACK_TRACES)) { 04324 Info->StackTrace = RtlpDphLogStackTrace (3); 04325 } 04326 else { 04327 Info->StackTrace = NULL; 04328 } 04329 04330 return TRUE; 04331 }

int __cdecl sprintf char *  ,
const char *  ,
  ...
 

Referenced by AlGetPathnameFromComponent(), ChooseDisk(), CmpAddAliasEntry(), CmpCreateControlSet(), CmpFindControlSet(), CmpInitializeMachineDependentConfiguration(), CmpSetVersionData(), CreateCombi(), dc(), dmem(), DoMakePartitionSystemPartition(), DoPartitionCreate(), DoPartitionDelete(), DoSystemPartitionCreate(), DsoDump(), dt(), Dump(), FileOpenHookProc(), FileSaveHookProc(), FixDisk(), FmtQueryFatPartitionList(), GetFlags(), GetMaskedEnum(), InstallProfiles(), InternalUpgradeICM(), IoGetBootDiskInformation(), IopApplySystemPartitionProt(), IopCopyBootLogRegistryToFile(), IopCreateArcNames(), IopDriverCorrectnessPrintBuffer(), IopGetDumpStack(), IopMarkBootPartition(), IopReassignSystemRoot(), IopWriteIpAddressToRegistry(), IopWriteSummaryDump(), IoWriteCrashDump(), IsBootSelectionPartition(), KeBugCheckEx(), KeDumpMachineState(), KiDumpParameterImages(), ListDrivers(), LowGetDriveGeometry(), LowOpenDisk(), main(), MigrateSystemNT(), MiInitMachineDependent(), MiLoadSystemImage(), MyMoveDir(), RtlpDebugPageHeapProtectionText(), RtlpVerCompare(), SaveToFile(), SearchFile(), SelectOutFileName(), UpgradeClass(), WriteBatchResults(), and xHalIoAssignDriveLetters().


Variable Documentation

BOOLEAN RtlpDebugPageHeap
 

Definition at line 189 of file heappage.c.

Referenced by LdrpInitialize(), LdrpInitializeProcess(), RtlCreateHeap(), and RtlGetProcessHeaps().

PVOID RtlpDphCurrentValidationStack
 

Definition at line 5194 of file heappage.c.

Referenced by RtlpDphInternalValidatePageHeap().

ULONG RtlpDphDebugLevel
 

Definition at line 263 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCommitVM(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapDecommitVM(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapReAllocate(), and RtlpDphNormalHeapFree().

SIZE_T RtlpDphDelayedFreeCacheSize = 256 * PAGE_SIZE
 

Definition at line 293 of file heappage.c.

Referenced by RtlpDphNeedToTrimDelayedFreeQueue(), and RtlpDphTrimDelayedFreeQueue().

LIST_ENTRY RtlpDphDelayedFreeQueue
 

Definition at line 4816 of file heappage.c.

Referenced by RtlpDphAddToDelayedFreeQueue(), RtlpDphFreeDelayedBlocksFromHeap(), RtlpDphInitializeDelayedFreeQueue(), and RtlpDphTrimDelayedFreeQueue().

RTL_CRITICAL_SECTION RtlpDphDelayedFreeQueueLock
 

Definition at line 4811 of file heappage.c.

Referenced by RtlpDphAddToDelayedFreeQueue(), RtlpDphFreeDelayedBlocksFromHeap(), RtlpDphInitializeDelayedFreeQueue(), RtlpDphNeedToTrimDelayedFreeQueue(), and RtlpDphTrimDelayedFreeQueue().

ULONG RtlpDphDllRangeEnd
 

Definition at line 242 of file heappage.c.

Referenced by LdrpInitialize(), and RtlpDphShouldAllocateInPageHeap().

ULONG RtlpDphDllRangeStart
 

Definition at line 241 of file heappage.c.

Referenced by LdrpInitialize(), and RtlpDphShouldAllocateInPageHeap().

ULONG RtlpDphGlobalCounter[MAX_GLOBAL_COUNTER_INDEX+1]
 

Definition at line 285 of file heappage.c.

ULONG RtlpDphGlobalFlags = PAGE_HEAP_COLLECT_STACK_TRACES
 

Definition at line 231 of file heappage.c.

Referenced by LdrpDphInitializeTargetDll(), LdrpInitialize(), and RtlpDebugPageHeapCreate().

ULONG RtlpDphHeapListCount
 

Definition at line 211 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate(), RtlpDebugPageHeapDestroy(), and RtlpDebugPageHeapGetProcessHeaps().

RTL_CRITICAL_SECTION RtlpDphHeapListCriticalSection
 

Definition at line 208 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate(), RtlpDebugPageHeapDestroy(), and RtlpDebugPageHeapGetProcessHeaps().

BOOLEAN RtlpDphHeapListHasBeenInitialized
 

Definition at line 207 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapGetProcessHeaps().

PDPH_HEAP_ROOT RtlpDphHeapListHead
 

Definition at line 209 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate(), RtlpDebugPageHeapDestroy(), and RtlpDebugPageHeapGetProcessHeaps().

PDPH_HEAP_ROOT RtlpDphHeapListTail
 

Definition at line 210 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapDestroy().

PVOID RtlpDphLastValidationStack
 

Definition at line 5193 of file heappage.c.

Referenced by RtlpDphInternalValidatePageHeap().

SIZE_T RtlpDphMemoryUsedByDelayedFreeBlocks
 

Definition at line 4813 of file heappage.c.

Referenced by RtlpDphAddToDelayedFreeQueue(), RtlpDphFreeDelayedBlocksFromHeap(), RtlpDphInitializeDelayedFreeQueue(), RtlpDphNeedToTrimDelayedFreeQueue(), and RtlpDphTrimDelayedFreeQueue().

SIZE_T RtlpDphNumberOfDelayedFreeBlocks
 

Definition at line 4814 of file heappage.c.

Referenced by RtlpDphAddToDelayedFreeQueue(), RtlpDphFreeDelayedBlocksFromHeap(), RtlpDphInitializeDelayedFreeQueue(), and RtlpDphTrimDelayedFreeQueue().

ULONG RtlpDphRandomProbability
 

Definition at line 243 of file heappage.c.

Referenced by LdrpInitialize(), and RtlpDphShouldAllocateInPageHeap().

ULONG RtlpDphSizeCounter[MAX_SIZE_COUNTER_INDEX+1]
 

Definition at line 286 of file heappage.c.

ULONG RtlpDphSizeRangeEnd
 

Definition at line 240 of file heappage.c.

Referenced by LdrpInitialize(), and RtlpDphShouldAllocateInPageHeap().

ULONG RtlpDphSizeRangeStart
 

Definition at line 239 of file heappage.c.

Referenced by LdrpInitialize(), and RtlpDphShouldAllocateInPageHeap().

WCHAR RtlpDphTargetDlls[512]
 

Definition at line 244 of file heappage.c.

Referenced by LdrpDphInitializeTargetDll(), LdrpInitialize(), and RtlpDebugPageHeapCreate().

BOOLEAN RtlpDphTargetDllsInitialized
 

Definition at line 5066 of file heappage.c.

Referenced by RtlpDphTargetDllsLoadCallBack(), and RtlpDphTargetDllsLogicInitialize().

LIST_ENTRY RtlpDphTargetDllsList
 

Definition at line 5065 of file heappage.c.

Referenced by RtlpDphTargetDllsLoadCallBack(), and RtlpDphTargetDllsLogicInitialize().

RTL_CRITICAL_SECTION RtlpDphTargetDllsLock
 

Definition at line 5064 of file heappage.c.

Referenced by RtlpDphTargetDllsLoadCallBack(), and RtlpDphTargetDllsLogicInitialize().

UNICODE_STRING RtlpDphTargetDllsUnicode
 

Definition at line 245 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate(), and RtlpDphIsDllTargeted().

PRTL_TRACE_DATABASE RtlpDphTraceDatabase
 

Definition at line 301 of file heappage.c.

Referenced by RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapReAllocate(), RtlpDphLogStackTrace(), RtlpDphNormalHeapFree(), and RtlpDphWriteNormalHeapBlockInformation().

SIZE_T RtlpDphTraceDatabaseMaximumSize = 256 * PAGE_SIZE
 

Definition at line 300 of file heappage.c.

Referenced by RtlpDebugPageHeapCreate().

PCHAR RtlpDphVersion = "03/14/2000"
 

Definition at line 196 of file heappage.c.


Generated on Sat May 15 19:44:04 2004 for test by doxygen 1.3.7