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

heapdll.c File Reference

#include "ntrtlp.h"
#include "heap.h"
#include "heappriv.h"

Go to the source code of this file.

Classes

struct  _RTL_HEAP_USAGE_INTERNAL

Defines

#define RTLP_STATIC_HEAP_LIST_SIZE   16

Typedefs

typedef _RTL_HEAP_USAGE_INTERNAL RTL_HEAP_USAGE_INTERNAL
typedef _RTL_HEAP_USAGE_INTERNALPRTL_HEAP_USAGE_INTERNAL

Functions

BOOLEAN RtlpGrowBlockInPlace (IN PHEAP Heap, IN ULONG Flags, IN PHEAP_ENTRY BusyBlock, IN SIZE_T Size, IN SIZE_T AllocationIndex)
PVOID RtlDebugReAllocateHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN SIZE_T Size)
BOOLEAN RtlDebugGetUserInfoHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, OUT PVOID *UserValue OPTIONAL, OUT PULONG UserFlags OPTIONAL)
BOOLEAN RtlDebugSetUserValueHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN PVOID UserValue)
BOOLEAN RtlDebugSetUserFlagsHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN ULONG UserFlagsReset, IN ULONG UserFlagsSet)
SIZE_T RtlDebugCompactHeap (IN PVOID HeapHandle, IN ULONG Flags)
NTSTATUS RtlDebugCreateTagHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PWSTR TagPrefix OPTIONAL, IN PWSTR TagNames)
PWSTR RtlDebugQueryTagHeap (IN PVOID HeapHandle, IN ULONG Flags, IN USHORT TagIndex, IN BOOLEAN ResetCounters, OUT PRTL_HEAP_TAG_INFO TagInfo OPTIONAL)
NTSTATUS RtlDebugUsageHeap (IN PVOID HeapHandle, IN ULONG Flags, IN OUT PRTL_HEAP_USAGE Usage)
BOOLEAN RtlDebugWalkHeap (IN PVOID HeapHandle, IN OUT PRTL_HEAP_WALK_ENTRY Entry)
PHEAP_TAG_ENTRY RtlpAllocateTags (PHEAP Heap, ULONG NumberOfTags)
PRTL_HEAP_USAGE_ENTRY RtlpFreeHeapUsageEntry (PRTL_HEAP_USAGE_INTERNAL Buffer, PRTL_HEAP_USAGE_ENTRY p)
NTSTATUS RtlpAllocateHeapUsageEntry (PRTL_HEAP_USAGE_INTERNAL Buffer, PRTL_HEAP_USAGE_ENTRY *pp)
NTSTATUS RtlInitializeHeapManager (VOID)
VOID RtlProtectHeap (IN PVOID HeapHandle, IN BOOLEAN MakeReadOnly)
BOOLEAN RtlLockHeap (IN PVOID HeapHandle)
BOOLEAN RtlUnlockHeap (IN PVOID HeapHandle)
PVOID RtlReAllocateHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN SIZE_T Size)
BOOLEAN RtlGetUserInfoHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, OUT PVOID *UserValue OPTIONAL, OUT PULONG UserFlags OPTIONAL)
BOOLEAN RtlSetUserValueHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN PVOID UserValue)
BOOLEAN RtlSetUserFlagsHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN ULONG UserFlagsReset, IN ULONG UserFlagsSet)
ULONG RtlCreateTagHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PWSTR TagPrefix OPTIONAL, IN PWSTR TagNames)
PWSTR RtlQueryTagHeap (IN PVOID HeapHandle, IN ULONG Flags, IN USHORT TagIndex, IN BOOLEAN ResetCounters, OUT PRTL_HEAP_TAG_INFO TagInfo OPTIONAL)
NTSTATUS RtlExtendHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID Base, IN SIZE_T Size)
SIZE_T NTAPI RtlCompactHeap (IN PVOID HeapHandle, IN ULONG Flags)
BOOLEAN RtlValidateHeap (PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress)
BOOLEAN RtlValidateProcessHeaps (VOID)
ULONG RtlGetProcessHeaps (ULONG NumberOfHeapsToReturn, PVOID *ProcessHeaps)
NTSTATUS RtlEnumProcessHeaps (PRTL_ENUM_HEAPS_ROUTINE EnumRoutine, PVOID Parameter)
NTSTATUS RtlUsageHeap (IN PVOID HeapHandle, IN ULONG Flags, IN OUT PRTL_HEAP_USAGE Usage)
NTSTATUS RtlWalkHeap (IN PVOID HeapHandle, IN OUT PRTL_HEAP_WALK_ENTRY Entry)
BOOLEAN RtlpCheckHeapSignature (IN PHEAP Heap, IN PCHAR Caller)
PHEAP_FREE_ENTRY RtlpCoalesceHeap (IN PHEAP Heap)
VOID RtlpAddHeapToProcessList (IN PHEAP Heap)
VOID RtlpRemoveHeapFromProcessList (IN PHEAP Heap)
PWSTR RtlpGetTagName (PHEAP Heap, USHORT TagIndex)
USHORT RtlpUpdateTagEntry (PHEAP Heap, USHORT TagIndex, SIZE_T OldSize, SIZE_T NewSize, HEAP_TAG_ACTION Action)
VOID RtlpResetTags (PHEAP Heap)
VOID RtlpDestroyTags (PHEAP Heap)
BOOLEAN RtlpHeapIsLocked (IN PVOID HeapHandle)

Variables

HEAP_LOCK RtlpProcessHeapsListLock
PHEAP RtlpProcessHeapsListBuffer [RTLP_STATIC_HEAP_LIST_SIZE]
PHEAP RtlpGlobalTagHeap = NULL
WCHAR RtlpPseudoTagNameBuffer [24]


Define Documentation

#define RTLP_STATIC_HEAP_LIST_SIZE   16
 

Definition at line 59 of file heapdll.c.

Referenced by RtlInitializeHeapManager().


Typedef Documentation

typedef struct _RTL_HEAP_USAGE_INTERNAL * PRTL_HEAP_USAGE_INTERNAL
 

Referenced by RtlUsageHeap().

typedef struct _RTL_HEAP_USAGE_INTERNAL RTL_HEAP_USAGE_INTERNAL
 


Function Documentation

SIZE_T NTAPI RtlCompactHeap IN PVOID  HeapHandle,
IN ULONG  Flags
 

Definition at line 2401 of file heapdll.c.

References DEBUG_HEAP, EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::ForceFlags, HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_SEGMENTS, HeapHandle, _HEAP_SEGMENT::LargestUnCommittedRange, _HEAP::LockVariable, NULL, RtlAcquireLockRoutine, RtlDebugCompactHeap(), RtlpCoalesceHeap(), RtlReleaseLockRoutine, _HEAP::Segments, SET_LAST_STATUS, _HEAP_FREE_ENTRY::Size, and TRUE.

Referenced by RtlDebugCompactHeap().

02408 : 02409 02410 This routine compacts the specified heap by coalescing all the free block. 02411 It also determines the size of the largest available free block and 02412 returns its, in bytes, back to the caller. 02413 02414 Arguments: 02415 02416 HeapHandle - Supplies a pointer to the heap being modified 02417 02418 Flags - Supplies a set of flags used to augment those already 02419 enforced by the heap 02420 02421 Return Value: 02422 02423 SIZE_T - Returns the size, in bytes, of the largest free block 02424 available in the heap 02425 02426 --*/ 02427 02428 { 02429 PHEAP Heap = (PHEAP)HeapHandle; 02430 PHEAP_FREE_ENTRY FreeBlock; 02431 PHEAP_SEGMENT Segment; 02432 UCHAR SegmentIndex; 02433 SIZE_T LargestFreeSize; 02434 BOOLEAN LockAcquired = FALSE; 02435 02436 // 02437 // Augment the heap flags 02438 // 02439 02440 Flags |= Heap->ForceFlags; 02441 02442 // 02443 // Check if this is a debug version of heap 02444 // 02445 02446 if (DEBUG_HEAP( Flags )) { 02447 02448 return RtlDebugCompactHeap( HeapHandle, Flags ); 02449 } 02450 02451 try { 02452 02453 // 02454 // Lock the heap 02455 // 02456 02457 if (!(Flags & HEAP_NO_SERIALIZE)) { 02458 02459 RtlAcquireLockRoutine( Heap->LockVariable ); 02460 02461 LockAcquired = TRUE; 02462 } 02463 02464 LargestFreeSize = 0; 02465 02466 try { 02467 02468 // 02469 // Coalesce the heap into its largest free blocks possible 02470 // and get the largest free block in the heap 02471 // 02472 02473 FreeBlock = RtlpCoalesceHeap( (PHEAP)HeapHandle ); 02474 02475 // 02476 // If there is a free block then compute its byte size 02477 // 02478 02479 if (FreeBlock != NULL) { 02480 02481 LargestFreeSize = FreeBlock->Size << HEAP_GRANULARITY_SHIFT; 02482 } 02483 02484 // 02485 // Scan every segment in the heap looking at its largest uncommitted 02486 // range. Remember the largest range if its bigger than anything 02487 // we've found so far 02488 // 02489 02490 for (SegmentIndex=0; SegmentIndex<HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) { 02491 02492 Segment = Heap->Segments[ SegmentIndex ]; 02493 02494 if (Segment && Segment->LargestUnCommittedRange > LargestFreeSize) { 02495 02496 LargestFreeSize = Segment->LargestUnCommittedRange; 02497 } 02498 } 02499 02500 } except( EXCEPTION_EXECUTE_HANDLER ) { 02501 02502 SET_LAST_STATUS( GetExceptionCode() ); 02503 } 02504 02505 } finally { 02506 02507 // 02508 // Unlock the heap 02509 // 02510 02511 if (LockAcquired) { 02512 02513 RtlReleaseLockRoutine( Heap->LockVariable ); 02514 } 02515 } 02516 02517 // 02518 // And return the largest free size to our caller 02519 // 02520 02521 return LargestFreeSize; 02522 }

ULONG RtlCreateTagHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PWSTR TagPrefix  OPTIONAL,
IN PWSTR  TagNames
 

Definition at line 1603 of file heapdll.c.

References DEBUG_HEAP, FALSE, _HEAP::ForceFlags, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, IS_HEAP_TAGGING_ENABLED, L, _HEAP::LockVariable, NULL, RtlAcquireLockRoutine, RtlAllocateHeap, RtlDebugCreateTagHeap(), RtlpAllocateTags(), RtlpGlobalTagHeap, RtlReleaseLockRoutine, _HEAP_TAG_ENTRY::TagIndex, _HEAP_TAG_ENTRY::TagName, and TRUE.

Referenced by CsrClientConnectToServer(), CsrpConnectToServer(), LdrpDefineDllTag(), LdrpInitializeProcess(), main(), and RtlDebugCreateTagHeap().

01612 : 01613 01614 This routine create a tag heap for either the specified heap or 01615 for the global tag heap. 01616 01617 Arguments: 01618 01619 HeapHandle - Optionally supplies a pointer to the heap that we 01620 want modified. If null then the global tag heap is used 01621 01622 Flags - Supplies a list of flags to augment the flags already 01623 enforced by the heap 01624 01625 TagPrefix - Optionally supplies a null terminated wchar string 01626 of a prefix to add to each tag 01627 01628 TagNames - Supplies a list of tag names separated by null and terminated 01629 by a double null. If the first name in the list start with 01630 a "!" then it is interpreted as the heap name. The syntax 01631 for the tag name is 01632 01633 [!<heapname> nul ] {<tagname> nul}* nul 01634 01635 Return Value: 01636 01637 ULONG - returns the index of the last tag create shifted to the high 01638 order word. 01639 01640 --*/ 01641 01642 { 01643 PHEAP Heap = (PHEAP)HeapHandle; 01644 BOOLEAN LockAcquired = FALSE; 01645 ULONG TagIndex; 01646 ULONG NumberOfTags, MaxTagNameLength, TagPrefixLength; 01647 PWSTR s, s1, HeapName; 01648 PHEAP_TAG_ENTRY TagEntry; 01649 ULONG Result; 01650 01651 // 01652 // Check if tagging is disable and so this call is a noop 01653 // 01654 01655 if (!IS_HEAP_TAGGING_ENABLED()) { 01656 01657 return 0; 01658 } 01659 01660 // 01661 // If the processes global tag heap has not been created yet then 01662 // allocate a global tag heap 01663 // 01664 01665 if (RtlpGlobalTagHeap == NULL) { 01666 01667 RtlpGlobalTagHeap = RtlAllocateHeap( RtlProcessHeap( ), HEAP_ZERO_MEMORY, sizeof( HEAP )); 01668 01669 if (RtlpGlobalTagHeap == NULL) { 01670 01671 return 0; 01672 } 01673 } 01674 01675 try { 01676 01677 // 01678 // If the user passed in a heap then we'll use the lock from that 01679 // heap to synchronize our work. Otherwise we're unsynchronized 01680 // 01681 01682 if (Heap != NULL) { 01683 01684 // 01685 // Tagging is not part of the guard page heap package 01686 // 01687 01688 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 0 ); 01689 01690 // 01691 // Check if we should be calling the debug version of the heap package 01692 // 01693 01694 if (DEBUG_HEAP( Flags )) { 01695 01696 Result = RtlDebugCreateTagHeap( HeapHandle, Flags, TagPrefix, TagNames ); 01697 leave; 01698 } 01699 01700 // 01701 // Augment the flags and lock the specified heap 01702 // 01703 01704 Flags |= Heap->ForceFlags; 01705 01706 if (!(Flags & HEAP_NO_SERIALIZE)) { 01707 01708 RtlAcquireLockRoutine( Heap->LockVariable ); 01709 01710 LockAcquired = TRUE; 01711 } 01712 } 01713 01714 // 01715 // We start off with zero tags 01716 // 01717 01718 TagIndex = 0; 01719 NumberOfTags = 0; 01720 01721 // 01722 // With tag names that start with "!" we assume what follows 01723 // is a heap name. 01724 // 01725 01726 if (*TagNames == L'!') { 01727 01728 HeapName = TagNames + 1; 01729 01730 // 01731 // Move up to the following tag name after the heap name 01732 // separated by a null 01733 // 01734 01735 while (*TagNames++) { NOTHING; } 01736 01737 } else { 01738 01739 HeapName = NULL; 01740 } 01741 01742 // 01743 // Gobble up each tag name keeping count of how many we find 01744 // 01745 01746 s = TagNames; 01747 01748 while (*s) { 01749 01750 while (*s++) { NOTHING; } 01751 01752 NumberOfTags += 1; 01753 } 01754 01755 // 01756 // Now we will only continue on if we were supplied tag names 01757 // 01758 01759 if (NumberOfTags > 0) { 01760 01761 // 01762 // Allocate heap entries for the number of tags we need and 01763 // only proceed if this allocation succeeded. The following 01764 // call also makes room for the heap name as tag index 0. Note 01765 // that is heap is null then we assume we're using the global 01766 // tag heap 01767 // 01768 01769 TagEntry = RtlpAllocateTags( Heap, NumberOfTags ); 01770 01771 if (TagEntry != NULL) { 01772 01773 MaxTagNameLength = (sizeof( TagEntry->TagName ) / sizeof( WCHAR )) - 1; 01774 01775 TagIndex = TagEntry->TagIndex; 01776 01777 // 01778 // If the first tag index is zero then we'll make this tag entry 01779 // the heap name. 01780 // 01781 01782 if (TagIndex == 0) { 01783 01784 if (HeapName != NULL ) { 01785 01786 // 01787 // Copy over the heap name and pad it out with nulls up 01788 // to the end of the name buffer 01789 // 01790 01791 wcsncpy( TagEntry->TagName, HeapName, MaxTagNameLength ); 01792 } 01793 01794 // 01795 // Whether we add a heap name or not we'll move on to the 01796 // next tag entry and index 01797 // 01798 01799 TagEntry += 1; 01800 01801 TagIndex = TagEntry->TagIndex; 01802 01803 // 01804 // This isn't the first index for a specified heap, but see if 01805 // it is the first index for the global heap. If so then put 01806 // name of the global tags into the 0 index 01807 // 01808 01809 } else if (TagIndex == HEAP_GLOBAL_TAG) { 01810 01811 wcsncpy( TagEntry->TagName, L"GlobalTags", MaxTagNameLength ); 01812 01813 TagEntry += 1; 01814 01815 TagIndex = TagEntry->TagIndex; 01816 } 01817 01818 // 01819 // Now we've taken case of the 0 index we'll go on to the rest of 01820 // the tags. If there is tag prefix and it is not zero length 01821 // then we'll use this tag prefix provided that is leaves us at 01822 // least 4 characters for the tag name itself. Otherwise we'll 01823 // ignore the tag prefix (by setting the variable to null). 01824 // 01825 01826 if ((ARGUMENT_PRESENT( TagPrefix )) && 01827 (TagPrefixLength = wcslen( TagPrefix ))) { 01828 01829 if (TagPrefixLength >= MaxTagNameLength-4) { 01830 01831 TagPrefix = NULL; 01832 01833 } else { 01834 01835 MaxTagNameLength -= TagPrefixLength; 01836 } 01837 01838 } else { 01839 01840 TagPrefix = NULL; 01841 } 01842 01843 // 01844 // For every tag name (note that this varable has already been 01845 // advanced beyond the heap name) we'll put it in a tag entry 01846 // by copying in the prefix and then appending on the tag itself 01847 // 01848 // s points to the current users supplied tag name 01849 // s1 points to the tag name buffer in the current tag entry 01850 // 01851 01852 s = TagNames; 01853 01854 while (*s) { 01855 01856 s1 = TagEntry->TagName; 01857 01858 // 01859 // Copy in the optional tag prefix and update s1 01860 // 01861 01862 if (ARGUMENT_PRESENT( TagPrefix )) { 01863 01864 wcscpy( s1, TagPrefix ); 01865 01866 s1 += TagPrefixLength; 01867 } 01868 01869 // 01870 // Copy over the remaining tag name padding it with nulls 01871 // up to the end of the name buffer 01872 // 01873 01874 wcsncpy( s1, s, MaxTagNameLength ); 01875 01876 // 01877 // Skip to the next tag name 01878 // 01879 01880 while (*s++) { NOTHING; } 01881 01882 // 01883 // Skip to the next tag entry 01884 // 01885 01886 TagEntry += 1; 01887 } 01888 } 01889 } 01890 01891 Result = TagIndex << HEAP_TAG_SHIFT; 01892 01893 } finally { 01894 01895 // 01896 // Unlock the heap 01897 // 01898 01899 if (LockAcquired) { 01900 01901 RtlReleaseLockRoutine( Heap->LockVariable ); 01902 } 01903 } 01904 01905 // 01906 // And return to our caller. The answer we return is the last tag index 01907 // stored in the high word of a ulong result 01908 // 01909 01910 return Result; 01911 }

SIZE_T RtlDebugCompactHeap IN PVOID  HeapHandle,
IN ULONG  Flags
 

Definition at line 1260 of file heapdbg.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::ForceFlags, HEAP_SKIP_VALIDATION_CHECKS, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, _HEAP::LockVariable, RtlAcquireLockRoutine, RtlCompactHeap(), RtlpCheckHeapSignature(), RtlpDebugPageHeapCompact(), RtlpValidateHeap(), RtlpValidateHeapHeaders(), RtlReleaseLockRoutine, SET_LAST_STATUS, and TRUE.

Referenced by RtlCompactHeap().

01267 : 01268 01269 Arguments: 01270 01271 Return Value: 01272 01273 --*/ 01274 01275 { 01276 PHEAP Heap = (PHEAP)HeapHandle; 01277 BOOLEAN LockAcquired = FALSE; 01278 SIZE_T LargestFreeSize; 01279 01280 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01281 RtlpDebugPageHeapCompact( HeapHandle, Flags )); 01282 01283 LargestFreeSize = 0; 01284 01285 try { 01286 01287 try { 01288 01289 // 01290 // Validate that HeapAddress points to a HEAP structure. 01291 // 01292 01293 if (!RtlpCheckHeapSignature( Heap, "RtlCompactHeap" )) { 01294 01295 LargestFreeSize = 0; 01296 leave; 01297 } 01298 01299 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01300 01301 // 01302 // Lock the heap 01303 // 01304 01305 if (!(Flags & HEAP_NO_SERIALIZE)) { 01306 01307 RtlAcquireLockRoutine( Heap->LockVariable ); 01308 01309 LockAcquired = TRUE; 01310 01311 Flags |= HEAP_NO_SERIALIZE; 01312 } 01313 01314 RtlpValidateHeap( Heap, FALSE ); 01315 01316 LargestFreeSize = RtlCompactHeap( HeapHandle, Flags ); 01317 01318 RtlpValidateHeapHeaders( Heap, TRUE ); 01319 01320 } except( EXCEPTION_EXECUTE_HANDLER ) { 01321 01322 SET_LAST_STATUS( GetExceptionCode() ); 01323 } 01324 01325 } finally { 01326 01327 if (LockAcquired) { 01328 01329 RtlReleaseLockRoutine( Heap->LockVariable ); 01330 } 01331 } 01332 01333 return LargestFreeSize; 01334 }

NTSTATUS RtlDebugCreateTagHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PWSTR TagPrefix  OPTIONAL,
IN PWSTR  TagNames
 

Definition at line 1421 of file heapdbg.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::ForceFlags, HEAP_SKIP_VALIDATION_CHECKS, HeapHandle, _HEAP::LockVariable, RtlAcquireLockRoutine, RtlCreateTagHeap(), RtlpCheckHeapSignature(), RtlpValidateHeap(), RtlpValidateHeapHeaders(), RtlReleaseLockRoutine, SET_LAST_STATUS, and TRUE.

Referenced by RtlCreateTagHeap().

01430 : 01431 01432 Arguments: 01433 01434 Return Value: 01435 01436 --*/ 01437 01438 { 01439 PHEAP Heap = (PHEAP)HeapHandle; 01440 BOOLEAN LockAcquired = FALSE; 01441 ULONG TagIndex; 01442 01443 TagIndex = 0; 01444 01445 try { 01446 01447 try { 01448 01449 // 01450 // Validate that HeapAddress points to a HEAP structure. 01451 // 01452 01453 if (RtlpCheckHeapSignature( Heap, "RtlCreateTagHeap" )) { 01454 01455 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01456 01457 // 01458 // Lock the heap 01459 // 01460 01461 if (!(Flags & HEAP_NO_SERIALIZE)) { 01462 01463 RtlAcquireLockRoutine( Heap->LockVariable ); 01464 01465 LockAcquired = TRUE; 01466 01467 Flags |= HEAP_NO_SERIALIZE; 01468 } 01469 01470 if (RtlpValidateHeap( Heap, FALSE )) { 01471 01472 TagIndex = RtlCreateTagHeap( HeapHandle, Flags, TagPrefix, TagNames ); 01473 } 01474 01475 RtlpValidateHeapHeaders( Heap, TRUE ); 01476 } 01477 01478 } except( EXCEPTION_EXECUTE_HANDLER ) { 01479 01480 SET_LAST_STATUS( GetExceptionCode() ); 01481 } 01482 01483 } finally { 01484 01485 if (LockAcquired) { 01486 01487 RtlReleaseLockRoutine( Heap->LockVariable ); 01488 } 01489 } 01490 01491 return TagIndex; 01492 }

BOOLEAN RtlDebugGetUserInfoHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress,
OUT PVOID *UserValue  OPTIONAL,
OUT PULONG UserFlags  OPTIONAL
 

Definition at line 919 of file heapdbg.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::ForceFlags, HEAP_SKIP_VALIDATION_CHECKS, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, _HEAP::LockVariable, RtlAcquireLockRoutine, RtlGetUserInfoHeap(), RtlpCheckHeapSignature(), RtlpDebugPageHeapGetUserInfo(), RtlpValidateHeap(), RtlpValidateHeapEntry(), RtlReleaseLockRoutine, SET_LAST_STATUS, and TRUE.

Referenced by RtlGetUserInfoHeap().

00929 : 00930 00931 Arguments: 00932 00933 Return Value: 00934 00935 --*/ 00936 00937 { 00938 PHEAP Heap = (PHEAP)HeapHandle; 00939 PHEAP_ENTRY BusyBlock; 00940 BOOLEAN Result = FALSE; 00941 BOOLEAN LockAcquired = FALSE; 00942 00943 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 00944 RtlpDebugPageHeapGetUserInfo( HeapHandle, Flags, BaseAddress, UserValue, UserFlags )); 00945 00946 try { 00947 00948 try { 00949 00950 // 00951 // Validate that HeapAddress points to a HEAP structure. 00952 // 00953 00954 if (!RtlpCheckHeapSignature( Heap, "RtlGetUserInfoHeap" )) { 00955 00956 Result = FALSE; 00957 leave; 00958 } 00959 00960 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 00961 00962 // 00963 // Lock the heap 00964 // 00965 00966 if (!(Flags & HEAP_NO_SERIALIZE)) { 00967 00968 RtlAcquireLockRoutine( Heap->LockVariable ); 00969 00970 LockAcquired = TRUE; 00971 00972 Flags |= HEAP_NO_SERIALIZE; 00973 } 00974 00975 RtlpValidateHeap( Heap, FALSE ); 00976 00977 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 00978 00979 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlGetUserInfoHeap" )) { 00980 00981 Result = RtlGetUserInfoHeap( HeapHandle, Flags, BaseAddress, UserValue, UserFlags ); 00982 } 00983 00984 } except( EXCEPTION_EXECUTE_HANDLER ) { 00985 00986 SET_LAST_STATUS( GetExceptionCode() ); 00987 } 00988 00989 } finally { 00990 00991 if (LockAcquired) { 00992 00993 RtlReleaseLockRoutine( Heap->LockVariable ); 00994 } 00995 } 00996 00997 return Result; 00998 }

PWSTR RtlDebugQueryTagHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN USHORT  TagIndex,
IN BOOLEAN  ResetCounters,
OUT PRTL_HEAP_TAG_INFO TagInfo  OPTIONAL
 

Definition at line 1498 of file heapdbg.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::ForceFlags, HEAP_SKIP_VALIDATION_CHECKS, HeapHandle, _HEAP::LockVariable, NULL, RtlAcquireLockRoutine, RtlpCheckHeapSignature(), RtlpValidateHeap(), RtlQueryTagHeap(), RtlReleaseLockRoutine, SET_LAST_STATUS, and TRUE.

Referenced by RtlQueryTagHeap().

01508 : 01509 01510 Arguments: 01511 01512 Return Value: 01513 01514 --*/ 01515 01516 { 01517 PHEAP Heap = (PHEAP)HeapHandle; 01518 BOOLEAN LockAcquired = FALSE; 01519 PWSTR Result; 01520 01521 Result = NULL; 01522 01523 try { 01524 01525 try { 01526 01527 // 01528 // Validate that HeapAddress points to a HEAP structure. 01529 // 01530 01531 if (RtlpCheckHeapSignature( Heap, "RtlQueryTagHeap" )) { 01532 01533 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01534 01535 // 01536 // Lock the heap 01537 // 01538 01539 if (!(Flags & HEAP_NO_SERIALIZE)) { 01540 01541 RtlAcquireLockRoutine( Heap->LockVariable ); 01542 01543 LockAcquired = TRUE; 01544 01545 Flags |= HEAP_NO_SERIALIZE; 01546 } 01547 01548 if (RtlpValidateHeap( Heap, FALSE )) { 01549 01550 Result = RtlQueryTagHeap( HeapHandle, Flags, TagIndex, ResetCounters, TagInfo ); 01551 } 01552 } 01553 01554 } except( EXCEPTION_EXECUTE_HANDLER ) { 01555 01556 SET_LAST_STATUS( GetExceptionCode() ); 01557 } 01558 01559 } finally { 01560 01561 if (LockAcquired) { 01562 01563 RtlReleaseLockRoutine( Heap->LockVariable ); 01564 } 01565 } 01566 01567 return Result; 01568 }

PVOID RtlDebugReAllocateHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress,
IN SIZE_T  Size
 

Definition at line 603 of file heapdbg.c.

References _HEAP::AlignMask, _HEAP::AlignRound, _HEAP_ENTRY_EXTRA::AllocatorBackTraceIndex, EXCEPTION_CONTINUE_SEARCH, EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::Flags, _HEAP_ENTRY::Flags, _HEAP::ForceFlags, HEAP_CAPTURE_STACK_BACKTRACES, HEAP_ENTRY_EXTRA_PRESENT, HEAP_SKIP_VALIDATION_CHECKS, _HEAP_STOP_ON_TAG::HeapAndTagIndex, HeapDebugBreak, HeapDebugPrint, HeapHandle, _HEAP_STOP_ON_TAG::HeapIndex, IF_DEBUG_PAGE_HEAP_THEN_RETURN, IS_HEAP_TAGGING_ENABLED, _HEAP::LockVariable, _HEAP::MaximumAllocationSize, NULL, _HEAP::ProcessHeapsListIndex, _HEAP_STOP_ON_VALUES::ReAllocAddress, _HEAP_STOP_ON_VALUES::ReAllocTag, RtlAcquireLockRoutine, RtlpCheckHeapSignature(), RtlpDebugPageHeapReAllocate(), RtlpGetExtraStuffPointer(), RtlpGetTagName(), RtlpHeapStopOn, RtlpValidateHeap(), RtlpValidateHeapEntry(), RtlpValidateHeapHeaders(), RtlReAllocateHeap(), RtlReleaseLockRoutine, SET_LAST_STATUS, Size, _HEAP_ENTRY::SmallTagIndex, _HEAP_STOP_ON_TAG::TagIndex, _HEAP_ENTRY_EXTRA::TagIndex, TRUE, and USHORT.

Referenced by RtlReAllocateHeap().

00612 : 00613 00614 Arguments: 00615 00616 Return Value: 00617 00618 --*/ 00619 00620 { 00621 PHEAP Heap = (PHEAP)HeapHandle; 00622 SIZE_T AllocationSize; 00623 PHEAP_ENTRY BusyBlock; 00624 PHEAP_ENTRY_EXTRA ExtraStuff; 00625 BOOLEAN LockAcquired = FALSE; 00626 PVOID ReturnValue = NULL; 00627 USHORT TagIndex; 00628 00629 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 00630 RtlpDebugPageHeapReAllocate( HeapHandle, Flags, BaseAddress, Size )); 00631 00632 try { 00633 00634 try { 00635 00636 // 00637 // Validate that HeapAddress points to a HEAP structure. 00638 // 00639 00640 if (!RtlpCheckHeapSignature( Heap, "RtlReAllocateHeap" )) { 00641 00642 ReturnValue = NULL; 00643 leave; 00644 } 00645 00646 Flags |= Heap->ForceFlags | HEAP_SETTABLE_USER_VALUE | HEAP_SKIP_VALIDATION_CHECKS; 00647 00648 // 00649 // Verify that the size did not wrap or exceed the limit for this heap. 00650 // 00651 00652 AllocationSize = (((Size ? Size : 1) + Heap->AlignRound) & Heap->AlignMask) + 00653 sizeof( HEAP_ENTRY_EXTRA ); 00654 00655 if (AllocationSize < Size || AllocationSize > Heap->MaximumAllocationSize) { 00656 00657 HeapDebugPrint(( "Invalid allocation size - %lx (exceeded %x)\n", 00658 Size, 00659 Heap->MaximumAllocationSize )); 00660 00661 HeapDebugBreak( NULL ); 00662 00663 ReturnValue = NULL; 00664 leave; 00665 } 00666 00667 // 00668 // Lock the heap 00669 // 00670 00671 if (!(Flags & HEAP_NO_SERIALIZE)) { 00672 00673 RtlAcquireLockRoutine( Heap->LockVariable ); 00674 00675 LockAcquired = TRUE; 00676 00677 Flags |= HEAP_NO_SERIALIZE; 00678 } 00679 00680 RtlpValidateHeap( Heap, FALSE ); 00681 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 00682 00683 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlReAllocateHeap" )) { 00684 00685 if ((ULONG_PTR)BaseAddress == RtlpHeapStopOn.ReAllocAddress) { 00686 00687 HeapDebugPrint(( "About to reallocate block at %lx to 0x%x bytes\n", 00688 RtlpHeapStopOn.ReAllocAddress, 00689 Size )); 00690 00691 HeapDebugBreak( NULL ); 00692 00693 } else if (IS_HEAP_TAGGING_ENABLED() && RtlpHeapStopOn.ReAllocTag.HeapAndTagIndex != 0) { 00694 00695 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 00696 00697 ExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 00698 TagIndex = ExtraStuff->TagIndex; 00699 00700 } else { 00701 00702 TagIndex = BusyBlock->SmallTagIndex; 00703 } 00704 00705 if ((TagIndex != 0) && 00706 (TagIndex == RtlpHeapStopOn.ReAllocTag.TagIndex) && 00707 (Heap->ProcessHeapsListIndex == RtlpHeapStopOn.ReAllocTag.HeapIndex)) { 00708 00709 HeapDebugPrint(( "About to rellocate block at %lx to 0x%x bytes with tag %ws\n", 00710 BaseAddress, 00711 Size, 00712 RtlpGetTagName( Heap, TagIndex ))); 00713 00714 HeapDebugBreak( NULL ); 00715 } 00716 } 00717 00718 ReturnValue = RtlReAllocateHeap( HeapHandle, Flags, BaseAddress, Size ); 00719 00720 if (ReturnValue != NULL) { 00721 00722 BusyBlock = (PHEAP_ENTRY)ReturnValue - 1; 00723 00724 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 00725 00726 ExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 00727 00728 #if i386 00729 00730 if (Heap->Flags & HEAP_CAPTURE_STACK_BACKTRACES) { 00731 00732 ExtraStuff->AllocatorBackTraceIndex = (USHORT)RtlLogStackBackTrace(); 00733 00734 } else { 00735 00736 ExtraStuff->AllocatorBackTraceIndex = 0; 00737 } 00738 00739 #endif // i386 00740 00741 TagIndex = ExtraStuff->TagIndex; 00742 00743 } else { 00744 00745 TagIndex = BusyBlock->SmallTagIndex; 00746 } 00747 } 00748 00749 RtlpValidateHeapHeaders( Heap, TRUE ); 00750 RtlpValidateHeap( Heap, FALSE ); 00751 } 00752 00753 if (ReturnValue != NULL) { 00754 00755 if ((ULONG_PTR)ReturnValue == RtlpHeapStopOn.ReAllocAddress) { 00756 00757 HeapDebugPrint(( "Just reallocated block at %lx to 0x%x bytes\n", 00758 RtlpHeapStopOn.ReAllocAddress, 00759 Size )); 00760 00761 HeapDebugBreak( NULL ); 00762 00763 } else if ((IS_HEAP_TAGGING_ENABLED()) && 00764 (TagIndex == RtlpHeapStopOn.ReAllocTag.TagIndex) && 00765 (Heap->ProcessHeapsListIndex == RtlpHeapStopOn.ReAllocTag.HeapIndex)) { 00766 00767 HeapDebugPrint(( "Just reallocated block at %lx to 0x%x bytes with tag %ws\n", 00768 ReturnValue, 00769 Size, 00770 RtlpGetTagName( Heap, TagIndex ))); 00771 00772 HeapDebugBreak( NULL ); 00773 } 00774 } 00775 00776 } except( GetExceptionCode() == STATUS_NO_MEMORY ? EXCEPTION_CONTINUE_SEARCH : 00777 EXCEPTION_EXECUTE_HANDLER ) { 00778 00779 SET_LAST_STATUS( GetExceptionCode() ); 00780 00781 ReturnValue = NULL; 00782 } 00783 00784 } finally { 00785 00786 if (LockAcquired) { 00787 00788 RtlReleaseLockRoutine( Heap->LockVariable ); 00789 } 00790 } 00791 00792 return ReturnValue; 00793 }

BOOLEAN RtlDebugSetUserFlagsHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress,
IN ULONG  UserFlagsReset,
IN ULONG  UserFlagsSet
 

Definition at line 1086 of file heapdbg.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::ForceFlags, HEAP_SKIP_VALIDATION_CHECKS, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, _HEAP::LockVariable, RtlAcquireLockRoutine, RtlpCheckHeapSignature(), RtlpDebugPageHeapSetUserFlags(), RtlpValidateHeap(), RtlpValidateHeapEntry(), RtlReleaseLockRoutine, RtlSetUserFlagsHeap(), SET_LAST_STATUS, and TRUE.

Referenced by RtlSetUserFlagsHeap().

01096 : 01097 01098 Arguments: 01099 01100 Return Value: 01101 01102 --*/ 01103 01104 { 01105 PHEAP Heap = (PHEAP)HeapHandle; 01106 PHEAP_ENTRY BusyBlock; 01107 BOOLEAN Result = FALSE; 01108 BOOLEAN LockAcquired = FALSE; 01109 01110 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01111 RtlpDebugPageHeapSetUserFlags( HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet )); 01112 01113 if ((UserFlagsReset & ~HEAP_SETTABLE_USER_FLAGS) || 01114 (UserFlagsSet & ~HEAP_SETTABLE_USER_FLAGS)) { 01115 01116 return FALSE; 01117 } 01118 01119 try { 01120 01121 try { 01122 01123 // 01124 // Validate that HeapAddress points to a HEAP structure. 01125 // 01126 01127 if (!RtlpCheckHeapSignature( Heap, "RtlSetUserFlagsHeap" )) { 01128 01129 Result = FALSE; 01130 leave; 01131 } 01132 01133 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01134 01135 // 01136 // Lock the heap 01137 // 01138 01139 if (!(Flags & HEAP_NO_SERIALIZE)) { 01140 01141 RtlAcquireLockRoutine( Heap->LockVariable ); 01142 01143 LockAcquired = TRUE; 01144 01145 Flags |= HEAP_NO_SERIALIZE; 01146 } 01147 01148 RtlpValidateHeap( Heap, FALSE ); 01149 01150 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 01151 01152 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlSetUserFlagsHeap" )) { 01153 01154 Result = RtlSetUserFlagsHeap( HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet ); 01155 01156 RtlpValidateHeap( Heap, FALSE ); 01157 } 01158 01159 } except( EXCEPTION_EXECUTE_HANDLER ) { 01160 01161 SET_LAST_STATUS( GetExceptionCode() ); 01162 } 01163 01164 } finally { 01165 01166 if (LockAcquired) { 01167 01168 RtlReleaseLockRoutine( Heap->LockVariable ); 01169 } 01170 } 01171 01172 return Result; 01173 }

BOOLEAN RtlDebugSetUserValueHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress,
IN PVOID  UserValue
 

Definition at line 1002 of file heapdbg.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::ForceFlags, HEAP_SKIP_VALIDATION_CHECKS, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, _HEAP::LockVariable, RtlAcquireLockRoutine, RtlpCheckHeapSignature(), RtlpDebugPageHeapSetUserValue(), RtlpValidateHeap(), RtlpValidateHeapEntry(), RtlReleaseLockRoutine, RtlSetUserValueHeap(), SET_LAST_STATUS, and TRUE.

Referenced by RtlSetUserValueHeap().

01011 : 01012 01013 Arguments: 01014 01015 Return Value: 01016 01017 --*/ 01018 01019 { 01020 PHEAP Heap = (PHEAP)HeapHandle; 01021 PHEAP_ENTRY BusyBlock; 01022 BOOLEAN Result = FALSE; 01023 BOOLEAN LockAcquired = FALSE; 01024 01025 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01026 RtlpDebugPageHeapSetUserValue( HeapHandle, Flags, BaseAddress, UserValue )); 01027 01028 try { 01029 01030 try { 01031 01032 // 01033 // Validate that HeapAddress points to a HEAP structure. 01034 // 01035 01036 if (!RtlpCheckHeapSignature( Heap, "RtlSetUserValueHeap" )) { 01037 01038 Result = FALSE; 01039 leave; 01040 } 01041 01042 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01043 01044 // 01045 // Lock the heap 01046 // 01047 01048 if (!(Flags & HEAP_NO_SERIALIZE)) { 01049 01050 RtlAcquireLockRoutine( Heap->LockVariable ); 01051 01052 LockAcquired = TRUE; 01053 01054 Flags |= HEAP_NO_SERIALIZE; 01055 } 01056 01057 RtlpValidateHeap( Heap, FALSE ); 01058 01059 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 01060 01061 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlSetUserValueHeap" )) { 01062 01063 Result = RtlSetUserValueHeap( HeapHandle, Flags, BaseAddress, UserValue ); 01064 01065 RtlpValidateHeap( Heap, FALSE ); 01066 } 01067 01068 } except( EXCEPTION_EXECUTE_HANDLER ) { 01069 01070 SET_LAST_STATUS( GetExceptionCode() ); 01071 } 01072 01073 } finally { 01074 01075 if (LockAcquired) { 01076 01077 RtlReleaseLockRoutine( Heap->LockVariable ); 01078 } 01079 } 01080 01081 return Result; 01082 }

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

Definition at line 1572 of file heapdbg.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::ForceFlags, HEAP_SKIP_VALIDATION_CHECKS, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, _HEAP::LockVariable, NTSTATUS(), RtlAcquireLockRoutine, RtlpCheckHeapSignature(), RtlpDebugPageHeapUsage(), RtlpValidateHeap(), RtlReleaseLockRoutine, RtlUsageHeap(), Status, TRUE, and Usage().

Referenced by RtlUsageHeap().

01580 : 01581 01582 Arguments: 01583 01584 Return Value: 01585 01586 --*/ 01587 01588 { 01589 PHEAP Heap = (PHEAP)HeapHandle; 01590 NTSTATUS Status; 01591 BOOLEAN LockAcquired = FALSE; 01592 01593 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01594 RtlpDebugPageHeapUsage( HeapHandle, Flags, Usage )); 01595 01596 Status = STATUS_SUCCESS; 01597 01598 try { 01599 01600 try { 01601 01602 // 01603 // Validate that HeapAddress points to a HEAP structure. 01604 // 01605 01606 if (!RtlpCheckHeapSignature( Heap, "RtlUsageHeap" )) { 01607 01608 Status = STATUS_INVALID_PARAMETER; 01609 leave; 01610 } 01611 01612 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01613 01614 // 01615 // Lock the heap 01616 // 01617 01618 if (!(Flags & HEAP_NO_SERIALIZE)) { 01619 01620 RtlAcquireLockRoutine( Heap->LockVariable ); 01621 01622 LockAcquired = TRUE; 01623 01624 Flags |= HEAP_NO_SERIALIZE; 01625 } 01626 01627 if (!RtlpValidateHeap( Heap, FALSE )) { 01628 01629 Status = STATUS_INVALID_PARAMETER; 01630 01631 } else { 01632 01633 Status = RtlUsageHeap( HeapHandle, Flags, Usage ); 01634 } 01635 01636 } except( EXCEPTION_EXECUTE_HANDLER ) { 01637 01638 Status = GetExceptionCode(); 01639 } 01640 01641 } finally { 01642 01643 if (LockAcquired) { 01644 01645 RtlReleaseLockRoutine( Heap->LockVariable ); 01646 } 01647 } 01648 01649 return Status; 01650 }

BOOLEAN RtlDebugWalkHeap IN PVOID  HeapHandle,
IN OUT PRTL_HEAP_WALK_ENTRY  Entry
 

Definition at line 1654 of file heapdbg.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, HeapHandle, RtlpCheckHeapSignature(), RtlpValidateHeap(), and SET_LAST_STATUS.

Referenced by RtlWalkHeap().

01661 : 01662 01663 Arguments: 01664 01665 Return Value: 01666 01667 --*/ 01668 01669 { 01670 PHEAP Heap = (PHEAP)HeapHandle; 01671 BOOLEAN Result; 01672 01673 // 01674 // Assumed the caller has serialized via RtlLockHeap or their own locking mechanism. 01675 // 01676 01677 Result = FALSE; 01678 01679 try { 01680 01681 if (RtlpCheckHeapSignature( Heap, "RtlWalkHeap" )) { 01682 01683 Result = RtlpValidateHeap( Heap, FALSE ); 01684 } 01685 01686 } except( EXCEPTION_EXECUTE_HANDLER ) { 01687 01688 SET_LAST_STATUS( GetExceptionCode() ); 01689 } 01690 01691 return Result; 01692 }

NTSTATUS RtlEnumProcessHeaps PRTL_ENUM_HEAPS_ROUTINE  EnumRoutine,
PVOID  Parameter
 

Definition at line 2896 of file heapdll.c.

References _HEAP_LOCK::Lock, NT_SUCCESS, NTSTATUS(), RtlAcquireLockRoutine, RtlpProcessHeapsListLock, RtlReleaseLockRoutine, and Status.

Referenced by RtlQueryProcessHeapInformation().

02903 : 02904 02905 This routine cycles through all the heaps in a process and 02906 invokes the specified call back routine for that heap 02907 02908 Arguments: 02909 02910 EnumRoutine - Supplies the callback to invoke for each heap 02911 in the process 02912 02913 Parameter - Provides an additional parameter to pass to the 02914 callback routine 02915 02916 Return Value: 02917 02918 NTSTATUS - returns success or the first error status returned 02919 by the callback routine 02920 02921 --*/ 02922 02923 { 02924 PPEB Peb = NtCurrentPeb(); 02925 NTSTATUS Status; 02926 ULONG i; 02927 02928 Status = STATUS_SUCCESS; 02929 02930 // 02931 // Lock the heap 02932 // 02933 02934 RtlAcquireLockRoutine( &RtlpProcessHeapsListLock.Lock ); 02935 02936 try { 02937 02938 // 02939 // For each heap in the process invoke the callback routine 02940 // and if the callback returns anything other than success 02941 // then break out and return immediately to our caller 02942 // 02943 02944 for (i=0; i<Peb->NumberOfHeaps; i++) { 02945 02946 Status = (*EnumRoutine)( (PHEAP)(Peb->ProcessHeaps[ i ]), Parameter ); 02947 02948 if (!NT_SUCCESS( Status )) { 02949 02950 break; 02951 } 02952 } 02953 02954 } finally { 02955 02956 // 02957 // Unlock the heap 02958 // 02959 02960 RtlReleaseLockRoutine( &RtlpProcessHeapsListLock.Lock ); 02961 } 02962 02963 // 02964 // And return to our caller 02965 // 02966 02967 return Status; 02968 }

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

Definition at line 2132 of file heapdll.c.

References FALSE, HEAP_MAXIMUM_SEGMENTS, HEAP_SEGMENT_USER_ALLOCATED, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, _HEAP_SEGMENT::LastValidEntry, _HEAP::LockVariable, NT_SUCCESS, NtQueryVirtualMemory(), NTSTATUS(), NULL, PAGE_SIZE, RtlAcquireLockRoutine, RtlpDebugPageHeapExtend(), RtlpInitializeHeapSegment(), RtlReleaseLockRoutine, _HEAP::Segments, Size, Status, and TRUE.

02141 : 02142 02143 This routine grows the specified heap by adding a new segment to its 02144 storage. The memory for the segment is supplied by the caller. 02145 02146 Arguments: 02147 02148 HeapHandle - Supplies a pointer to the heap being modified 02149 02150 Flags - Supplies a set of flags used to augment those already 02151 enforced by the heap 02152 02153 Base - Supplies the starting address for the new segment being added 02154 to the input heap 02155 02156 Size - Supplies the size, in bytes, of the new segment. Note that this 02157 routine will actually use more memory than specified by this 02158 variable. It will use whatever is committed and reserved provided 02159 the amount is greater than or equal to "Size" 02160 02161 Return Value: 02162 02163 NTSTATUS - An appropriate status value 02164 02165 --*/ 02166 02167 { 02168 PHEAP Heap = (PHEAP)HeapHandle; 02169 NTSTATUS Status; 02170 PHEAP_SEGMENT Segment; 02171 BOOLEAN LockAcquired = FALSE; 02172 UCHAR SegmentIndex, EmptySegmentIndex; 02173 SIZE_T CommitSize; 02174 SIZE_T ReserveSize; 02175 ULONG SegmentFlags; 02176 PVOID CommittedBase; 02177 PVOID UnCommittedBase; 02178 MEMORY_BASIC_INFORMATION MemoryInformation; 02179 02180 // 02181 // Check if the guard page version of heap can do the work 02182 // 02183 02184 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 02185 RtlpDebugPageHeapExtend( HeapHandle, Flags, Base, Size )); 02186 02187 // 02188 // See what Mm thinks about the base address we were passed in. 02189 // The address must not be free. 02190 // 02191 02192 Status = NtQueryVirtualMemory( NtCurrentProcess(), 02193 Base, 02194 MemoryBasicInformation, 02195 &MemoryInformation, 02196 sizeof( MemoryInformation ), 02197 NULL ); 02198 02199 if (!NT_SUCCESS( Status )) { 02200 02201 return Status; 02202 } 02203 02204 if (MemoryInformation.State == MEM_FREE) { 02205 02206 return STATUS_INVALID_PARAMETER; 02207 } 02208 02209 // 02210 // If what we were passed in as a base address is not on a page boundary then 02211 // adjust the information supplied by MM to the page boundary right after 02212 // the input base address 02213 // 02214 02215 if (MemoryInformation.BaseAddress != Base) { 02216 02217 MemoryInformation.BaseAddress = (PCHAR)MemoryInformation.BaseAddress + PAGE_SIZE; 02218 MemoryInformation.RegionSize -= PAGE_SIZE; 02219 } 02220 02221 try { 02222 02223 // 02224 // Lock the heap 02225 // 02226 02227 if (!(Flags & HEAP_NO_SERIALIZE)) { 02228 02229 RtlAcquireLockRoutine( Heap->LockVariable ); 02230 02231 LockAcquired = TRUE; 02232 } 02233 02234 // 02235 // Scan the heap's segment list for a free segment. And make sure the address 02236 // of all the segment does not contain the input base address 02237 // 02238 02239 Status = STATUS_INSUFFICIENT_RESOURCES; 02240 02241 EmptySegmentIndex = HEAP_MAXIMUM_SEGMENTS; 02242 02243 for (SegmentIndex=0; SegmentIndex<HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) { 02244 02245 Segment = Heap->Segments[ SegmentIndex ]; 02246 02247 if (Segment) { 02248 02249 if (((ULONG_PTR)Base >= (ULONG_PTR)Segment) && 02250 ((ULONG_PTR)Base < (ULONG_PTR)(Segment->LastValidEntry))) { 02251 02252 Status = STATUS_INVALID_PARAMETER; 02253 02254 break; 02255 } 02256 02257 } else if ((Segment == NULL) && 02258 (EmptySegmentIndex == HEAP_MAXIMUM_SEGMENTS)) { 02259 02260 EmptySegmentIndex = SegmentIndex; 02261 02262 Status = STATUS_SUCCESS; 02263 } 02264 } 02265 02266 // 02267 // At this point if status is success then the empty segment index 02268 // is available for us to use and base address doesn't overlap an 02269 // existing segment. 02270 // 02271 02272 if (NT_SUCCESS( Status )) { 02273 02274 // 02275 // Indicate that this segment is user supplied 02276 // 02277 02278 SegmentFlags = HEAP_SEGMENT_USER_ALLOCATED; 02279 02280 CommittedBase = MemoryInformation.BaseAddress; 02281 02282 // 02283 // If the start of the memory supplied by the use is already 02284 // committed then check the state of the following 02285 // uncommitted piece of memory to see if it is reserved 02286 // 02287 02288 if (MemoryInformation.State == MEM_COMMIT) { 02289 02290 CommitSize = MemoryInformation.RegionSize; 02291 02292 UnCommittedBase = (PCHAR)CommittedBase + CommitSize; 02293 02294 Status = NtQueryVirtualMemory( NtCurrentProcess(), 02295 UnCommittedBase, 02296 MemoryBasicInformation, 02297 &MemoryInformation, 02298 sizeof( MemoryInformation ), 02299 NULL ); 02300 02301 ReserveSize = CommitSize; 02302 02303 if ((NT_SUCCESS( Status )) && 02304 (MemoryInformation.State == MEM_RESERVE)) { 02305 02306 ReserveSize += MemoryInformation.RegionSize; 02307 } 02308 02309 } else { 02310 02311 // 02312 // Otherwise the user hasn't committed anything in the 02313 // the address they gave us and we know it is not free 02314 // so it must be reserved. 02315 // 02316 02317 UnCommittedBase = CommittedBase; 02318 02319 ReserveSize = MemoryInformation.RegionSize; 02320 } 02321 02322 // 02323 // Now if the reserved size is smaller than a page size or 02324 // the user specified size is greater than the reserved size 02325 // then the buffer we're given is too small to be a segment 02326 // of heap 02327 // 02328 02329 if ((ReserveSize < PAGE_SIZE) || 02330 (Size > ReserveSize)) { 02331 02332 Status = STATUS_BUFFER_TOO_SMALL; 02333 02334 } else { 02335 02336 // 02337 // Otherwise the size is okay, now check if we need 02338 // to do the commit of the base. If so we'll commit 02339 // one page 02340 02341 if (UnCommittedBase == CommittedBase) { 02342 02343 CommitSize = PAGE_SIZE; 02344 02345 Status = ZwAllocateVirtualMemory( NtCurrentProcess(), 02346 (PVOID *)&Segment, 02347 0, 02348 &CommitSize, 02349 MEM_COMMIT, 02350 PAGE_READWRITE ); 02351 } 02352 } 02353 02354 // 02355 // At this point the if status is good then memory is all set up 02356 // with at least one page of committed memory to start with. So 02357 // initialize the heap segment and we're done. 02358 // 02359 02360 if (NT_SUCCESS( Status )) { 02361 02362 if (RtlpInitializeHeapSegment( Heap, 02363 Segment, 02364 EmptySegmentIndex, 02365 0, 02366 Segment, 02367 (PCHAR)Segment + CommitSize, 02368 (PCHAR)Segment + ReserveSize )) { 02369 02370 Status = STATUS_NO_MEMORY; 02371 } 02372 } 02373 } 02374 02375 } finally { 02376 02377 // 02378 // Unlock the heap 02379 // 02380 02381 if (LockAcquired) { 02382 02383 RtlReleaseLockRoutine( Heap->LockVariable ); 02384 } 02385 } 02386 02387 // 02388 // And return to our caller 02389 // 02390 02391 return Status; 02392 }

ULONG RtlGetProcessHeaps ULONG  NumberOfHeapsToReturn,
PVOID *  ProcessHeaps
 

Definition at line 2803 of file heapdll.c.

References _HEAP_LOCK::Lock, RtlAcquireLockRoutine, RtlpDebugPageHeap, RtlpDebugPageHeapGetProcessHeaps(), RtlpProcessHeapsListLock, and RtlReleaseLockRoutine.

Referenced by RtlValidateProcessHeaps().

02810 : 02811 02812 This routine determines how many individual heaps there are in the 02813 current process and fills an array with pointers to each heap. 02814 02815 Arguments: 02816 02817 NumberOfHeapsToReturn - Indicates how many heaps the caller 02818 is willing to accept in the second parameter 02819 02820 ProcessHeaps - Supplies a pointer to an array of heap pointer 02821 to be filled in by this routine. The maximum size of this 02822 array is specified by the first parameter 02823 02824 Return Value: 02825 02826 ULONG - Returns the smaller of the actual number of heaps in the 02827 the process or the size of the output buffer 02828 02829 --*/ 02830 02831 { 02832 PPEB Peb = NtCurrentPeb(); 02833 ULONG NumberOfHeapsToCopy; 02834 ULONG TotalHeaps; 02835 02836 RtlAcquireLockRoutine( &RtlpProcessHeapsListLock.Lock ); 02837 02838 try { 02839 02840 // 02841 // Return no more than the number of heaps currently in use 02842 // 02843 02844 TotalHeaps = Peb->NumberOfHeaps; 02845 02846 if (TotalHeaps > NumberOfHeapsToReturn) { 02847 02848 NumberOfHeapsToCopy = NumberOfHeapsToReturn; 02849 02850 } else { 02851 02852 NumberOfHeapsToCopy = TotalHeaps; 02853 02854 } 02855 02856 // 02857 // Return the heap pointers to the caller 02858 // 02859 02860 RtlMoveMemory( ProcessHeaps, 02861 Peb->ProcessHeaps, 02862 NumberOfHeapsToCopy * sizeof( *ProcessHeaps )); 02863 02864 ProcessHeaps += NumberOfHeapsToCopy; 02865 NumberOfHeapsToReturn -= NumberOfHeapsToCopy; 02866 02867 } finally { 02868 02869 RtlReleaseLockRoutine( &RtlpProcessHeapsListLock.Lock ); 02870 } 02871 02872 #ifdef DEBUG_PAGE_HEAP 02873 02874 // 02875 // If we have debugging page heaps, go return what we can from them 02876 // 02877 02878 if ( RtlpDebugPageHeap ) { 02879 02880 TotalHeaps += 02881 RtlpDebugPageHeapGetProcessHeaps( NumberOfHeapsToReturn, ProcessHeaps ); 02882 02883 } 02884 02885 #endif 02886 02887 return TotalHeaps; 02888 }

BOOLEAN RtlGetUserInfoHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress,
OUT PVOID *UserValue  OPTIONAL,
OUT PULONG UserFlags  OPTIONAL
 

Definition at line 1192 of file heapdll.c.

References DEBUG_HEAP, EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP_ENTRY::Flags, _HEAP::ForceFlags, HEAP_ENTRY_BUSY, HEAP_ENTRY_EXTRA_PRESENT, HEAP_ENTRY_SETTABLE_FLAGS, HeapHandle, _HEAP::LockVariable, RtlAcquireLockRoutine, RtlDebugGetUserInfoHeap(), RtlpGetExtraStuffPointer(), RtlReleaseLockRoutine, SET_LAST_STATUS, _HEAP_ENTRY_EXTRA::Settable, and TRUE.

Referenced by RtlDebugGetUserInfoHeap(), and RtlpDphNormalHeapGetUserInfo().

01202 : 01203 01204 This routine returns to the user the set of user flags 01205 and user values for the specified heap entry. The user value 01206 is set via a set call and the user flags is part of the 01207 user settable flags used when communicating with the heap package 01208 and can also be set via a set call 01209 01210 Arguments: 01211 01212 HeapHandle - Supplies a pointer to the heap being queried 01213 01214 Flags - Supplies a set of flags to agument those already in the heap 01215 01216 BaseAddress - Supplies a pointer to the users heap entry being 01217 queried 01218 01219 UserValue - Optionally supplies a pointer to recieve the heap entry 01220 value 01221 01222 UserFlasg - Optionally supplies a pointer to recieve the heap flags 01223 01224 Return Value: 01225 01226 BOOLEAN - TRUE if the query is successful and FALSE otherwise 01227 01228 --*/ 01229 01230 { 01231 PHEAP Heap = (PHEAP)HeapHandle; 01232 PHEAP_ENTRY BusyBlock; 01233 PHEAP_ENTRY_EXTRA ExtraStuff; 01234 BOOLEAN LockAcquired = FALSE; 01235 BOOLEAN Result; 01236 01237 // 01238 // Build up a set of real flags to use in this operation 01239 // 01240 01241 Flags |= Heap->ForceFlags; 01242 01243 // 01244 // Check if we should be going the debug route 01245 // 01246 01247 if (DEBUG_HEAP( Flags )) { 01248 01249 return RtlDebugGetUserInfoHeap( HeapHandle, Flags, BaseAddress, UserValue, UserFlags ); 01250 } 01251 01252 Result = FALSE; 01253 01254 try { 01255 01256 try { 01257 01258 // 01259 // Lock the heap 01260 // 01261 01262 if (!(Flags & HEAP_NO_SERIALIZE)) { 01263 01264 RtlAcquireLockRoutine( Heap->LockVariable ); 01265 01266 LockAcquired = TRUE; 01267 } 01268 01269 // 01270 // Backup the pointer to the heap entry 01271 // 01272 01273 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 01274 01275 // 01276 // If the entry is not in use then it is an error 01277 // 01278 01279 if (!(BusyBlock->Flags & HEAP_ENTRY_BUSY)) { 01280 01281 SET_LAST_STATUS( STATUS_INVALID_PARAMETER ); 01282 01283 } else { 01284 01285 // 01286 // The heap entry is in use so now check if there is 01287 // any extra information present 01288 // 01289 01290 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 01291 01292 // 01293 // Get a pointer to the extra information and if the 01294 // user asked for user values then that field from the 01295 // extra stuff 01296 // 01297 01298 ExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 01299 01300 if (ARGUMENT_PRESENT( UserValue )) { 01301 01302 *UserValue = (PVOID)ExtraStuff->Settable; 01303 } 01304 } 01305 01306 // 01307 // If the user asked for user flags then return the flags 01308 // from the heap entry that are user setable 01309 // 01310 01311 if (ARGUMENT_PRESENT( UserFlags )) { 01312 01313 *UserFlags = (BusyBlock->Flags & HEAP_ENTRY_SETTABLE_FLAGS) << 4; 01314 } 01315 01316 // 01317 // Now that the assignments are done we can say that 01318 // we were successful 01319 // 01320 01321 Result = TRUE; 01322 } 01323 01324 } except( EXCEPTION_EXECUTE_HANDLER ) { 01325 01326 SET_LAST_STATUS( GetExceptionCode() ); 01327 01328 Result = FALSE; 01329 } 01330 01331 } finally { 01332 01333 // 01334 // Unlock the heap 01335 // 01336 01337 if (LockAcquired) { 01338 01339 RtlReleaseLockRoutine( Heap->LockVariable ); 01340 } 01341 } 01342 01343 // 01344 // And return to our caller 01345 // 01346 01347 return Result; 01348 }

NTSTATUS RtlInitializeHeapManager VOID   ) 
 

Definition at line 179 of file heapdll.c.

References CHECK_HEAP_TAIL_SIZE, HeapDebugBreak, HeapDebugPrint, _HEAP_LOCK::Lock, NULL, RtlInitializeLockRoutine, RTLP_STATIC_HEAP_LIST_SIZE, RtlpProcessHeapsListBuffer, RtlpProcessHeapsListLock, and VOID().

Referenced by LdrpForkProcess(), LdrpInitializeProcess(), and main().

00185 : 00186 00187 This routine is used to initialize the heap manager for the current process 00188 00189 Arguments: 00190 00191 None. 00192 00193 Return Value: 00194 00195 None. 00196 00197 --*/ 00198 00199 { 00200 PPEB Peb = NtCurrentPeb(); 00201 00202 #if DBG 00203 00204 // 00205 // Sanity check the sizes of the header entry structures 00206 // 00207 00208 if (sizeof( HEAP_ENTRY ) != sizeof( HEAP_ENTRY_EXTRA )) { 00209 00210 HeapDebugPrint(( "Heap header and extra header sizes disagree\n" )); 00211 00212 HeapDebugBreak( NULL ); 00213 } 00214 00215 if (sizeof( HEAP_ENTRY ) != CHECK_HEAP_TAIL_SIZE) { 00216 00217 HeapDebugPrint(( "Heap header and tail fill sizes disagree\n" )); 00218 00219 HeapDebugBreak( NULL ); 00220 } 00221 00222 if (sizeof( HEAP_FREE_ENTRY ) != (2 * sizeof( HEAP_ENTRY ))) { 00223 00224 HeapDebugPrint(( "Heap header and free header sizes disagree\n" )); 00225 00226 HeapDebugBreak( NULL ); 00227 } 00228 00229 #endif // DBG 00230 00231 // 00232 // Initialize the heap specific structures in the current peb 00233 // 00234 00235 Peb->NumberOfHeaps = 0; 00236 Peb->MaximumNumberOfHeaps = RTLP_STATIC_HEAP_LIST_SIZE; 00237 Peb->ProcessHeaps = RtlpProcessHeapsListBuffer; 00238 00239 #ifdef NTHEAP_ENABLED 00240 { 00241 (VOID) RtlInitializeNtHeapManager(); 00242 } 00243 #endif // NTHEAP_ENABLED 00244 00245 // 00246 // Initialize the lock and return to our caller 00247 // 00248 00249 return RtlInitializeLockRoutine( &RtlpProcessHeapsListLock.Lock ); 00250 }

BOOLEAN RtlLockHeap IN PVOID  HeapHandle  ) 
 

Definition at line 390 of file heapdll.c.

References FALSE, _HEAP::Flags, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, _HEAP::LockVariable, _HEAP::LookasideLockCount, RTL_PAGED_CODE, RtlAcquireLockRoutine, RtlpCheckHeapSignature(), RtlpDebugPageHeapLock(), and TRUE.

00396 : 00397 00398 This routine is used by lock access to a specific heap structure 00399 00400 Arguments: 00401 00402 HeapHandle - Supplies a pointer to the heap being locked 00403 00404 Return Value: 00405 00406 BOOLEAN - TRUE if the heap is now locked and FALSE otherwise (i.e., 00407 the heap is ill-formed). TRUE is returned even if the heap is 00408 not lockable. 00409 00410 --*/ 00411 00412 { 00413 PHEAP Heap = (PHEAP)HeapHandle; 00414 00415 RTL_PAGED_CODE(); 00416 00417 // 00418 // Check for the heap protected by guard pages 00419 // 00420 00421 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 00422 RtlpDebugPageHeapLock( HeapHandle )); 00423 00424 // 00425 // Validate that HeapAddress points to a HEAP structure. 00426 // 00427 00428 if (!RtlpCheckHeapSignature( Heap, "RtlLockHeap" )) { 00429 00430 return FALSE; 00431 } 00432 00433 // 00434 // Lock the heap. And disable the lookaside list by incrementing 00435 // its lock count. 00436 // 00437 00438 if (!(Heap->Flags & HEAP_NO_SERIALIZE)) { 00439 00440 RtlAcquireLockRoutine( Heap->LockVariable ); 00441 00442 Heap->LookasideLockCount += 1; 00443 } 00444 00445 return TRUE; 00446 }

VOID RtlpAddHeapToProcessList IN PHEAP  Heap  ) 
 

Definition at line 4457 of file heapdll.c.

References _HEAP_LOCK::Lock, NULL, RtlAcquireLockRoutine, RtlAllocateHeap, RtlFreeHeap, RtlpProcessHeapsListBuffer, RtlpProcessHeapsListLock, RtlReleaseLockRoutine, and USHORT.

Referenced by RtlCreateHeap().

04463 : 04464 04465 This routine adds the specified heap to the heap list for the 04466 current process 04467 04468 Arguments: 04469 04470 Heap - Supplies a pointer to the heap being added 04471 04472 Return Value: 04473 04474 None. 04475 04476 --*/ 04477 04478 { 04479 PPEB Peb = NtCurrentPeb(); 04480 PHEAP *NewList; 04481 04482 // 04483 // Lock the processes heap list 04484 // 04485 04486 RtlAcquireLockRoutine( &RtlpProcessHeapsListLock.Lock ); 04487 04488 try { 04489 04490 // 04491 // If the processes heap list is already full then we'll 04492 // double the size of the heap list for the process 04493 // 04494 04495 if (Peb->NumberOfHeaps == Peb->MaximumNumberOfHeaps) { 04496 04497 // 04498 // Double the size 04499 // 04500 04501 Peb->MaximumNumberOfHeaps *= 2; 04502 04503 // 04504 // Allocate space for the new list 04505 // 04506 04507 NewList = RtlAllocateHeap( RtlProcessHeap(), 04508 0, 04509 Peb->MaximumNumberOfHeaps * sizeof( *NewList )); 04510 04511 if (NewList == NULL) { 04512 04513 leave; 04514 } 04515 04516 // 04517 // Copy over the old buffer to the new buffer 04518 // 04519 04520 RtlMoveMemory( NewList, 04521 Peb->ProcessHeaps, 04522 Peb->NumberOfHeaps * sizeof( *NewList )); 04523 04524 // 04525 // Check if we should free the previous heap list buffer 04526 // 04527 04528 if (Peb->ProcessHeaps != RtlpProcessHeapsListBuffer) { 04529 04530 RtlFreeHeap( RtlProcessHeap(), 0, Peb->ProcessHeaps ); 04531 } 04532 04533 // 04534 // Set the new list 04535 // 04536 04537 Peb->ProcessHeaps = NewList; 04538 } 04539 04540 // 04541 // Add the input heap to the next free heap list slot, and note that 04542 // the processes heap list index is really one beyond the actualy 04543 // index used to get the processes heap 04544 // 04545 04546 Peb->ProcessHeaps[ Peb->NumberOfHeaps++ ] = Heap; 04547 Heap->ProcessHeapsListIndex = (USHORT)Peb->NumberOfHeaps; 04548 04549 } finally { 04550 04551 // 04552 // Unlock the processes heap list 04553 // 04554 04555 RtlReleaseLockRoutine( &RtlpProcessHeapsListLock.Lock ); 04556 } 04557 04558 // 04559 // And return to our caller 04560 // 04561 04562 return; 04563 }

NTSTATUS RtlpAllocateHeapUsageEntry PRTL_HEAP_USAGE_INTERNAL  Buffer,
PRTL_HEAP_USAGE_ENTRY *  pp
 

Definition at line 5954 of file heapdll.c.

References Buffer, NT_SUCCESS, NtAllocateVirtualMemory(), NTSTATUS(), NULL, PAGE_SIZE, and Status.

Referenced by RtlUsageHeap().

05961 : 05962 05963 This routine is used to allocate an new heap usage entry 05964 from the internal heap usage buffer 05965 05966 Arguments: 05967 05968 Buffer - Supplies a pointer to the internal heap usage 05969 buffer from which to allocate an entry 05970 05971 pp - Receives a pointer to the newly allocated heap 05972 usage entry. If pp is already pointing to an existing 05973 heap usage entry then on return we'll have this old 05974 entry point to the new entry, but still return the new 05975 entry. 05976 05977 Return Value: 05978 05979 NTSTATUS - An appropriate status value 05980 05981 --*/ 05982 05983 { 05984 NTSTATUS Status; 05985 PRTL_HEAP_USAGE_ENTRY p; 05986 PVOID CommitAddress; 05987 SIZE_T PageSize; 05988 05989 // 05990 // Check if the free list is empty and then we have to allocate more 05991 // memory for the free list 05992 // 05993 05994 if (Buffer->FreeList == NULL) { 05995 05996 // 05997 // We cannot grow the buffer any larger than the reserved size 05998 // 05999 06000 if (Buffer->CommittedSize >= Buffer->ReservedSize) { 06001 06002 return STATUS_NO_MEMORY; 06003 } 06004 06005 // 06006 // Try and add one page of committed memory to the buffer 06007 // starting right after the currently committed space 06008 // 06009 06010 PageSize = PAGE_SIZE; 06011 06012 CommitAddress = (PCHAR)Buffer->Base + Buffer->CommittedSize; 06013 06014 Status = NtAllocateVirtualMemory( NtCurrentProcess(), 06015 &CommitAddress, 06016 0, 06017 &PageSize, 06018 MEM_COMMIT, 06019 PAGE_READWRITE ); 06020 06021 if (!NT_SUCCESS( Status )) { 06022 06023 return Status; 06024 } 06025 06026 // 06027 // Update the committed buffer size 06028 // 06029 06030 Buffer->CommittedSize += PageSize; 06031 06032 // 06033 // Add the newly allocated space to the free list and 06034 // build up the free list 06035 // 06036 06037 Buffer->FreeList = CommitAddress; 06038 06039 p = Buffer->FreeList; 06040 06041 while (PageSize != 0) { 06042 06043 p->Next = (p+1); 06044 p += 1; 06045 PageSize -= sizeof( *p ); 06046 } 06047 06048 // 06049 // Null terminate the next pointer in the last free entry 06050 // 06051 06052 p -= 1; 06053 p->Next = NULL; 06054 } 06055 06056 // 06057 // At this point the free list contains at least one entry 06058 // so simply pop the entry. 06059 // 06060 06061 p = Buffer->FreeList; 06062 06063 Buffer->FreeList = p->Next; 06064 06065 p->Next = NULL; 06066 06067 // 06068 // Now if the caller supplied an existing heap entry then 06069 // we'll make the old heap entry point to this new entry 06070 // 06071 06072 if (*pp) { 06073 06074 (*pp)->Next = p; 06075 } 06076 06077 // 06078 // And then return the new entry to our caller 06079 // 06080 06081 *pp = p; 06082 06083 return STATUS_SUCCESS; 06084 }

PHEAP_TAG_ENTRY RtlpAllocateTags PHEAP  Heap,
ULONG  NumberOfTags
 

Definition at line 5225 of file heapdll.c.

References _HEAP_TAG_ENTRY::CreatorBackTraceIndex, _HEAP::Flags, HEAP_CAPTURE_STACK_BACKTRACES, HEAP_SIGNATURE, _HEAP::MaximumTagIndex, _HEAP::NextAvailableTagIndex, NT_SUCCESS, NtAllocateVirtualMemory(), NTSTATUS(), NULL, PAGE_SIZE, RtlpGlobalTagHeap, _HEAP::Signature, Status, _HEAP::TagEntries, _HEAP_TAG_ENTRY::TagIndex, and USHORT.

Referenced by RtlCreateTagHeap().

05232 : 05233 05234 This routine is used to allocate space for additional tags within 05235 a heap 05236 05237 Arguments: 05238 05239 Heap - Supplies a pointer to the heap being modified. If not specified 05240 then the processes global tag heap is used 05241 05242 NumberOfTags - Supplies the number of tags that we want stored in the 05243 heap. This is the number to grow the tag list by. 05244 05245 Return Value: 05246 05247 PHEAP_TAG_ENTRY - Returns a pointer to the next available tag entry in the 05248 heap 05249 05250 --*/ 05251 05252 { 05253 NTSTATUS Status; 05254 ULONG TagIndex; 05255 SIZE_T ReserveSize; 05256 SIZE_T CommitSize; 05257 PHEAP_TAG_ENTRY TagEntry; 05258 USHORT CreatorBackTraceIndex; 05259 USHORT MaximumTagIndex; 05260 USHORT TagIndexFlag; 05261 05262 // 05263 // Check if the process has a global tag heap. If not then there is 05264 // nothing for us to do 05265 // 05266 05267 if (RtlpGlobalTagHeap == NULL) { 05268 05269 return NULL; 05270 } 05271 05272 // 05273 // If the user didn't give us a heap then use the processes global 05274 // tag heap 05275 // 05276 05277 if (Heap == NULL) { 05278 05279 RtlpGlobalTagHeap->Signature = HEAP_SIGNATURE; 05280 05281 RtlpGlobalTagHeap->Flags = HEAP_NO_SERIALIZE; 05282 05283 TagIndexFlag = HEAP_GLOBAL_TAG; 05284 05285 Heap = RtlpGlobalTagHeap; 05286 05287 } else { 05288 05289 TagIndexFlag = 0; 05290 } 05291 05292 // 05293 // Grab the stack backtrace if possible and if we should 05294 // 05295 05296 CreatorBackTraceIndex = 0; 05297 05298 #if i386 05299 05300 if (Heap->Flags & HEAP_CAPTURE_STACK_BACKTRACES) { 05301 05302 CreatorBackTraceIndex = (USHORT)RtlLogStackBackTrace(); 05303 } 05304 05305 #endif // i386 05306 05307 // 05308 // If the heap does not already have tag entries then we'll 05309 // reserve space for them 05310 // 05311 05312 if (Heap->TagEntries == NULL) { 05313 05314 MaximumTagIndex = HEAP_MAXIMUM_TAG & ~HEAP_GLOBAL_TAG; 05315 05316 ReserveSize = MaximumTagIndex * sizeof( HEAP_TAG_ENTRY ); 05317 05318 Status = NtAllocateVirtualMemory( NtCurrentProcess(), 05319 &Heap->TagEntries, 05320 0, 05321 &ReserveSize, 05322 MEM_RESERVE, 05323 PAGE_READWRITE ); 05324 05325 if (!NT_SUCCESS( Status )) { 05326 05327 return NULL; 05328 } 05329 05330 Heap->MaximumTagIndex = MaximumTagIndex; 05331 05332 Heap->NextAvailableTagIndex = 0; 05333 05334 // 05335 // Add one for zero tag, as that is always reserved for heap name 05336 // 05337 05338 NumberOfTags += 1; 05339 } 05340 05341 // 05342 // At this point we have a space reserved for tag entries. If the number 05343 // of tags that we need to grow is too large then tell the user we can't 05344 // do it. 05345 // 05346 05347 if (NumberOfTags > (ULONG)(Heap->MaximumTagIndex - Heap->NextAvailableTagIndex)) { 05348 05349 return NULL; 05350 } 05351 05352 // 05353 // Get a pointer to the next available tag entry, and for 05354 // every tag entry that we want to grow by we'll commit 05355 // the page containing the tag entry. We only need to do 05356 // this for every page just once. We'll determine this 05357 // by seeing when the tag entry crosses a page boundary 05358 // 05359 05360 TagEntry = Heap->TagEntries + Heap->NextAvailableTagIndex; 05361 05362 for (TagIndex = Heap->NextAvailableTagIndex; 05363 TagIndex < Heap->NextAvailableTagIndex + NumberOfTags; 05364 TagIndex++ ) { 05365 05366 if (((((ULONG_PTR)TagEntry + sizeof(*TagEntry)) & (PAGE_SIZE-1)) <= 05367 sizeof(*TagEntry))) { 05368 05369 CommitSize = PAGE_SIZE; 05370 05371 Status = NtAllocateVirtualMemory( NtCurrentProcess(), 05372 &TagEntry, 05373 0, 05374 &CommitSize, 05375 MEM_COMMIT, 05376 PAGE_READWRITE ); 05377 05378 if (!NT_SUCCESS( Status )) { 05379 05380 return NULL; 05381 } 05382 } 05383 05384 // 05385 // Bias the tag index if this is the global tag heap 05386 // 05387 05388 TagEntry->TagIndex = (USHORT)TagIndex | TagIndexFlag; 05389 05390 // 05391 // Set the stack back trace 05392 // 05393 05394 TagEntry->CreatorBackTraceIndex = CreatorBackTraceIndex; 05395 05396 // 05397 // Move on to the next tag entry 05398 // 05399 05400 TagEntry += 1; 05401 } 05402 05403 // 05404 // At this point we've build the new tag list so now pop off the next 05405 // available tag entry 05406 // 05407 05408 TagEntry = Heap->TagEntries + Heap->NextAvailableTagIndex; 05409 05410 Heap->NextAvailableTagIndex += (USHORT)NumberOfTags; 05411 05412 // 05413 // And return to our caller 05414 // 05415 05416 return TagEntry; 05417 }

BOOLEAN RtlpCheckHeapSignature IN PHEAP  Heap,
IN PCHAR  Caller
 

Definition at line 4250 of file heapdll.c.

References DbgPrint, FALSE, HEAP_SIGNATURE, HeapDebugBreak, HeapDebugPrint, NULL, and TRUE.

Referenced by RtlDebugAllocateHeap(), RtlDebugCompactHeap(), RtlDebugCreateTagHeap(), RtlDebugDestroyHeap(), RtlDebugFreeHeap(), RtlDebugGetUserInfoHeap(), RtlDebugQueryTagHeap(), RtlDebugReAllocateHeap(), RtlDebugSetUserFlagsHeap(), RtlDebugSetUserValueHeap(), RtlDebugSizeHeap(), RtlDebugUsageHeap(), RtlDebugWalkHeap(), RtlDebugZeroHeap(), RtlLockHeap(), RtlpSerializeHeap(), RtlUnlockHeap(), and RtlValidateHeap().

04257 : 04258 04259 This routine verifies that it is being called with a properly identified 04260 heap. 04261 04262 Arguments: 04263 04264 Heap - Supplies a pointer to the heap being checked 04265 04266 Caller - Supplies a string that can be used to identify the caller 04267 04268 Return Value: 04269 04270 BOOLEAN - TRUE if the heap signature is present, and FALSE otherwise 04271 04272 --*/ 04273 04274 { 04275 // 04276 // If the heap signature matches then that is the only 04277 // checking we do 04278 // 04279 04280 if (Heap->Signature == HEAP_SIGNATURE) { 04281 04282 return TRUE; 04283 04284 } else { 04285 04286 // 04287 // We have a bad heap signature. Print out some information, break 04288 // into the debugger, and then return false 04289 // 04290 04291 HeapDebugPrint(( "Invalid heap signature for heap at %x", Heap )); 04292 04293 if (Caller != NULL) { 04294 04295 DbgPrint( ", passed to %s", Caller ); 04296 } 04297 04298 DbgPrint( "\n" ); 04299 04300 HeapDebugBreak( &Heap->Signature ); 04301 04302 return FALSE; 04303 } 04304 }

PHEAP_FREE_ENTRY RtlpCoalesceHeap IN PHEAP  Heap  ) 
 

Definition at line 4312 of file heapdll.c.

References _HEAP_FREE_ENTRY::Flags, HEAP_ENTRY_LAST_ENTRY, HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_FREELISTS, n, NULL, PAGE_SIZE, _HEAP_FREE_ENTRY::PreviousSize, RTL_PAGED_CODE, RtlpCoalesceFreeBlocks(), RtlpDeCommitFreeBlock(), RtlpInsertFreeBlock(), _HEAP_FREE_ENTRY::Size, and TRUE.

Referenced by RtlCompactHeap(), and RtlpExtendHeap().

04318 : 04319 04320 This routine scans through heap and coalesces its free blocks 04321 04322 Arguments: 04323 04324 Heap - Supplies a pointer to the heap being modified 04325 04326 Return Value: 04327 04328 PHEAP_FREE_ENTRY - returns a pointer to the largest free block 04329 in the heap 04330 04331 --*/ 04332 04333 { 04334 SIZE_T OldFreeSize; 04335 SIZE_T FreeSize; 04336 ULONG n; 04337 PHEAP_FREE_ENTRY FreeBlock, LargestFreeBlock; 04338 PLIST_ENTRY FreeListHead, Next; 04339 04340 RTL_PAGED_CODE(); 04341 04342 LargestFreeBlock = NULL; 04343 04344 // 04345 // For every free list in the heap, going from smallest to 04346 // largest and skipping the zero index one we will 04347 // scan the free list coalesceing the free blocks 04348 // 04349 04350 FreeListHead = &Heap->FreeLists[ 1 ]; 04351 04352 n = HEAP_MAXIMUM_FREELISTS; 04353 04354 while (n--) { 04355 04356 // 04357 // Scan the individual free list 04358 // 04359 04360 Next = FreeListHead->Blink; 04361 04362 while (FreeListHead != Next) { 04363 04364 // 04365 // Get a pointer to the current free list entry, and remember its 04366 // next and size 04367 // 04368 04369 FreeBlock = CONTAINING_RECORD( Next, HEAP_FREE_ENTRY, FreeList ); 04370 04371 Next = Next->Flink; 04372 OldFreeSize = FreeSize = FreeBlock->Size; 04373 04374 // 04375 // Coalesce the block 04376 // 04377 04378 FreeBlock = RtlpCoalesceFreeBlocks( Heap, 04379 FreeBlock, 04380 &FreeSize, 04381 TRUE ); 04382 04383 // 04384 // If the new free size is not equal to the old free size 04385 // then we actually did some changes otherwise the coalesce 04386 // calll was essentialy a noop 04387 // 04388 04389 if (FreeSize != OldFreeSize) { 04390 04391 // 04392 // Check if we should decommit this block because it is too 04393 // large and it is either at the beginning or end of a 04394 // committed run. Otherwise just insert the new sized 04395 // block into its corresponding free list. We'll hit this 04396 // block again when we visit larger free lists. 04397 // 04398 04399 if (FreeBlock->Size >= (PAGE_SIZE >> HEAP_GRANULARITY_SHIFT) 04400 04401 && 04402 04403 (FreeBlock->PreviousSize == 0 || 04404 (FreeBlock->Flags & HEAP_ENTRY_LAST_ENTRY))) { 04405 04406 RtlpDeCommitFreeBlock( Heap, FreeBlock, FreeSize ); 04407 04408 } else { 04409 04410 RtlpInsertFreeBlock( Heap, FreeBlock, FreeSize ); 04411 } 04412 04413 Next = FreeListHead->Blink; 04414 04415 } else { 04416 04417 // 04418 // Remember the largest free block we've found so far 04419 // 04420 04421 if ((LargestFreeBlock == NULL) || 04422 (LargestFreeBlock->Size < FreeBlock->Size)) { 04423 04424 LargestFreeBlock = FreeBlock; 04425 } 04426 } 04427 } 04428 04429 // 04430 // Go to the next free list. When we hit the largest dedicated 04431 // size free list we'll fall back to the [0] index list 04432 // 04433 04434 if (n == 1) { 04435 04436 FreeListHead = &Heap->FreeLists[ 0 ]; 04437 04438 } else { 04439 04440 FreeListHead++; 04441 } 04442 } 04443 04444 // 04445 // And return to our caller 04446 // 04447 04448 return LargestFreeBlock; 04449 }

VOID RtlpDestroyTags PHEAP  Heap  ) 
 

Definition at line 5893 of file heapdll.c.

References NT_SUCCESS, NtFreeVirtualMemory(), NTSTATUS(), NULL, Status, and _HEAP::TagEntries.

Referenced by RtlDestroyHeap().

05899 : 05900 05901 This routine is used to completely remove all the normal tag entries 05902 in use by a heap 05903 05904 Arguments: 05905 05906 Heap - Supplies a pointer to the heap being modified 05907 05908 Return Value: 05909 05910 None. 05911 05912 --*/ 05913 05914 { 05915 NTSTATUS Status; 05916 SIZE_T RegionSize; 05917 05918 // 05919 // We will only do the action if the heap has some tag entries 05920 // 05921 05922 if (Heap->TagEntries != NULL) { 05923 05924 // 05925 // Release all the memory used by the tag entries 05926 // 05927 05928 RegionSize = 0; 05929 05930 Status = NtFreeVirtualMemory( NtCurrentProcess(), 05931 &Heap->TagEntries, 05932 &RegionSize, 05933 MEM_RELEASE ); 05934 05935 if (NT_SUCCESS( Status )) { 05936 05937 Heap->TagEntries = NULL; 05938 } 05939 } 05940 05941 // 05942 // And return to our caller 05943 // 05944 05945 return; 05946 }

PRTL_HEAP_USAGE_ENTRY RtlpFreeHeapUsageEntry PRTL_HEAP_USAGE_INTERNAL  Buffer,
PRTL_HEAP_USAGE_ENTRY  p
 

Definition at line 6092 of file heapdll.c.

References Buffer, and NULL.

Referenced by RtlUsageHeap().

06099 : 06100 06101 This routine moves a heap usage entry from its current 06102 list onto the free list and returns a pointer to the 06103 next heap usage entry in the list. It is like doing a pop 06104 of the list denoted by "p" 06105 06106 Arguments: 06107 06108 Buffer - Supplies a pointer to the internal heap usage buffer 06109 being modified 06110 06111 p - Supplies a pointer to the entry being moved. Okay if 06112 it's null 06113 06114 Return Value: 06115 06116 PRTL_HEAP_USAGE_ENTRY - Returns a pointer to the next heap usage 06117 entry 06118 06119 --*/ 06120 06121 { 06122 PRTL_HEAP_USAGE_ENTRY pTmp; 06123 06124 // 06125 // Check if we have a non null heap entry and if so then add 06126 // the entry to the front of the free list and return the next 06127 // entry in the list 06128 // 06129 06130 if (p != NULL) { 06131 06132 pTmp = p->Next; 06133 06134 p->Next = Buffer->FreeList; 06135 06136 Buffer->FreeList = p; 06137 06138 } else { 06139 06140 pTmp = NULL; 06141 } 06142 06143 return pTmp; 06144 }

PWSTR RtlpGetTagName PHEAP  Heap,
USHORT  TagIndex
 

Definition at line 5425 of file heapdll.c.

References HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_FREELISTS, HEAP_NUMBER_OF_PSEUDO_TAG, L, _HEAP::NextAvailableTagIndex, NULL, _HEAP::PseudoTagEntries, RtlpGlobalTagHeap, RtlpPseudoTagNameBuffer, _HEAP::TagEntries, and _HEAP_TAG_ENTRY::TagName.

Referenced by RtlDebugAllocateHeap(), RtlDebugFreeHeap(), and RtlDebugReAllocateHeap().

05432 : 05433 05434 This routine returns the name of the tag denoted by the heap, tagindex 05435 tuple. 05436 05437 This routine is only called by heapdbg when doing a debug print to 05438 generate a tag name for printing 05439 05440 Arguments: 05441 05442 Heap - Supplies the tag being queried 05443 05444 TagIndex - Supplies the index for the tag being queried 05445 05446 Return Value: 05447 05448 PWSTR - returns the name of the indicated tag 05449 05450 --*/ 05451 05452 { 05453 // 05454 // If the processes global tag heap has not been initialized then 05455 // not tag has a name 05456 // 05457 05458 if (RtlpGlobalTagHeap == NULL) { 05459 05460 return NULL; 05461 } 05462 05463 // 05464 // We only deal with non zero tag indices 05465 // 05466 05467 if (TagIndex != 0) { 05468 05469 // 05470 // If the tag index is for a pseudo tag then we clear the 05471 // the psuedo bit and generate a pseudo tag name 05472 // 05473 05474 if (TagIndex & HEAP_PSEUDO_TAG_FLAG) { 05475 05476 TagIndex &= ~HEAP_PSEUDO_TAG_FLAG; 05477 05478 // 05479 // Check that the tag index is valid and that the heap 05480 // has some psuedo tag entries 05481 // 05482 05483 if ((TagIndex < HEAP_NUMBER_OF_PSEUDO_TAG) && 05484 (Heap->PseudoTagEntries != NULL)) { 05485 05486 // 05487 // A pseudo tag index of zero denote objects 05488 // 05489 05490 if (TagIndex == 0) { 05491 05492 swprintf( RtlpPseudoTagNameBuffer, L"Objects>%4u", 05493 HEAP_MAXIMUM_FREELISTS << HEAP_GRANULARITY_SHIFT ); 05494 05495 // 05496 // A psuedo tag index less than the free list maximum 05497 // denotes the dedicated free list 05498 // 05499 05500 } else if (TagIndex < HEAP_MAXIMUM_FREELISTS) { 05501 05502 swprintf( RtlpPseudoTagNameBuffer, L"Objects=%4u", TagIndex << HEAP_GRANULARITY_SHIFT ); 05503 05504 // 05505 // Otherwise the pseudo tag is for the big allocations 05506 // 05507 05508 } else { 05509 05510 swprintf( RtlpPseudoTagNameBuffer, L"VirtualAlloc" ); 05511 } 05512 05513 return RtlpPseudoTagNameBuffer; 05514 } 05515 05516 // 05517 // Otherwise if the tag index is for a global tag then we pull 05518 // the name off of the global heap. Provided the index is valid 05519 // and the heap does have some tag entries 05520 // 05521 05522 } else if (TagIndex & HEAP_GLOBAL_TAG) { 05523 05524 TagIndex &= ~HEAP_GLOBAL_TAG; 05525 05526 if ((TagIndex < RtlpGlobalTagHeap->NextAvailableTagIndex) && 05527 (RtlpGlobalTagHeap->TagEntries != NULL)) { 05528 05529 return RtlpGlobalTagHeap->TagEntries[ TagIndex ].TagName; 05530 } 05531 05532 // 05533 // Otherwise we'll pull the name off of the input heap 05534 // provided the index is valid and the heap does have some 05535 // tag entries 05536 // 05537 05538 } else if ((TagIndex < Heap->NextAvailableTagIndex) && 05539 (Heap->TagEntries != NULL)) { 05540 05541 return Heap->TagEntries[ TagIndex ].TagName; 05542 } 05543 } 05544 05545 return NULL; 05546 }

BOOLEAN RtlpGrowBlockInPlace IN PHEAP  Heap,
IN ULONG  Flags,
IN PHEAP_ENTRY  BusyBlock,
IN SIZE_T  Size,
IN SIZE_T  AllocationIndex
 

Definition at line 4693 of file heapdll.c.

References ALLOC_HEAP_FILL, CHECK_HEAP_TAIL_FILL, CHECK_HEAP_TAIL_SIZE, DEBUG_HEAP, FALSE, _HEAP_FREE_ENTRY::Flags, _HEAP_ENTRY::Flags, HEAP_ENTRY_BUSY, HEAP_ENTRY_EXTRA_PRESENT, HEAP_ENTRY_LAST_ENTRY, HEAP_ENTRY_SETTABLE_FLAGS, HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_BLOCK_SIZE, IS_HEAP_TAGGING_ENABLED, _HEAP_SEGMENT::LastEntryInSegment, NULL, PAGE_SIZE, _HEAP_FREE_ENTRY::PreviousSize, ReAllocationAction, ROUND_UP_TO_POWER2, RtlpCoalesceFreeBlocks(), RtlpFindAndCommitPages(), RtlpInsertFreeBlock(), RtlpInsertFreeBlockDirect, RtlpRemoveFreeBlock, RtlpUpdateTagEntry(), RtlpValidateHeapHeaders(), _HEAP_FREE_ENTRY::SegmentIndex, _HEAP_ENTRY::Size, Size, _HEAP_FREE_ENTRY::Size, _HEAP_ENTRY_EXTRA::TagIndex, TRUE, and USHORT.

Referenced by RtlReAllocateHeap().

04703 : 04704 04705 This routine will try and grow a heap allocation block at its current 04706 location 04707 04708 Arguments: 04709 04710 Heap - Supplies a pointer to the heap being modified 04711 04712 Flags - Supplies a set of flags to augment those already enforced by 04713 the heap 04714 04715 BusyBlock - Supplies a pointer to the block being resized 04716 04717 Size - Supplies the size, in bytes, needed by the resized block 04718 04719 AllocationIndex - Supplies the allocation index for the resized block 04720 Note that the size variable has not been rounded up to the next 04721 granular block size, but that allocation index has. 04722 04723 Return Value: 04724 04725 BOOLEAN - TRUE if the block has been resized and FALSE otherwise 04726 04727 --*/ 04728 04729 { 04730 SIZE_T FreeSize; 04731 SIZE_T OldSize; 04732 UCHAR EntryFlags, FreeFlags; 04733 PHEAP_FREE_ENTRY FreeBlock, SplitBlock, SplitBlock2; 04734 PHEAP_ENTRY_EXTRA OldExtraStuff, NewExtraStuff; 04735 04736 // 04737 // Check if the allocation index is too large for even the nondedicated 04738 // free list (i.e., too large for list [0]) 04739 // 04740 04741 if (AllocationIndex > Heap->VirtualMemoryThreshold) { 04742 04743 return FALSE; 04744 } 04745 04746 // 04747 // Get the flags for the current block and a pointer to the next 04748 // block following the current block 04749 // 04750 04751 EntryFlags = BusyBlock->Flags; 04752 04753 FreeBlock = (PHEAP_FREE_ENTRY)(BusyBlock + BusyBlock->Size); 04754 04755 // 04756 // If the current block is the last entry before an uncommitted range 04757 // we'll try and extend the uncommitted range to fit our new allocation 04758 // 04759 04760 if (EntryFlags & HEAP_ENTRY_LAST_ENTRY) { 04761 04762 // 04763 // Calculate how must more we need beyond the current block 04764 // size 04765 // 04766 04767 FreeSize = (AllocationIndex - BusyBlock->Size) << HEAP_GRANULARITY_SHIFT; 04768 FreeSize = ROUND_UP_TO_POWER2( FreeSize, PAGE_SIZE ); 04769 04770 // 04771 // Try and commit memory at the desired location 04772 // 04773 04774 FreeBlock = RtlpFindAndCommitPages( Heap, 04775 Heap->Segments[ BusyBlock->SegmentIndex ], 04776 &FreeSize, 04777 (PHEAP_ENTRY)FreeBlock ); 04778 04779 // 04780 // Check if the commit succeeded 04781 // 04782 04783 if (FreeBlock == NULL) { 04784 04785 return FALSE; 04786 } 04787 04788 // 04789 // New coalesce this newly committed space with whatever is free 04790 // around it 04791 // 04792 04793 FreeSize = FreeSize >> HEAP_GRANULARITY_SHIFT; 04794 04795 FreeBlock = RtlpCoalesceFreeBlocks( Heap, FreeBlock, &FreeSize, FALSE ); 04796 04797 FreeFlags = FreeBlock->Flags; 04798 04799 // 04800 // If the newly allocated space plus the current block size is still 04801 // not big enough for our resize effort then put this newly 04802 // allocated block into the appropriate free list and tell our caller 04803 // that a resize wasn't possible 04804 // 04805 04806 if ((FreeSize + BusyBlock->Size) < AllocationIndex) { 04807 04808 RtlpInsertFreeBlock( Heap, FreeBlock, FreeSize ); 04809 04810 Heap->TotalFreeSize += FreeSize; 04811 04812 if (DEBUG_HEAP(Flags)) { 04813 04814 RtlpValidateHeapHeaders( Heap, TRUE ); 04815 } 04816 04817 return FALSE; 04818 } 04819 04820 // 04821 // We were able to generate enough space for the resize effort, so 04822 // now free size will be the index for the current block plus the 04823 // new free space 04824 // 04825 04826 FreeSize += BusyBlock->Size; 04827 04828 } else { 04829 04830 // 04831 // The following block is present so grab its flags and see if 04832 // it is free or busy. If busy then we cannot grow the current 04833 // block 04834 // 04835 04836 FreeFlags = FreeBlock->Flags; 04837 04838 if (FreeFlags & HEAP_ENTRY_BUSY) { 04839 04840 return FALSE; 04841 } 04842 04843 // 04844 // Compute the index if we combine current block with its following 04845 // free block and check if it is big enough 04846 // 04847 04848 FreeSize = BusyBlock->Size + FreeBlock->Size; 04849 04850 if (FreeSize < AllocationIndex) { 04851 04852 return FALSE; 04853 } 04854 04855 // 04856 // The two blocks together are big enough so now remove the free 04857 // block from its free list, and update the heap's total free size 04858 // 04859 04860 RtlpRemoveFreeBlock( Heap, FreeBlock ); 04861 04862 Heap->TotalFreeSize -= FreeBlock->Size; 04863 } 04864 04865 // 04866 // At this point we have a busy block followed by a free block that 04867 // together have enough space for the resize. The free block has been 04868 // removed from its list and free size is the index of the two combined 04869 // blocks. 04870 // 04871 // Calculate the number of bytes in use in the old block 04872 // 04873 04874 OldSize = (BusyBlock->Size << HEAP_GRANULARITY_SHIFT) - BusyBlock->UnusedBytes; 04875 04876 // 04877 // Calculate the index for whatever excess we'll have when we combine 04878 // the two blocks 04879 // 04880 04881 FreeSize -= AllocationIndex; 04882 04883 // 04884 // If the excess is not too much then put it back in our allocation 04885 // (i.e., we don't want small free pieces left over) 04886 // 04887 04888 if (FreeSize <= 2) { 04889 04890 AllocationIndex += FreeSize; 04891 04892 FreeSize = 0; 04893 } 04894 04895 // 04896 // If the busy block has an extra stuff struct present then copy over the 04897 // extra stuff 04898 // 04899 04900 if (EntryFlags & HEAP_ENTRY_EXTRA_PRESENT) { 04901 04902 OldExtraStuff = (PHEAP_ENTRY_EXTRA)(BusyBlock + BusyBlock->Size - 1); 04903 NewExtraStuff = (PHEAP_ENTRY_EXTRA)(BusyBlock + AllocationIndex - 1); 04904 04905 *NewExtraStuff = *OldExtraStuff; 04906 04907 // 04908 // If heap tagging is enabled then update the heap tag from the extra 04909 // stuff struct 04910 // 04911 04912 if (IS_HEAP_TAGGING_ENABLED()) { 04913 04914 NewExtraStuff->TagIndex = 04915 RtlpUpdateTagEntry( Heap, 04916 NewExtraStuff->TagIndex, 04917 BusyBlock->Size, 04918 AllocationIndex, 04919 ReAllocationAction ); 04920 } 04921 04922 // 04923 // Otherwise extra stuff is not in use so see if heap tagging is enabled 04924 // and if so then update small tag index 04925 // 04926 04927 } else if (IS_HEAP_TAGGING_ENABLED()) { 04928 04929 BusyBlock->SmallTagIndex = (UCHAR) 04930 RtlpUpdateTagEntry( Heap, 04931 BusyBlock->SmallTagIndex, 04932 BusyBlock->Size, 04933 AllocationIndex, 04934 ReAllocationAction ); 04935 } 04936 04937 // 04938 // Check if we will have any free space to give back. 04939 // 04940 04941 if (FreeSize == 0) { 04942 04943 // 04944 // No following free space so update the flags, size and byte counts 04945 // for the resized block. If the free block was a last entry 04946 // then the busy block must also now be a last entry. 04947 // 04948 04949 BusyBlock->Flags |= FreeFlags & HEAP_ENTRY_LAST_ENTRY; 04950 04951 BusyBlock->Size = (USHORT)AllocationIndex; 04952 04953 BusyBlock->UnusedBytes = (UCHAR) 04954 ((AllocationIndex << HEAP_GRANULARITY_SHIFT) - Size); 04955 04956 // 04957 // Update the previous size field of the following block if it exists 04958 // 04959 04960 if (!(FreeFlags & HEAP_ENTRY_LAST_ENTRY)) { 04961 04962 (BusyBlock + BusyBlock->Size)->PreviousSize = BusyBlock->Size; 04963 04964 } else { 04965 04966 PHEAP_SEGMENT Segment; 04967 04968 Segment = Heap->Segments[BusyBlock->SegmentIndex]; 04969 Segment->LastEntryInSegment = BusyBlock; 04970 } 04971 04972 // 04973 // Otherwise there is some free space to return to the heap 04974 // 04975 04976 } else { 04977 04978 // 04979 // Update the size and byte counts for the resized block. 04980 // 04981 04982 BusyBlock->Size = (USHORT)AllocationIndex; 04983 04984 BusyBlock->UnusedBytes = (UCHAR) 04985 ((AllocationIndex << HEAP_GRANULARITY_SHIFT) - Size); 04986 04987 // 04988 // Determine where the new free block starts and fill in its fields 04989 // 04990 04991 SplitBlock = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)BusyBlock + AllocationIndex); 04992 04993 SplitBlock->PreviousSize = (USHORT)AllocationIndex; 04994 04995 SplitBlock->SegmentIndex = BusyBlock->SegmentIndex; 04996 04997 // 04998 // If this new free block will be the last entry then update its 04999 // flags and size and put it into the appropriate free list 05000 // 05001 05002 if (FreeFlags & HEAP_ENTRY_LAST_ENTRY) { 05003 05004 PHEAP_SEGMENT Segment; 05005 05006 Segment = Heap->Segments[SplitBlock->SegmentIndex]; 05007 Segment->LastEntryInSegment = (PHEAP_ENTRY)SplitBlock; 05008 05009 SplitBlock->Flags = FreeFlags; 05010 SplitBlock->Size = (USHORT)FreeSize; 05011 05012 RtlpInsertFreeBlockDirect( Heap, SplitBlock, (USHORT)FreeSize ); 05013 05014 Heap->TotalFreeSize += FreeSize; 05015 05016 // 05017 // The free block is followed by another valid block 05018 // 05019 05020 } else { 05021 05022 // 05023 // Point to the block following our new free block 05024 // 05025 05026 SplitBlock2 = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize); 05027 05028 // 05029 // If the block following the new free block is busy then 05030 // update the flags and size for the new free block, update 05031 // the following blocks previous size, and put the free block 05032 // into the appropriate free list 05033 // 05034 05035 if (SplitBlock2->Flags & HEAP_ENTRY_BUSY) { 05036 05037 SplitBlock->Flags = FreeFlags & (~HEAP_ENTRY_LAST_ENTRY); 05038 SplitBlock->Size = (USHORT)FreeSize; 05039 05040 // 05041 // **** note that this test must be true because we are 05042 // **** already in the else clause of the 05043 // **** if (FreeFlags & HEAP_ENTRY_LAST_ENTRY) statement 05044 // 05045 05046 if (!(FreeFlags & HEAP_ENTRY_LAST_ENTRY)) { 05047 05048 ((PHEAP_ENTRY)SplitBlock + FreeSize)->PreviousSize = (USHORT)FreeSize; 05049 05050 } else { 05051 05052 PHEAP_SEGMENT Segment; 05053 05054 Segment = Heap->Segments[SplitBlock->SegmentIndex]; 05055 Segment->LastEntryInSegment = (PHEAP_ENTRY)SplitBlock; 05056 } 05057 05058 RtlpInsertFreeBlockDirect( Heap, SplitBlock, (USHORT)FreeSize ); 05059 05060 Heap->TotalFreeSize += FreeSize; 05061 05062 // 05063 // Otherwise the following block is also free so we can combine 05064 // these two blocks 05065 // 05066 05067 } else { 05068 05069 // 05070 // Remember the new free flags from the following block 05071 // 05072 05073 FreeFlags = SplitBlock2->Flags; 05074 05075 // 05076 // Remove the following block from its free list 05077 // 05078 05079 RtlpRemoveFreeBlock( Heap, SplitBlock2 ); 05080 05081 Heap->TotalFreeSize -= SplitBlock2->Size; 05082 05083 // 05084 // Calculate the size of the new combined free block 05085 // 05086 05087 FreeSize += SplitBlock2->Size; 05088 05089 // 05090 // Give the new the its new flags 05091 // 05092 05093 SplitBlock->Flags = FreeFlags; 05094 05095 // 05096 // If the combited block is not too large for the dedicated 05097 // free lists then that where we'll put it 05098 // 05099 05100 if (FreeSize <= HEAP_MAXIMUM_BLOCK_SIZE) { 05101 05102 SplitBlock->Size = (USHORT)FreeSize; 05103 05104 // 05105 // If present update the previous size for the following block 05106 // 05107 05108 if (!(FreeFlags & HEAP_ENTRY_LAST_ENTRY)) { 05109 05110 ((PHEAP_ENTRY)SplitBlock + FreeSize)->PreviousSize = (USHORT)FreeSize; 05111 05112 } else { 05113 05114 PHEAP_SEGMENT Segment; 05115 05116 Segment = Heap->Segments[SplitBlock->SegmentIndex]; 05117 Segment->LastEntryInSegment = (PHEAP_ENTRY)SplitBlock; 05118 } 05119 05120 // 05121 // Insert the new combined free block into the free list 05122 // 05123 05124 RtlpInsertFreeBlockDirect( Heap, SplitBlock, (USHORT)FreeSize ); 05125 05126 Heap->TotalFreeSize += FreeSize; 05127 05128 } else { 05129 05130 // 05131 // Otherwise the new free block is too large to go into 05132 // a dedicated free list so put it in the general free list 05133 // which might involve breaking it apart. 05134 // 05135 05136 RtlpInsertFreeBlock( Heap, SplitBlock, FreeSize ); 05137 } 05138 } 05139 } 05140 } 05141 05142 // 05143 // At this point the block has been resized and any extra space has been 05144 // returned to the free list 05145 // 05146 // Check if we should zero out the new space 05147 // 05148 05149 if (Flags & HEAP_ZERO_MEMORY) { 05150 05151 // 05152 // **** this test is sort of bogus because we're resizing and the new 05153 // **** size by definition must be larger than the old size 05154 // 05155 05156 if (Size > OldSize) { 05157 05158 RtlZeroMemory( (PCHAR)(BusyBlock + 1) + OldSize, 05159 Size - OldSize ); 05160 } 05161 05162 // 05163 // Check if we should be filling in heap after it as 05164 // been freed, and if so then fill in the newly allocated 05165 // space beyond the old bytes. 05166 // 05167 05168 } else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED) { 05169 05170 SIZE_T PartialBytes, ExtraSize; 05171 05172 PartialBytes = OldSize & (sizeof( ULONG ) - 1); 05173 05174 if (PartialBytes) { 05175 05176 PartialBytes = 4 - PartialBytes; 05177 } 05178 05179 if (Size > (OldSize + PartialBytes)) { 05180 05181 ExtraSize = (Size - (OldSize + PartialBytes)) & ~(sizeof( ULONG ) - 1); 05182 05183 if (ExtraSize != 0) { 05184 05185 RtlFillMemoryUlong( (PCHAR)(BusyBlock + 1) + OldSize + PartialBytes, 05186 ExtraSize, 05187 ALLOC_HEAP_FILL ); 05188 } 05189 } 05190 } 05191 05192 // 05193 // If we are going tailing checking then fill in the space right beyond 05194 // the new allocation 05195 // 05196 05197 if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED) { 05198 05199 RtlFillMemory( (PCHAR)(BusyBlock + 1) + Size, 05200 CHECK_HEAP_TAIL_SIZE, 05201 CHECK_HEAP_TAIL_FILL ); 05202 } 05203 05204 // 05205 // Give the resized block any user settable flags send in by the 05206 // caller 05207 // 05208 05209 BusyBlock->Flags &= ~HEAP_ENTRY_SETTABLE_FLAGS; 05210 BusyBlock->Flags |= ((Flags & HEAP_SETTABLE_USER_FLAGS) >> 4); 05211 05212 // 05213 // And return to our caller 05214 // 05215 05216 return TRUE; 05217 }

BOOLEAN RtlpHeapIsLocked IN PVOID  HeapHandle  ) 
 

Definition at line 6152 of file heapdll.c.

References HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, _HEAP_LOCK::Lock, _HEAP::LockVariable, NULL, and RtlpDebugPageHeapIsLocked().

Referenced by LdrShutdownProcess().

06158 : 06159 06160 This routine is used to determine if a heap is locked 06161 06162 Arguments: 06163 06164 HeapHandle - Supplies a pointer to the heap being queried 06165 06166 Return Value: 06167 06168 BOOLEAN - TRUE if the heap is locked and FALSE otherwise 06169 06170 --*/ 06171 06172 { 06173 PHEAP Heap; 06174 06175 // 06176 // Check if this is guard page version of heap 06177 // 06178 06179 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 06180 RtlpDebugPageHeapIsLocked( HeapHandle )); 06181 06182 Heap = (PHEAP)HeapHandle; 06183 06184 // 06185 // The heap is locked if there is a lock variable, and it has an 06186 // owning thread or the lockcount is not -1 06187 // 06188 06189 return (( Heap->LockVariable != NULL ) && 06190 ( Heap->LockVariable->Lock.CriticalSection.OwningThread || 06191 Heap->LockVariable->Lock.CriticalSection.LockCount != -1 )); 06192 }

VOID RtlpRemoveHeapFromProcessList IN PHEAP  Heap  ) 
 

Definition at line 4571 of file heapdll.c.

References _HEAP_LOCK::Lock, n, NULL, RtlAcquireLockRoutine, RtlpProcessHeapsListLock, RtlpUpdateHeapListIndex(), RtlReleaseLockRoutine, and USHORT.

Referenced by RtlDestroyHeap().

04577 : 04578 04579 This routine removes the specified heap to the heap list for the 04580 current process 04581 04582 Arguments: 04583 04584 Heap - Supplies a pointer to the heap being removed 04585 04586 Return Value: 04587 04588 None. 04589 04590 --*/ 04591 04592 { 04593 PPEB Peb = NtCurrentPeb(); 04594 PHEAP *p, *p1; 04595 ULONG n; 04596 04597 // 04598 // Lock the current processes heap list lock 04599 // 04600 04601 RtlAcquireLockRoutine( &RtlpProcessHeapsListLock.Lock ); 04602 04603 try { 04604 04605 // 04606 // We only want to the the work if the current process actually has some 04607 // heaps, the index stored in the heap is within the range for active 04608 // heaps. Note that the heaps stored index is bias by one. 04609 // 04610 04611 if ((Peb->NumberOfHeaps != 0) && 04612 (Heap->ProcessHeapsListIndex != 0) && 04613 (Heap->ProcessHeapsListIndex <= Peb->NumberOfHeaps)) { 04614 04615 // 04616 // Establish a pointer into the array of process heaps at the 04617 // current heap location and one beyond 04618 // 04619 04620 p = (PHEAP *)&Peb->ProcessHeaps[ Heap->ProcessHeapsListIndex - 1 ]; 04621 04622 p1 = p + 1; 04623 04624 // 04625 // Calculate the number of heaps that exist beyond the current 04626 // heap in the array including the current heap location 04627 // 04628 04629 n = Peb->NumberOfHeaps - (Heap->ProcessHeapsListIndex - 1); 04630 04631 // 04632 // For every heap beyond the current one that we are removing 04633 // we'll move that heap down to the previous index. 04634 // 04635 04636 while (--n) { 04637 04638 // 04639 // Copy the heap process array entry of the next entry to 04640 // the current entry, and move p1 to the next next entry 04641 // 04642 04643 *p = *p1++; 04644 04645 // 04646 // This is simply a debugging call 04647 // 04648 04649 RtlpUpdateHeapListIndex( (*p)->ProcessHeapsListIndex, 04650 (USHORT)((*p)->ProcessHeapsListIndex - 1)); 04651 04652 // 04653 // Assign the moved heap its new heap index 04654 // 04655 04656 (*p)->ProcessHeapsListIndex -= 1; 04657 04658 // 04659 // Move on to the next heap entry 04660 // 04661 04662 p += 1; 04663 } 04664 04665 // 04666 // Zero out the last process heap pointer, update the count, and 04667 // make the heap we just removed realize it has been removed by 04668 // zeroing out its process heap list index 04669 // 04670 04671 Peb->ProcessHeaps[ --Peb->NumberOfHeaps ] = NULL; 04672 Heap->ProcessHeapsListIndex = 0; 04673 } 04674 04675 } finally { 04676 04677 // 04678 // Unlock the current processes heap list lock 04679 // 04680 04681 RtlReleaseLockRoutine( &RtlpProcessHeapsListLock.Lock ); 04682 } 04683 04684 return; 04685 }

VOID RtlpResetTags PHEAP  Heap  ) 
 

Definition at line 5802 of file heapdll.c.

References _HEAP_TAG_ENTRY::Allocs, _HEAP_PSEUDO_TAG_ENTRY::Allocs, _HEAP_TAG_ENTRY::Frees, _HEAP_PSEUDO_TAG_ENTRY::Frees, HEAP_NUMBER_OF_PSEUDO_TAG, _HEAP::NextAvailableTagIndex, NULL, _HEAP::PseudoTagEntries, _HEAP_TAG_ENTRY::Size, _HEAP_PSEUDO_TAG_ENTRY::Size, and _HEAP::TagEntries.

05808 : 05809 05810 This routine is used to reset all the tag entries in a heap 05811 05812 Arguments: 05813 05814 Heap - Supplies a pointer to the heap being modified 05815 05816 Return Value: 05817 05818 None. 05819 05820 --*/ 05821 05822 { 05823 PHEAP_TAG_ENTRY TagEntry; 05824 PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntry; 05825 ULONG i; 05826 05827 // 05828 // We only have work to do if the heap has any allocated tag entries 05829 // 05830 05831 TagEntry = Heap->TagEntries; 05832 05833 if (TagEntry != NULL) { 05834 05835 // 05836 // For every tag entry in the heap we will zero out its counters 05837 // 05838 05839 for (i=0; i<Heap->NextAvailableTagIndex; i++) { 05840 05841 TagEntry->Allocs = 0; 05842 TagEntry->Frees = 0; 05843 TagEntry->Size = 0; 05844 05845 // 05846 // Advance to the next tag entry 05847 // 05848 05849 TagEntry += 1; 05850 } 05851 } 05852 05853 // 05854 // We will only reset the pseudo tags if they exist 05855 // 05856 05857 PseudoTagEntry = Heap->PseudoTagEntries; 05858 05859 if (PseudoTagEntry != NULL) { 05860 05861 // 05862 // For every pseudo tag entry in the heap we will zero out its 05863 // counters 05864 // 05865 05866 for (i=0; i<HEAP_NUMBER_OF_PSEUDO_TAG; i++) { 05867 05868 PseudoTagEntry->Allocs = 0; 05869 PseudoTagEntry->Frees = 0; 05870 PseudoTagEntry->Size = 0; 05871 05872 // 05873 // Advance to the next pseudo tag entry 05874 // 05875 05876 PseudoTagEntry += 1; 05877 } 05878 } 05879 05880 // 05881 // And return to our caller 05882 // 05883 05884 return; 05885 }

VOID RtlProtectHeap IN PVOID  HeapHandle,
IN BOOLEAN  MakeReadOnly
 

Definition at line 258 of file heapdll.c.

References _HEAP_SEGMENT::BaseAddress, HEAP_MAXIMUM_SEGMENTS, HeapDebugPrint, HeapHandle, _HEAP_SEGMENT::LastValidEntry, NT_SUCCESS, NTSTATUS(), NULL, _HEAP::Segments, Size, and Status.

00265 : 00266 00267 This routine will change the protection on all the pages in a heap 00268 to be either readonly or readwrite 00269 00270 Arguments: 00271 00272 HeapHandle - Supplies a pointer to the heap being altered 00273 00274 MakeReadOnly - Specifies if the heap is to be made readonly or 00275 readwrite 00276 00277 Return Value: 00278 00279 None. 00280 00281 --*/ 00282 00283 { 00284 PHEAP Heap; 00285 UCHAR SegmentIndex; 00286 PHEAP_SEGMENT Segment; 00287 MEMORY_BASIC_INFORMATION VaInfo; 00288 NTSTATUS Status; 00289 PVOID Address; 00290 PVOID ProtectAddress; 00291 SIZE_T Size; 00292 ULONG OldProtect; 00293 ULONG NewProtect; 00294 00295 Heap = (PHEAP)HeapHandle; 00296 00297 // 00298 // For every valid segment in the heap we will zoom through all its 00299 // regions and for those that are committed we'll change it protection 00300 // 00301 00302 for (SegmentIndex=0; SegmentIndex<HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) { 00303 00304 Segment = Heap->Segments[ SegmentIndex ]; 00305 00306 if ( Segment ) { 00307 00308 // 00309 // Starting from the first address for the segment and going to 00310 // the last address in the segment we'll step through by regions 00311 // 00312 00313 Address = Segment->BaseAddress; 00314 00315 while ((ULONG_PTR)Address < (ULONG_PTR)(Segment->LastValidEntry)) { 00316 00317 // 00318 // Query the current region to get its state and size 00319 // 00320 00321 Status = ZwQueryVirtualMemory( NtCurrentProcess(), 00322 Address, 00323 MemoryBasicInformation, 00324 &VaInfo, 00325 sizeof(VaInfo), 00326 NULL ); 00327 00328 if (!NT_SUCCESS( Status )) { 00329 00330 HeapDebugPrint(( "VirtualQuery Failed 0x%08x %x\n", Address, Status )); 00331 00332 return; 00333 } 00334 00335 // 00336 // If we found a commited block then set its protection 00337 // 00338 00339 if (VaInfo.State == MEM_COMMIT) { 00340 00341 Size = VaInfo.RegionSize; 00342 00343 ProtectAddress = Address; 00344 00345 if (MakeReadOnly) { 00346 00347 NewProtect = PAGE_READONLY; 00348 00349 } else { 00350 00351 NewProtect = PAGE_READWRITE; 00352 } 00353 00354 Status = ZwProtectVirtualMemory( NtCurrentProcess(), 00355 &ProtectAddress, 00356 &Size, 00357 NewProtect, 00358 &OldProtect ); 00359 00360 if (!NT_SUCCESS( Status )) { 00361 00362 HeapDebugPrint(( "VirtualProtect Failed 0x%08x %x\n", Address, Status )); 00363 00364 return; 00365 } 00366 } 00367 00368 // 00369 // Now calculate the address of the next region in the segment 00370 // 00371 00372 Address = (PVOID)((PCHAR)Address + VaInfo.RegionSize); 00373 } 00374 } 00375 } 00376 00377 // 00378 // And return to our caller 00379 // 00380 00381 return; 00382 }

USHORT RtlpUpdateTagEntry PHEAP  Heap,
USHORT  TagIndex,
SIZE_T  OldSize,
SIZE_T  NewSize,
HEAP_TAG_ACTION  Action
 

Definition at line 5554 of file heapdll.c.

References Action, _HEAP_TAG_ENTRY::Allocs, FreeAction, _HEAP_TAG_ENTRY::Frees, HEAP_MAXIMUM_FREELISTS, HEAP_NUMBER_OF_PSEUDO_TAG, HEAP_TAG_ACTION, _HEAP::NextAvailableTagIndex, NULL, _HEAP::PseudoTagEntries, ReAllocationAction, RtlpGlobalTagHeap, _HEAP_TAG_ENTRY::Size, _HEAP::TagEntries, USHORT, VirtualAllocationAction, and VirtualReAllocationAction.

Referenced by RtlAllocateHeapSlowly(), RtlFreeHeapSlowly(), RtlpGrowBlockInPlace(), and RtlReAllocateHeap().

05564 : 05565 05566 This routine is used to modify a tag entry 05567 05568 Arguments: 05569 05570 Heap - Supplies a pointer to the heap being modified 05571 05572 TagIndex - Supplies the tag being modified 05573 05574 OldSize - Supplies the old allocation index of the block associated with the tag 05575 05576 NewSize - Supplies the new allocation index of the block associated with the tag 05577 05578 Action - Supplies the type of action being performed on the heap tag 05579 05580 Return Value: 05581 05582 USHORT - Returns a tag index for the newly updated tag 05583 05584 --*/ 05585 05586 { 05587 PHEAP_TAG_ENTRY TagEntry; 05588 05589 // 05590 // If the processes tag heap does not exist then we'll return a zero index 05591 // right away 05592 // 05593 05594 if (RtlpGlobalTagHeap == NULL) { 05595 05596 return 0; 05597 } 05598 05599 // 05600 // If the action is greater than or equal to free action then it is 05601 // either FreeAction, VirtualFreeAction, ReAllocationAction, or 05602 // VirtualReAllocationAction. Which means we already should have a tag 05603 // that is simply being modified 05604 // 05605 05606 if (Action >= FreeAction) { 05607 05608 // 05609 // If the tag index is zero then there is nothing for us to do 05610 // 05611 05612 if (TagIndex == 0) { 05613 05614 return 0; 05615 } 05616 05617 // 05618 // If this is a pseudo tag then make sure the rest of the tag index 05619 // after we remove the psuedo bit is valid and that the heap is 05620 // actually maintaining pseudo tags 05621 // 05622 05623 if (TagIndex & HEAP_PSEUDO_TAG_FLAG) { 05624 05625 TagIndex &= ~HEAP_PSEUDO_TAG_FLAG; 05626 05627 if ((TagIndex < HEAP_NUMBER_OF_PSEUDO_TAG) && 05628 (Heap->PseudoTagEntries != NULL)) { 05629 05630 TagEntry = (PHEAP_TAG_ENTRY)(Heap->PseudoTagEntries + TagIndex); 05631 05632 TagIndex |= HEAP_PSEUDO_TAG_FLAG; 05633 05634 } else { 05635 05636 return 0; 05637 } 05638 05639 // 05640 // Otherwise if this is a global tag then make sure the tag index 05641 // after we remove the global bit is valid and that the global tag 05642 // heap has some tag entries 05643 // 05644 05645 } else if (TagIndex & HEAP_GLOBAL_TAG) { 05646 05647 TagIndex &= ~HEAP_GLOBAL_TAG; 05648 05649 if ((TagIndex < RtlpGlobalTagHeap->NextAvailableTagIndex) && 05650 (RtlpGlobalTagHeap->TagEntries != NULL)) { 05651 05652 TagEntry = &RtlpGlobalTagHeap->TagEntries[ TagIndex ]; 05653 05654 TagIndex |= HEAP_GLOBAL_TAG; 05655 05656 } else { 05657 05658 return 0; 05659 } 05660 05661 // 05662 // Otherwise we have a regular tag index that we need to make sure 05663 // is a valid value and that the heap has some tag entries 05664 // 05665 05666 } else if ((TagIndex < Heap->NextAvailableTagIndex) && 05667 (Heap->TagEntries != NULL)) { 05668 05669 TagEntry = &Heap->TagEntries[ TagIndex ]; 05670 05671 } else { 05672 05673 return 0; 05674 } 05675 05676 // 05677 // At this point we have a tag entry and tag index. Increment the 05678 // number of frees we've done on the tag, and decrement the size by 05679 // the number of bytes we've just freed 05680 // 05681 05682 TagEntry->Frees += 1; 05683 05684 TagEntry->Size -= OldSize; 05685 05686 // 05687 // Now if the action is either ReAllocationAction or 05688 // VirtualReAllocationAction. Then we get to add back in the 05689 // new size and the allocation count 05690 // 05691 05692 if (Action >= ReAllocationAction) { 05693 05694 // 05695 // If the this is a pseudo tag then we tag entry goes off the 05696 // pseudo tag list 05697 // 05698 05699 if (TagIndex & HEAP_PSEUDO_TAG_FLAG) { 05700 05701 TagIndex = (USHORT)(NewSize < HEAP_MAXIMUM_FREELISTS ? 05702 NewSize : 05703 (Action == VirtualReAllocationAction ? HEAP_MAXIMUM_FREELISTS : 0)); 05704 05705 TagEntry = (PHEAP_TAG_ENTRY)(Heap->PseudoTagEntries + TagIndex); 05706 05707 TagIndex |= HEAP_PSEUDO_TAG_FLAG; 05708 } 05709 05710 TagEntry->Allocs += 1; 05711 05712 TagEntry->Size += NewSize; 05713 } 05714 05715 // 05716 // The action is either AllocationAction or VirtualAllocationAction 05717 // 05718 05719 } else { 05720 05721 // 05722 // Check if the supplied tag index is a regular tag and that it is 05723 // valid for the tags in this heap 05724 // 05725 05726 if ((TagIndex != 0) && 05727 (TagIndex < Heap->NextAvailableTagIndex) && 05728 (Heap->TagEntries != NULL)) { 05729 05730 TagEntry = &Heap->TagEntries[ TagIndex ]; 05731 05732 // 05733 // Otherwise if this is a global tag then make sure that it is a 05734 // valid global index 05735 // 05736 05737 } else if (TagIndex & HEAP_GLOBAL_TAG) { 05738 05739 TagIndex &= ~HEAP_GLOBAL_TAG; 05740 05741 Heap = RtlpGlobalTagHeap; 05742 05743 if ((TagIndex < Heap->NextAvailableTagIndex) && 05744 (Heap->TagEntries != NULL)) { 05745 05746 TagEntry = &Heap->TagEntries[ TagIndex ]; 05747 05748 TagIndex |= HEAP_GLOBAL_TAG; 05749 05750 } else { 05751 05752 return 0; 05753 } 05754 05755 // 05756 // Otherwise if this is a pseudo tag then build a valid tag index 05757 // based on the new size of the allocation 05758 // 05759 05760 } else if (Heap->PseudoTagEntries != NULL) { 05761 05762 TagIndex = (USHORT)(NewSize < HEAP_MAXIMUM_FREELISTS ? 05763 NewSize : 05764 (Action == VirtualAllocationAction ? HEAP_MAXIMUM_FREELISTS : 0)); 05765 05766 TagEntry = (PHEAP_TAG_ENTRY)(Heap->PseudoTagEntries + TagIndex); 05767 05768 TagIndex |= HEAP_PSEUDO_TAG_FLAG; 05769 05770 // 05771 // Otherwise the user didn't call us with a valid tag 05772 // 05773 05774 } else { 05775 05776 return 0; 05777 } 05778 05779 // 05780 // At this point we have a valid tag entry and tag index, so 05781 // update the tag entry state to reflect this new allocation 05782 // 05783 05784 TagEntry->Allocs += 1; 05785 05786 TagEntry->Size += NewSize; 05787 } 05788 05789 // 05790 // And return to our caller with the new tag index 05791 // 05792 05793 return TagIndex; 05794 }

PWSTR RtlQueryTagHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN USHORT  TagIndex,
IN BOOLEAN  ResetCounters,
OUT PRTL_HEAP_TAG_INFO TagInfo  OPTIONAL
 

Definition at line 1919 of file heapdll.c.

References _HEAP_TAG_ENTRY::Allocs, DEBUG_HEAP, FALSE, _HEAP::ForceFlags, _HEAP_TAG_ENTRY::Frees, HEAP_GRANULARITY_SHIFT, HEAP_NUMBER_OF_PSEUDO_TAG, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, IS_HEAP_TAGGING_ENABLED, L, _HEAP::LockVariable, _HEAP::NextAvailableTagIndex, NULL, _HEAP::PseudoTagEntries, RtlAcquireLockRoutine, RtlDebugQueryTagHeap(), RtlReleaseLockRoutine, _HEAP_TAG_ENTRY::Size, _HEAP::TagEntries, _HEAP_TAG_ENTRY::TagName, and TRUE.

Referenced by RtlDebugQueryTagHeap().

01929 : 01930 01931 This routine returns the name and optional statistics for a given 01932 tag index. 01933 01934 Arguments: 01935 01936 **** note that some of the code looks like it can handle the 01937 **** global tag heap but other places look rather wrong 01938 01939 HeapHandle - Specifies the heap being queried. If null then the 01940 global tag heap is used. 01941 01942 Flags - Supplies a set flags to augment those enforced by the 01943 heap 01944 01945 TagIndex - Specifies the tag index that we want to query 01946 01947 ResetCounter - Specifies if this routine should reset the counter 01948 for the tag after the query 01949 01950 TagInfo - Optionally supplies storage where the output tag information 01951 should be stored 01952 01953 Return Value: 01954 01955 PWSTR - Returns a pointer to the tag name or NULL if the index 01956 doesn't exist 01957 01958 --*/ 01959 01960 { 01961 PHEAP Heap = (PHEAP)HeapHandle; 01962 BOOLEAN LockAcquired = FALSE; 01963 PHEAP_TAG_ENTRY TagEntry; 01964 PWSTR Result; 01965 01966 // 01967 // Tagging is not part of the guard page heap package 01968 // 01969 01970 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, NULL ); 01971 01972 // 01973 // Check if tagging is disabled 01974 // 01975 01976 if (!IS_HEAP_TAGGING_ENABLED()) { 01977 01978 return NULL; 01979 } 01980 01981 try { 01982 01983 // 01984 // Check if the caller has given us a heap to query 01985 // 01986 01987 if (Heap != NULL) { 01988 01989 // 01990 // Check if we should be using the debug version of the 01991 // heap package 01992 // 01993 01994 if (DEBUG_HEAP( Flags )) { 01995 01996 Result = RtlDebugQueryTagHeap( HeapHandle, Flags, TagIndex, ResetCounters, TagInfo ); 01997 leave; 01998 } 01999 02000 // 02001 // Lock the heap 02002 // 02003 02004 Flags |= Heap->ForceFlags; 02005 02006 if (!(Flags & HEAP_NO_SERIALIZE)) { 02007 02008 RtlAcquireLockRoutine( Heap->LockVariable ); 02009 02010 LockAcquired = TRUE; 02011 } 02012 } 02013 02014 Result = NULL; 02015 02016 // 02017 // **** note that the next test assumes that heap is not null 02018 // 02019 // Check that the specified tag index is valid and that the 02020 // this heap does actually have some tag entries 02021 // 02022 02023 if ((TagIndex < Heap->NextAvailableTagIndex) && 02024 (Heap->TagEntries != NULL)) { 02025 02026 // 02027 // Stride over to the specific tag entry and if the caller gave us 02028 // an output buffer then fill in the details 02029 // 02030 02031 TagEntry = Heap->TagEntries + TagIndex; 02032 02033 if (ARGUMENT_PRESENT( TagInfo )) { 02034 02035 TagInfo->NumberOfAllocations = TagEntry->Allocs; 02036 TagInfo->NumberOfFrees = TagEntry->Frees; 02037 TagInfo->BytesAllocated = TagEntry->Size << HEAP_GRANULARITY_SHIFT; 02038 } 02039 02040 // 02041 // Check if we should reset the counters 02042 // 02043 02044 if (ResetCounters) { 02045 02046 TagEntry->Allocs = 0; 02047 TagEntry->Frees = 0; 02048 TagEntry->Size = 0; 02049 } 02050 02051 // 02052 // Point to the tag name 02053 // 02054 02055 Result = &TagEntry->TagName[ 0 ]; 02056 02057 // 02058 // If the tag index has the psuedo tag bit set then recalulate the 02059 // tag index and if this heap has pseudo tags than that is what 02060 // we'll return 02061 // 02062 02063 } else if (TagIndex & HEAP_PSEUDO_TAG_FLAG) { 02064 02065 // 02066 // Clear the bit 02067 // 02068 02069 TagIndex ^= HEAP_PSEUDO_TAG_FLAG; 02070 02071 if ((TagIndex < HEAP_NUMBER_OF_PSEUDO_TAG) && 02072 (Heap->PseudoTagEntries != NULL)) { 02073 02074 // 02075 // Stride over to the specific pseudo tag entry and if the 02076 // caller gave us an output buffer then fill in the details 02077 // 02078 02079 TagEntry = (PHEAP_TAG_ENTRY)(Heap->PseudoTagEntries + TagIndex); 02080 02081 if (ARGUMENT_PRESENT( TagInfo )) { 02082 02083 TagInfo->NumberOfAllocations = TagEntry->Allocs; 02084 TagInfo->NumberOfFrees = TagEntry->Frees; 02085 TagInfo->BytesAllocated = TagEntry->Size << HEAP_GRANULARITY_SHIFT; 02086 } 02087 02088 // 02089 // Check if we should reset the counters 02090 // 02091 02092 if (ResetCounters) { 02093 02094 TagEntry->Allocs = 0; 02095 TagEntry->Frees = 0; 02096 TagEntry->Size = 0; 02097 } 02098 02099 // 02100 // Pseudo tags do not have names 02101 // 02102 02103 Result = L""; 02104 } 02105 } 02106 02107 } finally { 02108 02109 // 02110 // Unlock the heap 02111 // 02112 02113 if (LockAcquired) { 02114 02115 RtlReleaseLockRoutine( Heap->LockVariable ); 02116 } 02117 } 02118 02119 // 02120 // And return the tag name to our caller 02121 // 02122 02123 return Result; 02124 }

PVOID RtlReAllocateHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress,
IN SIZE_T  Size
 

Definition at line 518 of file heapdll.c.

References _HEAP::AlignMask, _HEAP::AlignRound, ALLOC_HEAP_FILL, CHECK_HEAP_TAIL_FILL, CHECK_HEAP_TAIL_SIZE, _HEAP_VIRTUAL_ALLOC_ENTRY::CommitSize, DEBUG_HEAP, EXCEPTION_CONTINUE_SEARCH, EXCEPTION_EXECUTE_HANDLER, _HEAP_VIRTUAL_ALLOC_ENTRY::ExtraStuff, FALSE, _HEAP_FREE_ENTRY::Flags, _HEAP_ENTRY::Flags, _HEAP::Flags, _HEAP::ForceFlags, HEAP_ENTRY_BUSY, HEAP_ENTRY_EXTRA_PRESENT, HEAP_ENTRY_LAST_ENTRY, HEAP_ENTRY_SETTABLE_FLAGS, HEAP_ENTRY_VIRTUAL_ALLOC, HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_BLOCK_SIZE, HEAP_NEED_EXTRA_FLAGS, HeapDebugBreak, HeapDebugPrint, HeapHandle, IS_HEAP_TAGGING_ENABLED, _HEAP_SEGMENT::LastEntryInSegment, _HEAP::LockVariable, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, _HEAP_FREE_ENTRY::PreviousSize, _HEAP::PseudoTagEntries, ReAllocationAction, ROUND_UP_TO_POWER2, RtlAcquireLockRoutine, RtlAllocateHeap, RtlDebugReAllocateHeap(), RtlFreeHeap, RtlpGetExtraStuffPointer(), RtlpGetSizeOfBigBlock(), RtlpGrowBlockInPlace(), RtlpInsertFreeBlock(), RtlpInsertFreeBlockDirect, RtlpRemoveFreeBlock, RtlpUpdateTagEntry(), RtlRaiseException(), RtlReleaseLockRoutine, _HEAP_ENTRY::SegmentIndex, _HEAP_FREE_ENTRY::SegmentIndex, _HEAP::Segments, SET_LAST_STATUS, _HEAP_ENTRY_EXTRA::Settable, _HEAP_FREE_ENTRY::Size, _HEAP_ENTRY::Size, Size, _HEAP_ENTRY::SmallTagIndex, Status, _HEAP_ENTRY_EXTRA::TagIndex, _HEAP::TotalFreeSize, TRUE, _HEAP_ENTRY::UnusedBytes, USHORT, and VirtualReAllocationAction.

Referenced by LdrpDphSnapImports(), LdrpSetAlternateResourceModuleHandle(), LdrUnloadAlternateResourceModule(), main(), and RtlDebugReAllocateHeap().

00527 : 00528 00529 This routine will resize a user specified heap block. The new size 00530 can either be smaller or larger than the current block size. 00531 00532 Arguments: 00533 00534 HeapHandle - Supplies a pointer to the heap being modified 00535 00536 Flags - Supplies a set of heap flags to augment those already 00537 enforced by the heap 00538 00539 BaseAddress - Supplies the current address of a block allocated 00540 from heap. We will try and resize this block at its current 00541 address, but it could possibly move if this heap structure 00542 allows for relocation 00543 00544 Size - Supplies the size, in bytes, for the newly resized heap 00545 block 00546 00547 Return Value: 00548 00549 PVOID - A pointer to the resized block. If the block had to move 00550 then this address will not be equal to the input base address 00551 00552 --*/ 00553 00554 { 00555 PHEAP Heap = (PHEAP)HeapHandle; 00556 SIZE_T AllocationSize; 00557 PHEAP_ENTRY BusyBlock, NewBusyBlock; 00558 PHEAP_ENTRY_EXTRA OldExtraStuff, NewExtraStuff; 00559 SIZE_T FreeSize; 00560 BOOLEAN LockAcquired = FALSE; 00561 PVOID NewBaseAddress; 00562 PHEAP_FREE_ENTRY SplitBlock, SplitBlock2; 00563 SIZE_T OldSize; 00564 SIZE_T AllocationIndex; 00565 SIZE_T OldAllocationIndex; 00566 UCHAR FreeFlags; 00567 NTSTATUS Status; 00568 PVOID DeCommitAddress; 00569 SIZE_T DeCommitSize; 00570 EXCEPTION_RECORD ExceptionRecord; 00571 00572 // 00573 // If there isn't an address to relocate the heap at then our work is done 00574 // 00575 00576 if (BaseAddress == NULL) { 00577 00578 SET_LAST_STATUS( STATUS_SUCCESS ); 00579 00580 return NULL; 00581 } 00582 00583 #ifdef NTHEAP_ENABLED 00584 { 00585 if (Heap->Flags & NTHEAP_ENABLED_FLAG) { 00586 00587 return RtlReAllocateNtHeap( HeapHandle, Flags, BaseAddress, Size ); 00588 } 00589 } 00590 #endif // NTHEAP_ENABLED 00591 00592 // 00593 // Augment the heap flags 00594 // 00595 00596 Flags |= Heap->ForceFlags; 00597 00598 // 00599 // Check if we should simply call the debug version of heap to do the work 00600 // 00601 00602 if (DEBUG_HEAP( Flags)) { 00603 00604 return RtlDebugReAllocateHeap( HeapHandle, Flags, BaseAddress, Size ); 00605 } 00606 00607 // 00608 // Make sure we didn't get a negative heap size 00609 // 00610 00611 if (Size > 0x7fffffff) { 00612 00613 SET_LAST_STATUS( STATUS_NO_MEMORY ); 00614 00615 return NULL; 00616 } 00617 00618 // 00619 // Round the requested size up to the allocation granularity. Note 00620 // that if the request is for 0 bytes, we still allocate memory, because 00621 // we add in an extra byte to protect ourselves from idiots. 00622 // 00623 00624 AllocationSize = ((Size ? Size : 1) + Heap->AlignRound) & Heap->AlignMask; 00625 00626 if ((Flags & HEAP_NEED_EXTRA_FLAGS) || 00627 (Heap->PseudoTagEntries != NULL) || 00628 ((((PHEAP_ENTRY)BaseAddress)-1)->Flags & HEAP_ENTRY_EXTRA_PRESENT)) { 00629 00630 AllocationSize += sizeof( HEAP_ENTRY_EXTRA ); 00631 } 00632 00633 try { 00634 00635 // 00636 // Lock the heap 00637 // 00638 00639 if (!(Flags & HEAP_NO_SERIALIZE)) { 00640 00641 RtlAcquireLockRoutine( Heap->LockVariable ); 00642 00643 LockAcquired = TRUE; 00644 00645 // 00646 // Because it is now zero the following statement will set the no 00647 // serialize bit 00648 // 00649 00650 Flags ^= HEAP_NO_SERIALIZE; 00651 } 00652 00653 try { 00654 00655 // 00656 // Compute the heap block address for user specified block 00657 // 00658 00659 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 00660 00661 // 00662 // Check if the block is not in use then it is an error 00663 // 00664 00665 if (!(BusyBlock->Flags & HEAP_ENTRY_BUSY)) { 00666 00667 SET_LAST_STATUS( STATUS_INVALID_PARAMETER ); 00668 00669 // 00670 // Bail if not a busy block. 00671 // 00672 00673 leave; 00674 00675 // 00676 // We need the current (i.e., old) size and allocation of the 00677 // block. Check if the block is a big allocation. The size 00678 // field of a big block is really the unused by count 00679 // 00680 00681 } else if (BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) { 00682 00683 OldSize = RtlpGetSizeOfBigBlock( BusyBlock ); 00684 00685 OldAllocationIndex = (OldSize + BusyBlock->Size) >> HEAP_GRANULARITY_SHIFT; 00686 00687 // 00688 // We'll need to adjust the new allocation size to account 00689 // for the big block header and then round it up to a page 00690 // 00691 00692 AllocationSize += FIELD_OFFSET( HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock ); 00693 AllocationSize = ROUND_UP_TO_POWER2( AllocationSize, PAGE_SIZE ); 00694 00695 // 00696 // Otherwise the block is in use and is a small allocation 00697 // 00698 00699 } else { 00700 00701 OldAllocationIndex = BusyBlock->Size; 00702 00703 OldSize = (OldAllocationIndex << HEAP_GRANULARITY_SHIFT) - 00704 BusyBlock->UnusedBytes; 00705 } 00706 00707 // 00708 // Compute the new allocation index 00709 // 00710 00711 AllocationIndex = AllocationSize >> HEAP_GRANULARITY_SHIFT; 00712 00713 // 00714 // At this point we have the old size and index, and the new size 00715 // and index 00716 // 00717 // See if new size less than or equal to the current size. 00718 // 00719 00720 if (AllocationIndex <= OldAllocationIndex) { 00721 00722 // 00723 // If the new allocation index is only one less then the current 00724 // index then make the sizes equal 00725 // 00726 00727 if (AllocationIndex + 1 == OldAllocationIndex) { 00728 00729 AllocationIndex += 1; 00730 AllocationSize += sizeof( HEAP_ENTRY ); 00731 } 00732 00733 // 00734 // Calculate new residual (unused) amount 00735 // 00736 00737 if (BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) { 00738 00739 // 00740 // In a big block the size is really the unused byte count 00741 // 00742 00743 BusyBlock->Size = (USHORT)(AllocationSize - Size); 00744 00745 } else if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 00746 00747 // 00748 // The extra stuff struct goes after the data. So compute 00749 // the old and new extra stuff location and copy the data 00750 // 00751 00752 OldExtraStuff = (PHEAP_ENTRY_EXTRA)(BusyBlock + BusyBlock->Size - 1); 00753 00754 NewExtraStuff = (PHEAP_ENTRY_EXTRA)(BusyBlock + AllocationIndex - 1); 00755 00756 *NewExtraStuff = *OldExtraStuff; 00757 00758 // 00759 // If we're doing heap tagging then update the tag entry 00760 // 00761 00762 if (IS_HEAP_TAGGING_ENABLED()) { 00763 00764 NewExtraStuff->TagIndex = 00765 RtlpUpdateTagEntry( Heap, 00766 NewExtraStuff->TagIndex, 00767 OldAllocationIndex, 00768 AllocationIndex, 00769 ReAllocationAction ); 00770 } 00771 00772 BusyBlock->UnusedBytes = (UCHAR)(AllocationSize - Size); 00773 00774 } else { 00775 00776 // 00777 // If we're doing heap tagging then update the tag entry 00778 // 00779 00780 if (IS_HEAP_TAGGING_ENABLED()) { 00781 00782 BusyBlock->SmallTagIndex = (UCHAR) 00783 RtlpUpdateTagEntry( Heap, 00784 BusyBlock->SmallTagIndex, 00785 BusyBlock->Size, 00786 AllocationIndex, 00787 ReAllocationAction ); 00788 } 00789 00790 BusyBlock->UnusedBytes = (UCHAR)(AllocationSize - Size); 00791 } 00792 00793 // 00794 // Check if the block is getting bigger, then fill in the extra 00795 // space. 00796 // 00797 // **** how can this happen if the allocation index is less than or 00798 // **** equal to the old allocation index 00799 // 00800 00801 if (Size > OldSize) { 00802 00803 // 00804 // See if we should zero the extra space 00805 // 00806 00807 if (Flags & HEAP_ZERO_MEMORY) { 00808 00809 RtlZeroMemory( (PCHAR)BaseAddress + OldSize, 00810 Size - OldSize ); 00811 00812 // 00813 // Otherwise see if we should fill the extra space 00814 // 00815 00816 } else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED) { 00817 00818 SIZE_T PartialBytes, ExtraSize; 00819 00820 PartialBytes = OldSize & (sizeof( ULONG ) - 1); 00821 00822 if (PartialBytes) { 00823 00824 PartialBytes = 4 - PartialBytes; 00825 } 00826 00827 if (Size > (OldSize + PartialBytes)) { 00828 00829 ExtraSize = (Size - (OldSize + PartialBytes)) & ~(sizeof( ULONG ) - 1); 00830 00831 if (ExtraSize != 0) { 00832 00833 RtlFillMemoryUlong( (PCHAR)(BusyBlock + 1) + OldSize + PartialBytes, 00834 ExtraSize, 00835 ALLOC_HEAP_FILL ); 00836 } 00837 } 00838 } 00839 } 00840 00841 if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED) { 00842 00843 RtlFillMemory( (PCHAR)(BusyBlock + 1) + Size, 00844 CHECK_HEAP_TAIL_SIZE, 00845 CHECK_HEAP_TAIL_FILL ); 00846 } 00847 00848 // 00849 // If amount of change is greater than the size of a free block, 00850 // then need to free the extra space. Otherwise, nothing else to 00851 // do. 00852 // 00853 00854 if (AllocationIndex != OldAllocationIndex) { 00855 00856 FreeFlags = BusyBlock->Flags & ~HEAP_ENTRY_BUSY; 00857 00858 if (FreeFlags & HEAP_ENTRY_VIRTUAL_ALLOC) { 00859 00860 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock; 00861 00862 VirtualAllocBlock = CONTAINING_RECORD( BusyBlock, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock ); 00863 00864 if (IS_HEAP_TAGGING_ENABLED()) { 00865 00866 VirtualAllocBlock->ExtraStuff.TagIndex = 00867 RtlpUpdateTagEntry( Heap, 00868 VirtualAllocBlock->ExtraStuff.TagIndex, 00869 OldAllocationIndex, 00870 AllocationIndex, 00871 VirtualReAllocationAction ); 00872 } 00873 00874 DeCommitAddress = (PCHAR)VirtualAllocBlock + AllocationSize; 00875 00876 DeCommitSize = (OldAllocationIndex << HEAP_GRANULARITY_SHIFT) - 00877 AllocationSize; 00878 00879 Status = ZwFreeVirtualMemory( NtCurrentProcess(), 00880 (PVOID *)&DeCommitAddress, 00881 &DeCommitSize, 00882 MEM_RELEASE ); 00883 00884 if (!NT_SUCCESS( Status )) { 00885 00886 HeapDebugPrint(( "Unable to release memory at %p for %p bytes - Status == %x\n", 00887 DeCommitAddress, DeCommitSize, Status )); 00888 00889 HeapDebugBreak( NULL ); 00890 00891 } else { 00892 00893 VirtualAllocBlock->CommitSize -= DeCommitSize; 00894 } 00895 00896 } else { 00897 00898 // 00899 // Otherwise, shrink size of this block to new size, and make extra 00900 // space at end free. 00901 // 00902 00903 SplitBlock = (PHEAP_FREE_ENTRY)(BusyBlock + AllocationIndex); 00904 00905 SplitBlock->Flags = FreeFlags; 00906 00907 SplitBlock->PreviousSize = (USHORT)AllocationIndex; 00908 00909 SplitBlock->SegmentIndex = BusyBlock->SegmentIndex; 00910 00911 FreeSize = BusyBlock->Size - AllocationIndex; 00912 00913 BusyBlock->Size = (USHORT)AllocationIndex; 00914 00915 BusyBlock->Flags &= ~HEAP_ENTRY_LAST_ENTRY; 00916 00917 // 00918 // If the following block is uncommitted then we only need to 00919 // add this new entry to its free list 00920 // 00921 00922 if (FreeFlags & HEAP_ENTRY_LAST_ENTRY) { 00923 00924 PHEAP_SEGMENT Segment; 00925 00926 Segment = Heap->Segments[SplitBlock->SegmentIndex]; 00927 Segment->LastEntryInSegment = (PHEAP_ENTRY)SplitBlock; 00928 00929 SplitBlock->Size = (USHORT)FreeSize; 00930 00931 RtlpInsertFreeBlockDirect( Heap, SplitBlock, (USHORT)FreeSize ); 00932 00933 Heap->TotalFreeSize += FreeSize; 00934 00935 } else { 00936 00937 // 00938 // Otherwise get the next block and check if it is busy. If it 00939 // is in use then add this new entry to its free list 00940 // 00941 00942 SplitBlock2 = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize); 00943 00944 if (SplitBlock2->Flags & HEAP_ENTRY_BUSY) { 00945 00946 SplitBlock->Size = (USHORT)FreeSize; 00947 00948 ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize))->PreviousSize = (USHORT)FreeSize; 00949 00950 RtlpInsertFreeBlockDirect( Heap, SplitBlock, (USHORT)FreeSize ); 00951 00952 Heap->TotalFreeSize += FreeSize; 00953 00954 } else { 00955 00956 // 00957 // Otherwise the next block is not in use so we 00958 // should be able to merge with it. Remove the 00959 // second free block and if the combined size is 00960 // still okay then merge the two blocks and add 00961 // the single block back in. Otherwise call a 00962 // routine that will actually break it apart 00963 // before insertion. 00964 // 00965 00966 SplitBlock->Flags = SplitBlock2->Flags; 00967 00968 RtlpRemoveFreeBlock( Heap, SplitBlock2 ); 00969 00970 Heap->TotalFreeSize -= SplitBlock2->Size; 00971 00972 FreeSize += SplitBlock2->Size; 00973 00974 if (FreeSize <= HEAP_MAXIMUM_BLOCK_SIZE) { 00975 00976 SplitBlock->Size = (USHORT)FreeSize; 00977 00978 if (!(SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY)) { 00979 00980 ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize))->PreviousSize = (USHORT)FreeSize; 00981 00982 } else { 00983 00984 PHEAP_SEGMENT Segment; 00985 00986 Segment = Heap->Segments[SplitBlock->SegmentIndex]; 00987 Segment->LastEntryInSegment = (PHEAP_ENTRY)SplitBlock; 00988 } 00989 00990 RtlpInsertFreeBlockDirect( Heap, SplitBlock, (USHORT)FreeSize ); 00991 00992 Heap->TotalFreeSize += FreeSize; 00993 00994 } else { 00995 00996 RtlpInsertFreeBlock( Heap, SplitBlock, FreeSize ); 00997 } 00998 } 00999 } 01000 } 01001 } 01002 01003 } else { 01004 01005 // 01006 // At this point the new size is greater than the current size 01007 // 01008 // If the block is a big allocation or we're not able to grow 01009 // the block in place then we have a lot of work to do 01010 // 01011 01012 if ((BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) || 01013 !RtlpGrowBlockInPlace( Heap, Flags, BusyBlock, Size, AllocationIndex )) { 01014 01015 // 01016 // We're growing the block. Allocate a new block with the bigger 01017 // size, copy the contents of the old block to the new block and then 01018 // free the old block. Return the address of the new block. 01019 // 01020 01021 if (Flags & HEAP_REALLOC_IN_PLACE_ONLY) { 01022 01023 #if DBG 01024 // HeapDebugPrint(( "Failing ReAlloc because cant do it inplace.\n" )); 01025 #endif 01026 01027 BaseAddress = NULL; 01028 01029 } else { 01030 01031 // 01032 // Clear the tag bits from the flags 01033 // 01034 01035 Flags &= ~HEAP_TAG_MASK; 01036 01037 // 01038 // If there is an extra struct present then get the tag 01039 // index from the extra stuff and augment the flags with 01040 // the tag index. 01041 // 01042 01043 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 01044 01045 Flags &= ~HEAP_SETTABLE_USER_FLAGS; 01046 01047 Flags |= HEAP_SETTABLE_USER_VALUE | 01048 ((BusyBlock->Flags & HEAP_ENTRY_SETTABLE_FLAGS) << 4); 01049 01050 OldExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 01051 01052 try { 01053 01054 if ((OldExtraStuff->TagIndex != 0) && 01055 !(OldExtraStuff->TagIndex & HEAP_PSEUDO_TAG_FLAG)) { 01056 01057 Flags |= OldExtraStuff->TagIndex << HEAP_TAG_SHIFT; 01058 } 01059 01060 } except (EXCEPTION_EXECUTE_HANDLER) { 01061 01062 BusyBlock->Flags &= ~HEAP_ENTRY_EXTRA_PRESENT; 01063 } 01064 01065 } else if (BusyBlock->SmallTagIndex != 0) { 01066 01067 // 01068 // There is not an extra stuff struct, but block 01069 // does have a small tag index so now add this small 01070 // tag to the flags 01071 // 01072 01073 Flags |= BusyBlock->SmallTagIndex << HEAP_TAG_SHIFT; 01074 } 01075 01076 // 01077 // Allocate from the heap space for the reallocation 01078 // 01079 01080 NewBaseAddress = RtlAllocateHeap( HeapHandle, 01081 Flags & ~HEAP_ZERO_MEMORY, 01082 Size ); 01083 01084 if (NewBaseAddress != NULL) { 01085 01086 // 01087 // We were able to get the allocation so now back up 01088 // to the heap block and if the block has an extra 01089 // stuff struct then copy over the extra stuff 01090 // 01091 01092 NewBusyBlock = (PHEAP_ENTRY)NewBaseAddress - 1; 01093 01094 if (NewBusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 01095 01096 NewExtraStuff = RtlpGetExtraStuffPointer( NewBusyBlock ); 01097 01098 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 01099 01100 OldExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 01101 01102 NewExtraStuff->Settable = OldExtraStuff->Settable; 01103 01104 } else { 01105 01106 RtlZeroMemory( NewExtraStuff, sizeof( *NewExtraStuff )); 01107 } 01108 } 01109 01110 // 01111 // Copy over the user's data area to the new block 01112 // 01113 01114 RtlMoveMemory( NewBaseAddress, BaseAddress, Size < OldSize ? Size : OldSize ); 01115 01116 // 01117 // Check if we grew the block and we should zero 01118 // the remaining part. 01119 // 01120 // **** is this first test always true because we're 01121 // **** in the part that grows blocks 01122 // 01123 01124 if (Size > OldSize && (Flags & HEAP_ZERO_MEMORY)) { 01125 01126 RtlZeroMemory( (PCHAR)NewBaseAddress + OldSize, 01127 Size - OldSize ); 01128 } 01129 01130 // 01131 // Release the old block 01132 // 01133 01134 RtlFreeHeap( HeapHandle, 01135 Flags, 01136 BaseAddress ); 01137 } 01138 01139 BaseAddress = NewBaseAddress; 01140 } 01141 } 01142 } 01143 01144 if ((BaseAddress == NULL) && (Flags & HEAP_GENERATE_EXCEPTIONS)) { 01145 01146 // 01147 // Construct an exception record. 01148 // 01149 01150 ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY; 01151 ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)NULL; 01152 ExceptionRecord.NumberParameters = 1; 01153 ExceptionRecord.ExceptionFlags = 0; 01154 ExceptionRecord.ExceptionInformation[ 0 ] = AllocationSize; 01155 01156 RtlRaiseException( &ExceptionRecord ); 01157 } 01158 01159 } except( GetExceptionCode() == STATUS_NO_MEMORY ? EXCEPTION_CONTINUE_SEARCH : 01160 EXCEPTION_EXECUTE_HANDLER ) { 01161 01162 SET_LAST_STATUS( GetExceptionCode() ); 01163 BaseAddress = NULL; 01164 01165 } 01166 01167 } finally { 01168 01169 // 01170 // Unlock the heap 01171 // 01172 01173 if (LockAcquired) { 01174 01175 RtlReleaseLockRoutine( Heap->LockVariable ); 01176 } 01177 } 01178 01179 // 01180 // And return to our caller 01181 // 01182 01183 return BaseAddress; 01184 }

BOOLEAN RtlSetUserFlagsHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress,
IN ULONG  UserFlagsReset,
IN ULONG  UserFlagsSet
 

Definition at line 1480 of file heapdll.c.

References DEBUG_HEAP, EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP_ENTRY::Flags, _HEAP::ForceFlags, HEAP_ENTRY_BUSY, HeapHandle, _HEAP::LockVariable, RtlAcquireLockRoutine, RtlDebugSetUserFlagsHeap(), RtlReleaseLockRoutine, SET_LAST_STATUS, and TRUE.

Referenced by RtlDebugSetUserFlagsHeap(), and RtlpDphNormalHeapSetUserFlags().

01490 : 01491 01492 HeapHandle - Supplies a pointer to the heap being modified 01493 01494 Flags - Supplies a set of flags needed to augment those already enforced 01495 by the heap 01496 01497 BaseAddress - Supplies a pointer to the heap entry allocation being 01498 modified 01499 01500 UserFlagsReset - Supplies a mask of flags that the user wants cleared 01501 01502 UserFlagsSet- Supplies a mask of flags that the user wants set 01503 01504 Return Value: 01505 01506 BOOLEAN - TRUE if the operation is a success and FALSE otherwise 01507 01508 --*/ 01509 01510 { 01511 PHEAP Heap = (PHEAP)HeapHandle; 01512 PHEAP_ENTRY BusyBlock; 01513 BOOLEAN LockAcquired = FALSE; 01514 BOOLEAN Result = FALSE; 01515 01516 // 01517 // Augment the set of flags 01518 // 01519 01520 Flags |= Heap->ForceFlags; 01521 01522 // 01523 // Check to see if we should be going the debug route 01524 // 01525 01526 if (DEBUG_HEAP( Flags )) { 01527 01528 return RtlDebugSetUserFlagsHeap( HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet ); 01529 } 01530 01531 try { 01532 01533 // 01534 // Lock the heap 01535 // 01536 01537 if (!(Flags & HEAP_NO_SERIALIZE)) { 01538 01539 RtlAcquireLockRoutine( Heap->LockVariable ); 01540 01541 LockAcquired = TRUE; 01542 } 01543 01544 try { 01545 01546 // 01547 // Get a pointer to the owning heap entry 01548 // 01549 01550 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 01551 01552 // 01553 // If the entry is not in use then it is an error 01554 // 01555 01556 if (!(BusyBlock->Flags & HEAP_ENTRY_BUSY)) { 01557 01558 SET_LAST_STATUS( STATUS_INVALID_PARAMETER ); 01559 01560 } else { 01561 01562 // 01563 // Otherwise modify the flags in the block 01564 // 01565 // **** this is terrible error prone if the user passes in 01566 // **** flags that aren't 0x200 0x400 or 0x800 only. 01567 // 01568 01569 BusyBlock->Flags &= ~(UserFlagsReset >> 4); 01570 BusyBlock->Flags |= (UserFlagsSet >> 4); 01571 01572 Result = TRUE; 01573 } 01574 01575 } except( EXCEPTION_EXECUTE_HANDLER ) { 01576 01577 SET_LAST_STATUS( GetExceptionCode() ); 01578 01579 Result = FALSE; 01580 } 01581 01582 } finally { 01583 01584 // 01585 // Unlock the heap 01586 // 01587 01588 if (LockAcquired) { 01589 01590 RtlReleaseLockRoutine( Heap->LockVariable ); 01591 } 01592 } 01593 01594 return Result; 01595 }

BOOLEAN RtlSetUserValueHeap IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress,
IN PVOID  UserValue
 

Definition at line 1356 of file heapdll.c.

References DEBUG_HEAP, FALSE, _HEAP_ENTRY::Flags, _HEAP::ForceFlags, HEAP_ENTRY_BUSY, HEAP_ENTRY_EXTRA_PRESENT, HeapHandle, _HEAP::LockVariable, RtlAcquireLockRoutine, RtlDebugSetUserValueHeap(), RtlpGetExtraStuffPointer(), RtlReleaseLockRoutine, SET_LAST_STATUS, _HEAP_ENTRY_EXTRA::Settable, and TRUE.

Referenced by RtlDebugSetUserValueHeap(), and RtlpDphNormalHeapSetUserValue().

01365 : 01366 01367 This routine is used to set the user settable value for a heap entry 01368 01369 Arguments: 01370 01371 HeapHandle - Supplies a pointer to the heap being modified 01372 01373 Flags - Supplies a set of flags needed to augment those already enforced 01374 by the heap 01375 01376 BaseAddress - Supplies a pointer to the heap entry allocation being 01377 modified 01378 01379 UserValue - Supplies the value to store in the extra stuff space of 01380 the heap entry 01381 01382 Return Value: 01383 01384 BOOLEAN - TRUE if the setting worked, and FALSE otherwise. It could be 01385 FALSE if the base address is invalid, or if there is not room for 01386 the extra stuff 01387 01388 --*/ 01389 01390 { 01391 PHEAP Heap = (PHEAP)HeapHandle; 01392 PHEAP_ENTRY BusyBlock; 01393 PHEAP_ENTRY_EXTRA ExtraStuff; 01394 BOOLEAN LockAcquired = FALSE; 01395 BOOLEAN Result; 01396 01397 // 01398 // Augment the set of flags 01399 // 01400 01401 Flags |= Heap->ForceFlags; 01402 01403 // 01404 // Check to see if we should be going the debug route 01405 // 01406 01407 if (DEBUG_HEAP( Flags )) { 01408 01409 return RtlDebugSetUserValueHeap( HeapHandle, Flags, BaseAddress, UserValue ); 01410 } 01411 01412 Result = FALSE; 01413 01414 try { 01415 01416 // 01417 // Lock the heap 01418 // 01419 01420 if (!(Flags & HEAP_NO_SERIALIZE)) { 01421 01422 RtlAcquireLockRoutine( Heap->LockVariable ); 01423 01424 LockAcquired = TRUE; 01425 } 01426 01427 // 01428 // Get a pointer to the owning heap entry 01429 // 01430 01431 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 01432 01433 // 01434 // If the entry is not in use then its is an error 01435 // 01436 01437 if (!(BusyBlock->Flags & HEAP_ENTRY_BUSY)) { 01438 01439 SET_LAST_STATUS( STATUS_INVALID_PARAMETER ); 01440 01441 // 01442 // Otherwise we only can set the value if the entry has space 01443 // for the extra stuff 01444 // 01445 01446 } else if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 01447 01448 ExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 01449 01450 ExtraStuff->Settable = (ULONG_PTR)UserValue; 01451 01452 Result = TRUE; 01453 } 01454 01455 } finally { 01456 01457 // 01458 // Unlock the heap 01459 // 01460 01461 if (LockAcquired) { 01462 01463 RtlReleaseLockRoutine( Heap->LockVariable ); 01464 } 01465 } 01466 01467 // 01468 // And return to our caller 01469 // 01470 01471 return Result; 01472 }

BOOLEAN RtlUnlockHeap IN PVOID  HeapHandle  ) 
 

Definition at line 454 of file heapdll.c.

References FALSE, _HEAP::Flags, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, _HEAP::LockVariable, _HEAP::LookasideLockCount, RTL_PAGED_CODE, RtlpCheckHeapSignature(), RtlpDebugPageHeapUnlock(), RtlReleaseLockRoutine, and TRUE.

00460 : 00461 00462 This routine is used to unlock access to a specific heap structure 00463 00464 Arguments: 00465 00466 HeapHandle - Supplies a pointer to the heep being unlocked 00467 00468 Return Value: 00469 00470 BOOLEAN - TRUE if the heap is now unlocked and FALSE otherwise (i.e., 00471 the heap is ill-formed). TRUE is also returned if the heap was 00472 never locked to begin with because it is not seralizable. 00473 00474 --*/ 00475 00476 { 00477 PHEAP Heap = (PHEAP)HeapHandle; 00478 00479 RTL_PAGED_CODE(); 00480 00481 // 00482 // Check for the heap protected by guard pages 00483 // 00484 00485 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 00486 RtlpDebugPageHeapUnlock( HeapHandle )); 00487 00488 // 00489 // Validate that HeapAddress points to a HEAP structure. 00490 // 00491 00492 if (!RtlpCheckHeapSignature( Heap, "RtlUnlockHeap" )) { 00493 00494 return FALSE; 00495 } 00496 00497 // 00498 // Unlock the heap. And enable the lookaside logic by decrementing 00499 // its lock count 00500 // 00501 00502 if (!(Heap->Flags & HEAP_NO_SERIALIZE)) { 00503 00504 Heap->LookasideLockCount -= 1; 00505 00506 RtlReleaseLockRoutine( Heap->LockVariable ); 00507 } 00508 00509 return TRUE; 00510 }

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

Definition at line 2976 of file heapdll.c.

References _HEAP_UNCOMMMTTED_RANGE::Address, _HEAP_ENTRY_EXTRA::AllocatorBackTraceIndex, _HEAP_SEGMENT::BaseAddress, Buffer, _HEAP_VIRTUAL_ALLOC_ENTRY::BusyBlock, _HEAP_VIRTUAL_ALLOC_ENTRY::CommitSize, DEBUG_HEAP, _HEAP_SEGMENT::Entry, _HEAP::Entry, _HEAP_VIRTUAL_ALLOC_ENTRY::ExtraStuff, FALSE, _HEAP_ENTRY::Flags, _HEAP::Flags, _HEAP::ForceFlags, HEAP_ENTRY_BUSY, HEAP_ENTRY_EXTRA_PRESENT, HEAP_ENTRY_LAST_ENTRY, HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_SEGMENTS, HeapHandle, IS_HEAP_TAGGING_ENABLED, _HEAP_SEGMENT::LastValidEntry, _HEAP::LockVariable, _HEAP_UNCOMMMTTED_RANGE::Next, NT_SUCCESS, NtAllocateVirtualMemory(), NtFreeVirtualMemory(), NTSTATUS(), NULL, _HEAP_SEGMENT::NumberOfPages, _HEAP_SEGMENT::NumberOfUnCommittedPages, PAGE_SIZE, PRTL_HEAP_USAGE_INTERNAL, RtlAcquireLockRoutine, RtlDebugUsageHeap(), RtlpAllocateHeapUsageEntry(), RtlpFreeHeapUsageEntry(), RtlpGetExtraStuffPointer(), RtlReleaseLockRoutine, _HEAP::SegmentReserve, _HEAP::Segments, _HEAP_UNCOMMMTTED_RANGE::Size, _HEAP_ENTRY::Size, _HEAP_ENTRY::SmallTagIndex, Status, _HEAP_ENTRY_EXTRA::TagIndex, _HEAP::TotalFreeSize, TRUE, _HEAP_SEGMENT::UnCommittedRanges, _HEAP_ENTRY::UnusedBytes, Usage(), and _HEAP::VirtualAllocdBlocks.

Referenced by main(), and RtlDebugUsageHeap().

02984 : 02985 02986 This is a rather bizzare routine. It models heap usage in that it returns 02987 to the caller the various heap sizes, but it also return three lists. One 02988 is a list of entries for each active allocation in the heap. The next two 02989 are used for tracking difference between usage calls. There is a list of 02990 what was added and a list of what was removed. 02991 02992 Arguments: 02993 02994 HeapHandle - Supplies a pointer to the heap being queried 02995 02996 Flags - Supplies a set of flags needed to augment those enforced 02997 by the heap. 02998 02999 HEAP_USAGE_ALLOCATED_BLOCKS - Denotes that the calls wants the list 03000 of allocated entries. 03001 03002 HEAP_USAGE_FREE_BUFFER - Denotes the last call to this procedure and 03003 that any temporary storage can now be freed 03004 03005 Usage - Receives the current usage statistics for the heap. This variable 03006 is also used to store state information between calls to this routine. 03007 03008 Return Value: 03009 03010 NTSTATUS - An appropriate status value. STATUS_SUCCESS if the heap has 03011 not changed at all between calls and STATUS_MORE_ENTRIES if thep changed 03012 between two calls. 03013 03014 --*/ 03015 03016 { 03017 NTSTATUS Status; 03018 PHEAP Heap = (PHEAP)HeapHandle; 03019 PRTL_HEAP_USAGE_INTERNAL Buffer; 03020 PHEAP_SEGMENT Segment; 03021 PHEAP_UNCOMMMTTED_RANGE UnCommittedRange; 03022 PHEAP_ENTRY CurrentBlock; 03023 PHEAP_ENTRY_EXTRA ExtraStuff; 03024 PLIST_ENTRY Head, Next; 03025 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock; 03026 SIZE_T BytesFree; 03027 UCHAR SegmentIndex; 03028 BOOLEAN LockAcquired = FALSE; 03029 BOOLEAN VirtualAllocBlockSeen; 03030 PRTL_HEAP_USAGE_ENTRY pOldEntries, pNewEntries, pNewEntry; 03031 PRTL_HEAP_USAGE_ENTRY *ppEntries, *ppAddedEntries, *ppRemovedEntries, *pp; 03032 PVOID DataAddress; 03033 SIZE_T DataSize; 03034 03035 // 03036 // Augment the heap flags 03037 // 03038 03039 Flags |= Heap->ForceFlags; 03040 03041 // 03042 // Check if we should be using the debug version of heap 03043 // 03044 03045 if (DEBUG_HEAP( Flags )) { 03046 03047 return RtlDebugUsageHeap( HeapHandle, Flags, Usage ); 03048 } 03049 03050 // 03051 // Make sure that the size of the input buffer is correct 03052 // 03053 03054 if (Usage->Length != sizeof( RTL_HEAP_USAGE )) { 03055 03056 return STATUS_INFO_LENGTH_MISMATCH; 03057 } 03058 03059 // 03060 // Zero out the output fields 03061 // 03062 03063 Usage->BytesAllocated = 0; 03064 Usage->BytesCommitted = 0; 03065 Usage->BytesReserved = 0; 03066 Usage->BytesReservedMaximum = 0; 03067 03068 // 03069 // Use the reserved area of the output buffer as an internal 03070 // heap usage storage space between calls 03071 // 03072 03073 Buffer = (PRTL_HEAP_USAGE_INTERNAL)&Usage->Reserved[ 0 ]; 03074 03075 // 03076 // Check if there is not a base buffer and we should allocate 03077 // one then do so now 03078 // 03079 03080 if ((Buffer->Base == NULL) && 03081 (Flags & HEAP_USAGE_ALLOCATED_BLOCKS)) { 03082 03083 Buffer->ReservedSize = 4 * 1024 * 1024; 03084 03085 Status = NtAllocateVirtualMemory( NtCurrentProcess(), 03086 &Buffer->Base, 03087 0, 03088 &Buffer->ReservedSize, 03089 MEM_RESERVE, 03090 PAGE_READWRITE ); 03091 03092 if (!NT_SUCCESS( Status )) { 03093 03094 return Status; 03095 } 03096 03097 Buffer->CommittedSize = 0; 03098 Buffer->FreeList = NULL; 03099 Buffer->LargeEntriesSentinal = NULL; 03100 03101 // 03102 // Otherwise check if there already is a base buffer 03103 // and we should free it now 03104 // 03105 03106 } else if ((Buffer->Base != NULL) && 03107 (Flags & HEAP_USAGE_FREE_BUFFER)) { 03108 03109 Buffer->ReservedSize = 0; 03110 03111 Status = NtFreeVirtualMemory( NtCurrentProcess(), 03112 &Buffer->Base, 03113 &Buffer->ReservedSize, 03114 MEM_RELEASE ); 03115 03116 if (!NT_SUCCESS( Status )) { 03117 03118 return Status; 03119 } 03120 03121 RtlZeroMemory( Buffer, sizeof( *Buffer ) ); 03122 } 03123 03124 // 03125 // **** Augment the heap flags again 03126 // 03127 03128 Flags |= Heap->ForceFlags; 03129 03130 try { 03131 03132 // 03133 // Lock the heap 03134 // 03135 03136 if (!(Flags & HEAP_NO_SERIALIZE)) { 03137 03138 RtlAcquireLockRoutine( Heap->LockVariable ); 03139 03140 LockAcquired = TRUE; 03141 } 03142 03143 // 03144 // Scan through the heap segments and for every in-use segment 03145 // we add it to the amount of committed and reserved bytes 03146 // If the segment is not in use and the heap is growable then 03147 // we just add it to the reserved maximum 03148 // 03149 03150 for (SegmentIndex=0; SegmentIndex<HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) { 03151 03152 Segment = Heap->Segments[ SegmentIndex ]; 03153 03154 if (Segment) { 03155 03156 Usage->BytesCommitted += (Segment->NumberOfPages - 03157 Segment->NumberOfUnCommittedPages) * PAGE_SIZE; 03158 03159 Usage->BytesReserved += Segment->NumberOfPages * PAGE_SIZE; 03160 03161 } else if (Heap->Flags & HEAP_GROWABLE) { 03162 03163 Usage->BytesReservedMaximum += Heap->SegmentReserve; 03164 } 03165 } 03166 03167 Usage->BytesReservedMaximum += Usage->BytesReserved; 03168 Usage->BytesAllocated = Usage->BytesCommitted - (Heap->TotalFreeSize << HEAP_GRANULARITY_SHIFT); 03169 03170 // 03171 // Scan through the big allocations and add those amounts to the 03172 // usage statistics 03173 // 03174 03175 Head = &Heap->VirtualAllocdBlocks; 03176 Next = Head->Flink; 03177 03178 while (Head != Next) { 03179 03180 VirtualAllocBlock = CONTAINING_RECORD( Next, HEAP_VIRTUAL_ALLOC_ENTRY, Entry ); 03181 03182 Usage->BytesAllocated += VirtualAllocBlock->CommitSize; 03183 Usage->BytesCommitted += VirtualAllocBlock->CommitSize; 03184 03185 Next = Next->Flink; 03186 } 03187 03188 Status = STATUS_SUCCESS; 03189 03190 // 03191 // Now check if we have a base buffer and we are suppose to account 03192 // for allocated blocks 03193 // 03194 03195 if ((Buffer->Base != NULL) && 03196 (Flags & HEAP_USAGE_ALLOCATED_BLOCKS)) { 03197 03198 // 03199 // Setup a pointer to the old entries, added entries, and removed 03200 // entries in the usage struct. Also drain the added entries 03201 // and removed entries list 03202 // 03203 03204 pOldEntries = Usage->Entries; 03205 03206 ppEntries = &Usage->Entries; 03207 03208 *ppEntries = NULL; 03209 03210 ppAddedEntries = &Usage->AddedEntries; 03211 03212 while (*ppAddedEntries = RtlpFreeHeapUsageEntry( Buffer, *ppAddedEntries )) { NOTHING; } 03213 03214 ppRemovedEntries = &Usage->RemovedEntries; 03215 03216 while (*ppRemovedEntries = RtlpFreeHeapUsageEntry( Buffer, *ppRemovedEntries )) { NOTHING; } 03217 03218 // 03219 // The way the code works is that ppEntries, ppAddedEntries, and 03220 // ppRemovedEntries point to the tail of their respective lists. If 03221 // the list is empty then they point to the head. 03222 // 03223 03224 // 03225 // Process every segment in the heap 03226 // 03227 03228 for (SegmentIndex=0; SegmentIndex<HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) { 03229 03230 Segment = Heap->Segments[ SegmentIndex ]; 03231 03232 // 03233 // Only deal with segments that are in use 03234 // 03235 03236 if (Segment) { 03237 03238 // 03239 // The current block is really the first block in current 03240 // segment. We need to special case the computation to 03241 // account for the first heap segment. 03242 // 03243 03244 if (Segment->BaseAddress == Heap) { 03245 03246 CurrentBlock = &Heap->Entry; 03247 03248 } else { 03249 03250 CurrentBlock = &Segment->Entry; 03251 } 03252 03253 // 03254 // Now for every busy block in the segment we'll check if 03255 // we need to allocate a heap usage entry and put it in the 03256 // the entries list 03257 // 03258 03259 while (CurrentBlock < Segment->LastValidEntry) { 03260 03261 if (CurrentBlock->Flags & HEAP_ENTRY_BUSY) { 03262 03263 // 03264 // Compute the users data address and size 03265 // 03266 03267 DataAddress = (CurrentBlock+1); 03268 DataSize = (CurrentBlock->Size << HEAP_GRANULARITY_SHIFT) - 03269 CurrentBlock->UnusedBytes; 03270 03271 keepLookingAtOldEntries: 03272 03273 // 03274 // The first time through this routine will have 03275 // both of these variables null so we'll start off 03276 // by looking at new entries. 03277 // 03278 03279 if (pOldEntries == Buffer->LargeEntriesSentinal) { 03280 03281 goto keepLookingAtNewEntries; 03282 } 03283 03284 // 03285 // Check if this entry hasn't changed. 03286 // 03287 // If the old entry is equal to this data block 03288 // then move the old entry back to the entries 03289 // list and go on to the next block. 03290 // 03291 03292 if ((pOldEntries->Address == DataAddress) && 03293 (pOldEntries->Size == DataSize)) { 03294 03295 // 03296 // Same block, keep in entries list 03297 // 03298 03299 *ppEntries = pOldEntries; 03300 pOldEntries = pOldEntries->Next; 03301 ppEntries = &(*ppEntries)->Next; 03302 03303 *ppEntries = NULL; 03304 03305 // 03306 // Check if an entry was removed 03307 // 03308 // If this entry is beyond the old entry then move 03309 // the old entry to the removed entry list and keep 03310 // looking at the old entry list without advancing 03311 // the current data block 03312 // 03313 03314 } else if (pOldEntries->Address <= DataAddress) { 03315 03316 *ppRemovedEntries = pOldEntries; 03317 pOldEntries = pOldEntries->Next; 03318 ppRemovedEntries = &(*ppRemovedEntries)->Next; 03319 03320 *ppRemovedEntries = NULL; 03321 03322 goto keepLookingAtOldEntries; 03323 03324 // 03325 // Otherwise the we want to process the current data block 03326 // 03327 03328 } else { 03329 03330 keepLookingAtNewEntries: 03331 03332 // 03333 // Allocate a new heap usage entry 03334 // 03335 03336 pNewEntry = NULL; 03337 03338 Status = RtlpAllocateHeapUsageEntry( Buffer, &pNewEntry ); 03339 03340 if (!NT_SUCCESS( Status )) { 03341 03342 break; 03343 } 03344 03345 // 03346 // And fill in the new entry 03347 // 03348 03349 pNewEntry->Address = DataAddress; 03350 pNewEntry->Size = DataSize; 03351 03352 // 03353 // If there is an extra stuff struct then fill it in 03354 // with the stack backtrace, and appropriate tag index 03355 // 03356 03357 if (CurrentBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 03358 03359 ExtraStuff = RtlpGetExtraStuffPointer( CurrentBlock ); 03360 03361 #if i386 03362 03363 pNewEntry->AllocatorBackTraceIndex = ExtraStuff->AllocatorBackTraceIndex; 03364 03365 #endif // i386 03366 03367 if (!IS_HEAP_TAGGING_ENABLED()) { 03368 03369 pNewEntry->TagIndex = 0; 03370 03371 } else { 03372 03373 pNewEntry->TagIndex = ExtraStuff->TagIndex; 03374 } 03375 03376 } else { 03377 03378 // 03379 // Otherwise there is no extra stuff so there is 03380 // no backtrace and the tag is from the small index 03381 // 03382 03383 #if i386 03384 03385 pNewEntry->AllocatorBackTraceIndex = 0; 03386 03387 #endif // i386 03388 03389 if (!IS_HEAP_TAGGING_ENABLED()) { 03390 03391 pNewEntry->TagIndex = 0; 03392 03393 } else { 03394 03395 pNewEntry->TagIndex = CurrentBlock->SmallTagIndex; 03396 } 03397 } 03398 03399 // 03400 // Allocate another new heap usage entry as part of the added 03401 // entry list 03402 // 03403 03404 Status = RtlpAllocateHeapUsageEntry( Buffer, ppAddedEntries ); 03405 03406 if (!NT_SUCCESS( Status )) { 03407 03408 break; 03409 } 03410 03411 // 03412 // Copy over the contents of the new entry to the added entry 03413 // 03414 03415 **ppAddedEntries = *pNewEntry; 03416 03417 // 03418 // Advance the added entry pointer to the next slot 03419 // 03420 03421 ppAddedEntries = &((*ppAddedEntries)->Next); 03422 03423 *ppAddedEntries = NULL; 03424 03425 pNewEntry->Next = NULL; 03426 03427 // 03428 // Add the new entry to the entries list 03429 // 03430 03431 *ppEntries = pNewEntry; 03432 ppEntries = &pNewEntry->Next; 03433 } 03434 } 03435 03436 // 03437 // Now advance to the next block in the segment 03438 // 03439 // If the next block doesn't exist then zoom through the 03440 // uncommitted ranges in the segment until we find a 03441 // match and can recompute the next real block 03442 // 03443 03444 if (CurrentBlock->Flags & HEAP_ENTRY_LAST_ENTRY) { 03445 03446 CurrentBlock += CurrentBlock->Size; 03447 03448 if (CurrentBlock < Segment->LastValidEntry) { 03449 03450 UnCommittedRange = Segment->UnCommittedRanges; 03451 03452 while ((UnCommittedRange != NULL) && 03453 (UnCommittedRange->Address != (ULONG_PTR)CurrentBlock)) { 03454 03455 UnCommittedRange = UnCommittedRange->Next; 03456 } 03457 03458 if (UnCommittedRange == NULL) { 03459 03460 CurrentBlock = Segment->LastValidEntry; 03461 03462 } else { 03463 03464 CurrentBlock = (PHEAP_ENTRY)(UnCommittedRange->Address + 03465 UnCommittedRange->Size); 03466 } 03467 } 03468 03469 } else { 03470 03471 // 03472 // Otherwise the next block exists and so point 03473 // directly at it 03474 // 03475 03476 CurrentBlock += CurrentBlock->Size; 03477 } 03478 } 03479 } 03480 } 03481 03482 // 03483 // At this point we've scanned through every segment in the heap 03484 // 03485 // The first time through we now have two lists one of entries and 03486 // another of added entries. In each case Usage->Entries, and 03487 // Usage->AddedEntries points to the start of the list and ppEntries, 03488 // and ppAddedEntries points to the tail of the list. The first 03489 // time through we has seem to have a one-to-one correspondence 03490 // between Entries and AddedEntries, but the AddedEntries records 03491 // do not contain anything useful 03492 // 03493 03494 if (NT_SUCCESS( Status )) { 03495 03496 // 03497 // Now we'll examine each big allocation, and for each big allocation 03498 // we'll make a heap usage entry 03499 // 03500 03501 Head = &Heap->VirtualAllocdBlocks; 03502 Next = Head->Flink; 03503 VirtualAllocBlockSeen = FALSE; 03504 03505 while (Head != Next) { 03506 03507 VirtualAllocBlock = CONTAINING_RECORD( Next, HEAP_VIRTUAL_ALLOC_ENTRY, Entry ); 03508 03509 // 03510 // Allocate a new heap usage entry 03511 // 03512 03513 pNewEntry = NULL; 03514 03515 Status = RtlpAllocateHeapUsageEntry( Buffer, &pNewEntry ); 03516 03517 if (!NT_SUCCESS( Status )) { 03518 03519 break; 03520 } 03521 03522 VirtualAllocBlockSeen = TRUE; 03523 03524 // 03525 // Fill in the new heap usage entry 03526 // 03527 03528 pNewEntry->Address = (VirtualAllocBlock + 1); 03529 pNewEntry->Size = VirtualAllocBlock->CommitSize - VirtualAllocBlock->BusyBlock.Size; 03530 03531 #if i386 03532 03533 pNewEntry->AllocatorBackTraceIndex = VirtualAllocBlock->ExtraStuff.AllocatorBackTraceIndex; 03534 03535 #endif // i386 03536 03537 if (!IS_HEAP_TAGGING_ENABLED()) { 03538 03539 pNewEntry->TagIndex = 0; 03540 03541 } else { 03542 03543 pNewEntry->TagIndex = VirtualAllocBlock->ExtraStuff.TagIndex; 03544 } 03545 03546 // 03547 // Search the heap usage entries list until we find the address 03548 // that right after the new entry address and then insert 03549 // this new entry. This will keep the entries list sorted in 03550 // assending addresses 03551 // 03552 // 03553 // The first time through this function ppEntries will point 03554 // to the tail and so *pp should actually start off as null, 03555 // which means that the big allocation simply get tacked on 03556 // the end of the entries list. We do not augment the 03557 // AddedEntries list for these big allocations. 03558 // 03559 03560 pp = ppEntries; 03561 03562 while (*pp) { 03563 03564 if ((*pp)->Address >= pNewEntry->Address) { 03565 03566 break; 03567 } 03568 03569 pp = &(*pp)->Next; 03570 } 03571 03572 pNewEntry->Next = *pp; 03573 *pp = pNewEntry; 03574 03575 // 03576 // Get the next big allocation block 03577 // 03578 03579 Next = Next->Flink; 03580 } 03581 03582 // 03583 // At this point we've scanned through the heap segments and the 03584 // big allocations. 03585 // 03586 // The first time through this procedure we have built two lists 03587 // the Entries and the AddedEntries 03588 // 03589 03590 if (NT_SUCCESS( Status )) { 03591 03592 pOldEntries = Buffer->LargeEntriesSentinal; 03593 Buffer->LargeEntriesSentinal = *ppEntries; 03594 03595 // 03596 // Now we'll process the previous large entries sentinal list 03597 // 03598 // This path is not taken the first time through this procedure 03599 // 03600 03601 while (pOldEntries != NULL) { 03602 03603 // 03604 // If we have new entries and the entry is equal to the 03605 // entry in the previous large sentinal list then 03606 // we move one down on the new list and remove the previous 03607 // sentinal entry 03608 // 03609 03610 if ((*ppEntries != NULL) && 03611 (pOldEntries->Address == (*ppEntries)->Address) && 03612 (pOldEntries->Size == (*ppEntries)->Size)) { 03613 03614 ppEntries = &(*ppEntries)->Next; 03615 03616 pOldEntries = RtlpFreeHeapUsageEntry( Buffer, pOldEntries ); 03617 03618 // 03619 // If we do now have any new entries or the previous 03620 // sentinal entry is comes before this new entry then 03621 // we'll add the sentinal entry to the remove list 03622 // 03623 03624 } else if ((*ppEntries == NULL) || 03625 (pOldEntries->Address < (*ppEntries)->Address)) { 03626 03627 *ppRemovedEntries = pOldEntries; 03628 03629 pOldEntries = pOldEntries->Next; 03630 03631 ppRemovedEntries = &(*ppRemovedEntries)->Next; 03632 03633 *ppRemovedEntries = NULL; 03634 03635 // 03636 // Otherwise the old sentinal entry is put on the added 03637 // entries list 03638 // 03639 03640 } else { 03641 03642 *ppAddedEntries = pOldEntries; 03643 03644 pOldEntries = pOldEntries->Next; 03645 03646 **ppAddedEntries = **ppEntries; 03647 03648 ppAddedEntries = &(*ppAddedEntries)->Next; 03649 03650 *ppAddedEntries = NULL; 03651 } 03652 } 03653 03654 // 03655 // This path is not taken the first time through this procedure 03656 // 03657 03658 while (pNewEntry = *ppEntries) { 03659 03660 Status = RtlpAllocateHeapUsageEntry( Buffer, ppAddedEntries ); 03661 03662 if (!NT_SUCCESS( Status )) { 03663 03664 break; 03665 } 03666 03667 **ppAddedEntries = *pNewEntry; 03668 03669 ppAddedEntries = &(*ppAddedEntries)->Next; 03670 03671 *ppAddedEntries = NULL; 03672 03673 ppEntries = &pNewEntry->Next; 03674 } 03675 03676 // 03677 // Tell the user that something has changed between the 03678 // previous call and this one 03679 // 03680 03681 if ((Usage->AddedEntries != NULL) || (Usage->RemovedEntries != NULL)) { 03682 03683 Status = STATUS_MORE_ENTRIES; 03684 } 03685 } 03686 } 03687 } 03688 03689 } finally { 03690 03691 // 03692 // Unlock the heap 03693 // 03694 03695 if (LockAcquired) { 03696 03697 RtlReleaseLockRoutine( Heap->LockVariable ); 03698 } 03699 } 03700 03701 // 03702 // And return to our caller 03703 // 03704 03705 return Status; 03706 }

BOOLEAN RtlValidateHeap PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress
 

Definition at line 2530 of file heapdll.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::ForceFlags, HEAP_MAXIMUM_FREELISTS, HeapHandle, IS_DEBUG_PAGE_HEAP_HANDLE, _HEAP::LockVariable, _HEAP::Lookaside, NULL, RtlAcquireLockRoutine, RtlFreeHeap, RtlpAllocateFromHeapLookaside(), RtlpCheckHeapSignature(), RtlpDebugPageHeapValidate(), RtlpValidateHeap(), RtlpValidateHeapEntry(), RtlReleaseLockRoutine, SET_LAST_STATUS, and TRUE.

Referenced by main(), RtlpDphNormalHeapValidate(), and RtlValidateProcessHeaps().

02538 : 02539 02540 This routine verifies the structure of a heap and/or heap block 02541 02542 Arguments: 02543 02544 HeapHandle - Supplies a pointer to the heap being queried 02545 02546 Flags - Supplies a set of flags used to augment those already 02547 enforced by the heap 02548 02549 BaseAddress - Optionally supplies a pointer to the heap block 02550 that should be individually validated 02551 02552 Return Value: 02553 02554 BOOLEAN - TRUE if the heap/block is okay and FALSE otherwise 02555 02556 --*/ 02557 02558 { 02559 PHEAP Heap = (PHEAP)HeapHandle; 02560 BOOLEAN LockAcquired = FALSE; 02561 BOOLEAN Result; 02562 02563 try { 02564 02565 try { 02566 02567 // 02568 // Check for the guard page version of heap 02569 // 02570 02571 if ( IS_DEBUG_PAGE_HEAP_HANDLE( HeapHandle )) { 02572 02573 Result = RtlpDebugPageHeapValidate( HeapHandle, Flags, BaseAddress ); 02574 02575 } else { 02576 02577 // 02578 // If there is an active lookaside list then drain and remove it. 02579 // By setting the lookaside field in the heap to null we guarantee 02580 // that the call the free heap will not try and use the lookaside 02581 // list logic. 02582 // 02583 // We'll actually capture the lookaside pointer from the heap and 02584 // only use the captured pointer. This will take care of the 02585 // condition where another walk or lock heap can cause us to check 02586 // for a non null pointer and then have it become null when we read 02587 // it again. If it is non null to start with then even if the 02588 // user walks or locks the heap via another thread the pointer to 02589 // still valid here so we can still try and do a lookaside list pop. 02590 // 02591 02592 PHEAP_LOOKASIDE Lookaside = (PHEAP_LOOKASIDE)Heap->Lookaside; 02593 02594 if (Lookaside != NULL) { 02595 02596 ULONG i; 02597 PVOID Block; 02598 02599 Heap->Lookaside = NULL; 02600 02601 for (i = 0; i < HEAP_MAXIMUM_FREELISTS; i += 1) { 02602 02603 while ((Block = RtlpAllocateFromHeapLookaside(&(Lookaside[i]))) != NULL) { 02604 02605 RtlFreeHeap( HeapHandle, 0, Block ); 02606 } 02607 } 02608 } 02609 02610 Result = FALSE; 02611 02612 // 02613 // Validate that HeapAddress points to a HEAP structure. 02614 // 02615 02616 if (RtlpCheckHeapSignature( Heap, "RtlValidateHeap" )) { 02617 02618 Flags |= Heap->ForceFlags; 02619 02620 // 02621 // Lock the heap 02622 // 02623 02624 if (!(Flags & HEAP_NO_SERIALIZE)) { 02625 02626 RtlAcquireLockRoutine( Heap->LockVariable ); 02627 02628 LockAcquired = TRUE; 02629 } 02630 02631 // 02632 // If the user did not supply a base address then verify 02633 // the complete heap otherwise just do a single heap 02634 // entry 02635 // 02636 02637 if (BaseAddress == NULL) { 02638 02639 Result = RtlpValidateHeap( Heap, TRUE ); 02640 02641 } else { 02642 02643 Result = RtlpValidateHeapEntry( Heap, (PHEAP_ENTRY)BaseAddress - 1, "RtlValidateHeap" ); 02644 } 02645 } 02646 } 02647 02648 } except( EXCEPTION_EXECUTE_HANDLER ) { 02649 02650 SET_LAST_STATUS( GetExceptionCode() ); 02651 02652 Result = FALSE; 02653 } 02654 02655 } finally { 02656 02657 // 02658 // Unlock the heap 02659 // 02660 02661 if (LockAcquired) { 02662 02663 RtlReleaseLockRoutine( Heap->LockVariable ); 02664 } 02665 } 02666 02667 // 02668 // And return to our caller 02669 // 02670 02671 return Result; 02672 }

BOOLEAN RtlValidateProcessHeaps VOID   ) 
 

Definition at line 2680 of file heapdll.c.

References FALSE, NT_SUCCESS, NTSTATUS(), NULL, RtlGetProcessHeaps(), RtlValidateHeap(), Size, Status, and TRUE.

Referenced by LdrShutdownProcess().

02686 : 02687 02688 This routine cycles through all and validates each heap in the current 02689 process. 02690 02691 Arguments: 02692 02693 None. 02694 02695 Return Value: 02696 02697 BOOLEAN - TRUE if all the heap verify okay and FALSE for any other 02698 reason. 02699 02700 --*/ 02701 02702 { 02703 NTSTATUS Status; 02704 ULONG i, NumberOfHeaps; 02705 PVOID HeapsArray[ 512 ]; 02706 PVOID *Heaps; 02707 SIZE_T Size; 02708 BOOLEAN Result; 02709 02710 Result = TRUE; 02711 02712 Heaps = &HeapsArray[ 0 ]; 02713 02714 // 02715 // By default we can handle 512 heaps per process any more than 02716 // that and we'll need to allocate storage to do the processing 02717 // 02718 // So now determine how many heaps are in the current process 02719 // 02720 02721 NumberOfHeaps = RtlGetProcessHeaps( 512, Heaps ); 02722 02723 // 02724 // **** this is bogus because the preceeding routine will 02725 // **** never return more than 512. Either this routine 02726 // **** needs to get the heap count from the peb itself 02727 // **** or the called routine needs to return the actual 02728 // **** number of heaps in the process, Then we have to know 02729 // **** not to to beyond the heap array size 02730 // 02731 02732 if (NumberOfHeaps > 512) { 02733 02734 // 02735 // The number of heaps is greater than 512 so 02736 // allocate extra memory to store the array of 02737 // heap pointers 02738 // 02739 02740 Heaps = NULL; 02741 Size = NumberOfHeaps * sizeof( PVOID ); 02742 02743 Status = ZwAllocateVirtualMemory( NtCurrentProcess(), 02744 (PVOID *)&Heaps, 02745 0, 02746 &Size, 02747 MEM_COMMIT, 02748 PAGE_READWRITE ); 02749 02750 if (!NT_SUCCESS( Status )) { 02751 02752 return FALSE; 02753 } 02754 02755 // 02756 // And retry getting the heaps 02757 // 02758 // **** this won't work again because it still uses 512 02759 // 02760 02761 NumberOfHeaps = RtlGetProcessHeaps( 512, Heaps ); 02762 } 02763 02764 // 02765 // Now for each heap in our heap array we'll validate 02766 // that heap 02767 // 02768 02769 for (i=0; i<NumberOfHeaps; i++) { 02770 02771 if (!RtlValidateHeap( Heaps[i], 0, NULL )) { 02772 02773 Result = FALSE; 02774 } 02775 } 02776 02777 // 02778 // Check if we need to return the memory that we use for 02779 // an enlarged heap array 02780 // 02781 02782 if (Heaps != &HeapsArray[ 0 ]) { 02783 02784 ZwFreeVirtualMemory( NtCurrentProcess(), 02785 (PVOID *)&Heaps, 02786 &Size, 02787 MEM_RELEASE ); 02788 } 02789 02790 // 02791 // And return to our caller 02792 // 02793 02794 return Result; 02795 }

NTSTATUS RtlWalkHeap IN PVOID  HeapHandle,
IN OUT PRTL_HEAP_WALK_ENTRY  Entry
 

Definition at line 3714 of file heapdll.c.

References _HEAP_UNCOMMMTTED_RANGE::Address, _HEAP_ENTRY_EXTRA::AllocatorBackTraceIndex, _HEAP_VIRTUAL_ALLOC_ENTRY::BusyBlock, DEBUG_HEAP, _HEAP_VIRTUAL_ALLOC_ENTRY::Entry, _HEAP_SEGMENT::FirstEntry, _HEAP_ENTRY::Flags, _HEAP_SEGMENT::Flags, _HEAP::Flags, HEAP_ENTRY_BUSY, HEAP_ENTRY_EXTRA_PRESENT, HEAP_ENTRY_LAST_ENTRY, HEAP_ENTRY_SETTABLE_FLAGS, HEAP_ENTRY_VIRTUAL_ALLOC, HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_FREELISTS, HEAP_MAXIMUM_SEGMENTS, HeapHandle, IF_DEBUG_PAGE_HEAP_THEN_RETURN, IS_HEAP_TAGGING_ENABLED, _HEAP_SEGMENT::LastValidEntry, _HEAP::Lookaside, _HEAP_UNCOMMMTTED_RANGE::Next, NTSTATUS(), NULL, _HEAP_SEGMENT::NumberOfPages, _HEAP_SEGMENT::NumberOfUnCommittedPages, PAGE_SIZE, RtlDebugWalkHeap(), RtlFreeHeap, RtlpAllocateFromHeapLookaside(), RtlpDebugPageHeapWalk(), RtlpGetExtraStuffPointer(), RtlpGetSizeOfBigBlock(), _HEAP_ENTRY::SegmentIndex, _HEAP::Segments, _HEAP_ENTRY_EXTRA::Settable, _HEAP_UNCOMMMTTED_RANGE::Size, _HEAP_ENTRY::Size, _HEAP_ENTRY::SmallTagIndex, Status, _HEAP_ENTRY_EXTRA::TagIndex, _HEAP_SEGMENT::UnCommittedRanges, _HEAP_ENTRY::UnusedBytes, and _HEAP::VirtualAllocdBlocks.

03721 : 03722 03723 This routine is used to enumerate all the entries within a heap. For each 03724 call it returns a new information in entry. 03725 03726 Arguments: 03727 03728 HeapHandle - Supplies a pointer to the heap being queried 03729 03730 Entry - Supplies storage for the entry information. If the DataAddress field 03731 is null then the enumeration starts over from the beginning otherwise it 03732 resumes from where it left off 03733 03734 Return Value: 03735 03736 NTSTATUS - An appropriate status value 03737 03738 --*/ 03739 03740 { 03741 NTSTATUS Status; 03742 PHEAP Heap = (PHEAP)HeapHandle; 03743 PHEAP_SEGMENT Segment; 03744 UCHAR SegmentIndex; 03745 PHEAP_ENTRY CurrentBlock; 03746 PHEAP_ENTRY_EXTRA ExtraStuff; 03747 PHEAP_UNCOMMMTTED_RANGE UnCommittedRange, *pp; 03748 PLIST_ENTRY Next, Head; 03749 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock; 03750 03751 // 03752 // Check if we should be using the guard page verion of heap 03753 // 03754 03755 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 03756 RtlpDebugPageHeapWalk( HeapHandle, Entry )); 03757 03758 // 03759 // If this is the debug version of heap then validate the heap 03760 // before we go on 03761 // 03762 03763 if (DEBUG_HEAP( Heap->Flags )) { 03764 03765 if (!RtlDebugWalkHeap( HeapHandle, Entry )) { 03766 03767 return STATUS_INVALID_PARAMETER; 03768 } 03769 } 03770 03771 Status = STATUS_SUCCESS; 03772 03773 // 03774 // If there is an active lookaside list then drain and remove it. 03775 // By setting the lookaside field in the heap to null we guarantee 03776 // that the call the free heap will not try and use the lookaside 03777 // list logic. 03778 // 03779 // We'll actually capture the lookaside pointer from the heap and 03780 // only use the captured pointer. This will take care of the 03781 // condition where another walk or lock heap can cause us to check 03782 // for a non null pointer and then have it become null when we read 03783 // it again. If it is non null to start with then even if the 03784 // user walks or locks the heap via another thread the pointer to 03785 // still valid here so we can still try and do a lookaside list pop. 03786 // 03787 03788 { 03789 PHEAP_LOOKASIDE Lookaside = (PHEAP_LOOKASIDE)Heap->Lookaside; 03790 03791 if (Lookaside != NULL) { 03792 03793 ULONG i; 03794 PVOID Block; 03795 03796 Heap->Lookaside = NULL; 03797 03798 for (i = 0; i < HEAP_MAXIMUM_FREELISTS; i += 1) { 03799 03800 while ((Block = RtlpAllocateFromHeapLookaside(&(Lookaside[i]))) != NULL) { 03801 03802 RtlFreeHeap( HeapHandle, 0, Block ); 03803 } 03804 } 03805 } 03806 } 03807 03808 // 03809 // Check if this is the first time we've been called to walk the heap 03810 // 03811 03812 if (Entry->DataAddress == NULL) { 03813 03814 // 03815 // Start with the first segement in the heap 03816 // 03817 03818 SegmentIndex = 0; 03819 03820 nextSegment: 03821 03822 CurrentBlock = NULL; 03823 03824 // 03825 // Now find the next in use segment for the heap 03826 // 03827 03828 Segment = NULL; 03829 03830 while ((SegmentIndex < HEAP_MAXIMUM_SEGMENTS) && 03831 ((Segment = Heap->Segments[ SegmentIndex ]) == NULL)) { 03832 03833 SegmentIndex += 1; 03834 } 03835 03836 // 03837 // If there are no more valid segments then we'll try the big 03838 // allocation 03839 // 03840 03841 if (Segment == NULL) { 03842 03843 Head = &Heap->VirtualAllocdBlocks; 03844 Next = Head->Flink; 03845 03846 if (Next == Head) { 03847 03848 Status = STATUS_NO_MORE_ENTRIES; 03849 03850 } else { 03851 03852 VirtualAllocBlock = CONTAINING_RECORD( Next, HEAP_VIRTUAL_ALLOC_ENTRY, Entry ); 03853 03854 CurrentBlock = &VirtualAllocBlock->BusyBlock; 03855 } 03856 03857 // 03858 // Otherwise we'll grab information about the segment. Note that 03859 // the current block is still null so when we fall out of this 03860 // block we'll return directly to our caller with this segment 03861 // information 03862 // 03863 03864 } else { 03865 03866 Entry->DataAddress = Segment; 03867 03868 Entry->DataSize = 0; 03869 03870 Entry->OverheadBytes = sizeof( *Segment ); 03871 03872 Entry->Flags = RTL_HEAP_SEGMENT; 03873 03874 Entry->SegmentIndex = SegmentIndex; 03875 03876 Entry->Segment.CommittedSize = (Segment->NumberOfPages - 03877 Segment->NumberOfUnCommittedPages) * PAGE_SIZE; 03878 03879 Entry->Segment.UnCommittedSize = Segment->NumberOfUnCommittedPages * PAGE_SIZE; 03880 03881 Entry->Segment.FirstEntry = (Segment->FirstEntry->Flags & HEAP_ENTRY_BUSY) ? 03882 ((PHEAP_ENTRY)Segment->FirstEntry + 1) : 03883 (PHEAP_ENTRY)((PHEAP_FREE_ENTRY)Segment->FirstEntry + 1); 03884 03885 Entry->Segment.LastEntry = Segment->LastValidEntry; 03886 } 03887 03888 // 03889 // This is not the first time through. Check if last time we gave back 03890 // an heap segement or an uncommitted range 03891 // 03892 03893 } else if (Entry->Flags & (RTL_HEAP_SEGMENT | RTL_HEAP_UNCOMMITTED_RANGE)) { 03894 03895 // 03896 // Check that the segment index is still valid 03897 // 03898 03899 if ((SegmentIndex = Entry->SegmentIndex) >= HEAP_MAXIMUM_SEGMENTS) { 03900 03901 Status = STATUS_INVALID_ADDRESS; 03902 03903 CurrentBlock = NULL; 03904 03905 } else { 03906 03907 // 03908 // Check that the segment is still in use 03909 // 03910 03911 Segment = Heap->Segments[ SegmentIndex ]; 03912 03913 if (Segment == NULL) { 03914 03915 Status = STATUS_INVALID_ADDRESS; 03916 03917 CurrentBlock = NULL; 03918 03919 // 03920 // The segment is still in use if what we returned last time 03921 // as the segment header then this time we'll return the 03922 // segments first entry 03923 // 03924 03925 } else if (Entry->Flags & RTL_HEAP_SEGMENT) { 03926 03927 CurrentBlock = (PHEAP_ENTRY)Segment->FirstEntry; 03928 03929 // 03930 // Otherwise what we returned last time as an uncommitted 03931 // range so now we need to get the next block 03932 // 03933 03934 } else { 03935 03936 CurrentBlock = (PHEAP_ENTRY)((PCHAR)Entry->DataAddress + Entry->DataSize); 03937 03938 // 03939 // Check if we are beyond this segment and need to get the 03940 // next one 03941 // 03942 03943 if (CurrentBlock >= Segment->LastValidEntry) { 03944 03945 SegmentIndex += 1; 03946 03947 goto nextSegment; 03948 } 03949 } 03950 } 03951 03952 // 03953 // Otherwise this is not the first time through and last time we gave back a 03954 // valid heap entry 03955 // 03956 03957 } else { 03958 03959 // 03960 // Check if the last entry we gave back was in use 03961 // 03962 03963 if (Entry->Flags & HEAP_ENTRY_BUSY) { 03964 03965 // 03966 // Get the last entry we returned 03967 // 03968 03969 CurrentBlock = ((PHEAP_ENTRY)Entry->DataAddress - 1); 03970 03971 // 03972 // If the last entry was for a big allocation then 03973 // get the next big block if there is one otherwise 03974 // say there are no more entries 03975 // 03976 03977 if (CurrentBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) { 03978 03979 Head = &Heap->VirtualAllocdBlocks; 03980 03981 VirtualAllocBlock = CONTAINING_RECORD( CurrentBlock, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock ); 03982 03983 Next = VirtualAllocBlock->Entry.Flink; 03984 03985 if (Next == Head) { 03986 03987 Status = STATUS_NO_MORE_ENTRIES; 03988 03989 } else { 03990 03991 VirtualAllocBlock = CONTAINING_RECORD( Next, HEAP_VIRTUAL_ALLOC_ENTRY, Entry ); 03992 03993 CurrentBlock = &VirtualAllocBlock->BusyBlock; 03994 } 03995 03996 // 03997 // Our previous result is a busy normal block 03998 // 03999 04000 } else { 04001 04002 // 04003 // Get the segment and make sure it it still valid and in use 04004 // 04005 // **** this should also check that segment index is not 04006 // **** greater than HEAP MAXIMUM SEGMENTS 04007 // 04008 04009 Segment = Heap->Segments[ SegmentIndex = CurrentBlock->SegmentIndex ]; 04010 04011 if (Segment == NULL) { 04012 04013 Status = STATUS_INVALID_ADDRESS; 04014 04015 CurrentBlock = NULL; 04016 04017 // 04018 // The segment is still in use, check if what we returned 04019 // previously was a last entry 04020 // 04021 04022 } else if (CurrentBlock->Flags & HEAP_ENTRY_LAST_ENTRY) { 04023 04024 findUncommittedRange: 04025 04026 // 04027 // We are at a last entry so now if the segment is done 04028 // then go get another segment 04029 // 04030 04031 CurrentBlock += CurrentBlock->Size; 04032 04033 if (CurrentBlock >= Segment->LastValidEntry) { 04034 04035 SegmentIndex += 1; 04036 04037 goto nextSegment; 04038 } 04039 04040 // 04041 // Otherwise we will find the uncommitted range entry that 04042 // immediately follows this last entry 04043 // 04044 04045 pp = &Segment->UnCommittedRanges; 04046 04047 while ((UnCommittedRange = *pp) && UnCommittedRange->Address != (ULONG_PTR)CurrentBlock ) { 04048 04049 pp = &UnCommittedRange->Next; 04050 } 04051 04052 if (UnCommittedRange == NULL) { 04053 04054 Status = STATUS_INVALID_PARAMETER; 04055 04056 } else { 04057 04058 // 04059 // Now fill in the entry to denote that uncommitted 04060 // range information 04061 // 04062 04063 Entry->DataAddress = (PVOID)UnCommittedRange->Address; 04064 04065 Entry->DataSize = UnCommittedRange->Size; 04066 04067 Entry->OverheadBytes = 0; 04068 04069 Entry->SegmentIndex = SegmentIndex; 04070 04071 Entry->Flags = RTL_HEAP_UNCOMMITTED_RANGE; 04072 } 04073 04074 // 04075 // Null out the current block because we've just filled in 04076 // the entry 04077 // 04078 04079 CurrentBlock = NULL; 04080 04081 } else { 04082 04083 // 04084 // Otherwise the entry has a following entry so now 04085 // advance to the next entry 04086 // 04087 04088 CurrentBlock += CurrentBlock->Size; 04089 } 04090 } 04091 04092 // 04093 // Otherwise the previous entry we returned is not in use 04094 // 04095 04096 } else { 04097 04098 // 04099 // Get the last entry we returned 04100 // 04101 04102 CurrentBlock = (PHEAP_ENTRY)((PHEAP_FREE_ENTRY)Entry->DataAddress - 1); 04103 04104 // 04105 // Get the segment and make sure it it still valid and in use 04106 // 04107 // **** this should also check that segment index is not 04108 // **** greater than HEAP MAXIMUM SEGMENTS 04109 // 04110 04111 Segment = Heap->Segments[ SegmentIndex = CurrentBlock->SegmentIndex ]; 04112 04113 if (Segment == NULL) { 04114 04115 Status = STATUS_INVALID_ADDRESS; 04116 04117 CurrentBlock = NULL; 04118 04119 // 04120 // If the block is the last entry then go find the next uncommitted 04121 // range or segment 04122 // 04123 04124 } else if (CurrentBlock->Flags & HEAP_ENTRY_LAST_ENTRY) { 04125 04126 goto findUncommittedRange; 04127 04128 // 04129 // Otherwise we'll just move on to the next entry 04130 // 04131 04132 } else { 04133 04134 CurrentBlock += CurrentBlock->Size; 04135 } 04136 } 04137 } 04138 04139 // 04140 // At this point if current block is not null then we've found another 04141 // entry to return. We could also have found a segment or uncommitted 04142 // range but those are handled separately above and keep current block 04143 // null 04144 // 04145 04146 if (CurrentBlock != NULL) { 04147 04148 // 04149 // Check if the block is in use 04150 // 04151 04152 if (CurrentBlock->Flags & HEAP_ENTRY_BUSY) { 04153 04154 // 04155 // Fill in the entry field for this block 04156 // 04157 04158 Entry->DataAddress = (CurrentBlock+1); 04159 04160 if (CurrentBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) { 04161 04162 Entry->DataSize = RtlpGetSizeOfBigBlock( CurrentBlock ); 04163 04164 Entry->OverheadBytes = (UCHAR)( sizeof( *VirtualAllocBlock ) + CurrentBlock->Size); 04165 04166 Entry->SegmentIndex = HEAP_MAXIMUM_SEGMENTS; 04167 04168 Entry->Flags = RTL_HEAP_BUSY | HEAP_ENTRY_VIRTUAL_ALLOC; 04169 04170 } else { 04171 04172 Entry->DataSize = (CurrentBlock->Size << HEAP_GRANULARITY_SHIFT) - 04173 CurrentBlock->UnusedBytes; 04174 04175 Entry->OverheadBytes = CurrentBlock->UnusedBytes; 04176 04177 Entry->SegmentIndex = CurrentBlock->SegmentIndex; 04178 04179 Entry->Flags = RTL_HEAP_BUSY; 04180 } 04181 04182 if (CurrentBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 04183 04184 ExtraStuff = RtlpGetExtraStuffPointer( CurrentBlock ); 04185 04186 Entry->Block.Settable = ExtraStuff->Settable; 04187 #if i386 04188 04189 Entry->Block.AllocatorBackTraceIndex = ExtraStuff->AllocatorBackTraceIndex; 04190 04191 #endif // i386 04192 04193 if (!IS_HEAP_TAGGING_ENABLED()) { 04194 04195 Entry->Block.TagIndex = 0; 04196 04197 } else { 04198 04199 Entry->Block.TagIndex = ExtraStuff->TagIndex; 04200 } 04201 04202 Entry->Flags |= RTL_HEAP_SETTABLE_VALUE; 04203 04204 } else { 04205 04206 if (!IS_HEAP_TAGGING_ENABLED()) { 04207 04208 Entry->Block.TagIndex = 0; 04209 04210 } else { 04211 04212 Entry->Block.TagIndex = CurrentBlock->SmallTagIndex; 04213 } 04214 } 04215 04216 Entry->Flags |= CurrentBlock->Flags & HEAP_ENTRY_SETTABLE_FLAGS; 04217 04218 // 04219 // Otherwise the block is not in use 04220 // 04221 04222 } else { 04223 04224 Entry->DataAddress = ((PHEAP_FREE_ENTRY)CurrentBlock+1); 04225 04226 Entry->DataSize = (CurrentBlock->Size << HEAP_GRANULARITY_SHIFT) - 04227 sizeof( HEAP_FREE_ENTRY ); 04228 04229 Entry->OverheadBytes = sizeof( HEAP_FREE_ENTRY ); 04230 04231 Entry->SegmentIndex = CurrentBlock->SegmentIndex; 04232 04233 Entry->Flags = 0; 04234 } 04235 } 04236 04237 // 04238 // And return to our caller 04239 // 04240 04241 return Status; 04242 }


Variable Documentation

PHEAP RtlpGlobalTagHeap = NULL
 

Definition at line 68 of file heapdll.c.

Referenced by LdrpDefineDllTag(), RtlCreateTagHeap(), RtlpAllocateTags(), RtlpGetTagName(), RtlpUpdateTagEntry(), and RtlQueryProcessHeapInformation().

PHEAP RtlpProcessHeapsListBuffer[RTLP_STATIC_HEAP_LIST_SIZE]
 

Definition at line 61 of file heapdll.c.

Referenced by RtlInitializeHeapManager(), and RtlpAddHeapToProcessList().

HEAP_LOCK RtlpProcessHeapsListLock
 

Definition at line 53 of file heapdll.c.

Referenced by RtlEnumProcessHeaps(), RtlGetProcessHeaps(), RtlInitializeHeapManager(), RtlpAddHeapToProcessList(), and RtlpRemoveHeapFromProcessList().

WCHAR RtlpPseudoTagNameBuffer[24] [static]
 

Definition at line 75 of file heapdll.c.

Referenced by RtlpGetTagName().


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