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

heappage.h File Reference

#include "heappagi.h"

Go to the source code of this file.

Defines

#define DEBUG_PAGE_HEAP   1
#define HEAP_FLAG_PAGE_ALLOCS   0x01000000
#define HEAP_PROTECTION_ENABLED   0x02000000
#define HEAP_BREAK_WHEN_OUT_OF_VM   0x04000000
#define HEAP_NO_ALIGNMENT   0x08000000
#define IS_DEBUG_PAGE_HEAP_HANDLE(HeapHandle)   (((PHEAP)(HeapHandle))->ForceFlags & HEAP_FLAG_PAGE_ALLOCS )
#define IF_DEBUG_PAGE_HEAP_THEN_RETURN(Handle, ReturnThis)
#define IF_DEBUG_PAGE_HEAP_THEN_CALL(Handle, CallThis)
#define IF_DEBUG_PAGE_HEAP_THEN_BREAK(Handle, Text, ReturnThis)

Functions

PVOID RtlpDebugPageHeapCreate (IN ULONG Flags, IN PVOID HeapBase, IN SIZE_T ReserveSize, IN SIZE_T CommitSize, IN PVOID Lock, IN PRTL_HEAP_PARAMETERS Parameters)
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)
VOID RtlpDebugPageHeapBreak (PCH Text)


Define Documentation

#define DEBUG_PAGE_HEAP   1
 

Definition at line 17 of file heappage.h.

#define HEAP_BREAK_WHEN_OUT_OF_VM   0x04000000
 

Definition at line 50 of file heappage.h.

Referenced by RtlCreateHeap().

#define HEAP_FLAG_PAGE_ALLOCS   0x01000000
 

Definition at line 47 of file heappage.h.

Referenced by RtlpDebugPageHeapCreate(), and RtlpDebugPageHeapPointerFromHandle().

#define HEAP_NO_ALIGNMENT   0x08000000
 

Definition at line 51 of file heappage.h.

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

#define HEAP_PROTECTION_ENABLED   0x02000000
 

Definition at line 49 of file heappage.h.

Referenced by RtlCreateHeap(), RtlpDebugPageHeapProtectStructures(), and RtlpDebugPageHeapUnProtectStructures().

#define IF_DEBUG_PAGE_HEAP_THEN_BREAK Handle,
Text,
ReturnThis   ) 
 

Value:

{ \ if ( IS_DEBUG_PAGE_HEAP_HANDLE( Handle )) \ { \ RtlpDebugPageHeapBreak( Text ); \ return ReturnThis; \ } \ }

Definition at line 77 of file heappage.h.

#define IF_DEBUG_PAGE_HEAP_THEN_CALL Handle,
CallThis   ) 
 

Value:

{ \ if ( IS_DEBUG_PAGE_HEAP_HANDLE( Handle )) \ { \ CallThis; \ return; \ } \ }

Definition at line 67 of file heappage.h.

#define IF_DEBUG_PAGE_HEAP_THEN_RETURN Handle,
ReturnThis   ) 
 

Value:

{ \ if ( IS_DEBUG_PAGE_HEAP_HANDLE( Handle )) \ { \ return ReturnThis; \ } \ }

Definition at line 58 of file heappage.h.

Referenced by RtlCreateTagHeap(), RtlDebugAllocateHeap(), RtlDebugCompactHeap(), RtlDebugFreeHeap(), RtlDebugGetUserInfoHeap(), RtlDebugReAllocateHeap(), RtlDebugSetUserFlagsHeap(), RtlDebugSetUserValueHeap(), RtlDebugSizeHeap(), RtlDebugUsageHeap(), RtlDebugZeroHeap(), RtlDestroyHeap(), RtlExtendHeap(), RtlLockHeap(), RtlpHeapIsLocked(), RtlpSerializeHeap(), RtlQueryTagHeap(), RtlUnlockHeap(), and RtlWalkHeap().

#define IS_DEBUG_PAGE_HEAP_HANDLE HeapHandle   )     (((PHEAP)(HeapHandle))->ForceFlags & HEAP_FLAG_PAGE_ALLOCS )
 

Definition at line 54 of file heappage.h.

Referenced by RtlValidateHeap().


Function Documentation

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 }

VOID RtlpDebugPageHeapBreak PCH  Text  ) 
 

Referenced by RtlpDebugPageHeapAssert(), RtlpDebugPageHeapDestroy(), RtlpDebugPageHeapEnterCritSect(), RtlpDebugPageHeapGetProcessHeaps(), and RtlpDebugPageHeapPointerFromHandle().

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,
IN SIZE_T  ReserveSize,
IN SIZE_T  CommitSize,
IN PVOID  Lock,
IN PRTL_HEAP_PARAMETERS  Parameters
 

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 }

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 }

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 }

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 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 }

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 }

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 }

NTSTATUS RtlpDebugPageHeapReset IN PVOID  HeapHandle,
IN ULONG  Flags
 

Definition at line 3837 of file heappage.c.

03841 { 03842 return STATUS_SUCCESS; 03843 }

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 }

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 }

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 }


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