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

heappriv.h File Reference

#include "heappage.h"

Go to the source code of this file.

Classes

struct  _HEAP_LOOKASIDE

Defines

#define HEAPASSERT(exp)
#define PREALLOCATE_EVENT_MASK   0x80000000
#define RtlInitializeLockRoutine(L)   RtlInitializeCriticalSectionAndSpinCount((PRTL_CRITICAL_SECTION)(L),(PREALLOCATE_EVENT_MASK | 4000))
#define RtlAcquireLockRoutine(L)   RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)(L))
#define RtlReleaseLockRoutine(L)   RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)(L))
#define RtlDeleteLockRoutine(L)   RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)(L))
#define RtlOkayToLockRoutine(L)   NtdllOkayToLockRoutine((PVOID)(L))
#define HEAP_DEBUG_FLAGS
#define DEBUG_HEAP(F)   ((F & HEAP_DEBUG_FLAGS) && !(F & HEAP_SKIP_VALIDATION_CHECKS))
#define SET_LAST_STATUS(S)   {NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError( NtCurrentTeb()->LastStatusValue = (ULONG)(S) );}
#define HeapDebugPrint(_x_)
#define HeapDebugBreak(_x_)
#define SET_FREELIST_BIT(H, FB)
#define CLEAR_FREELIST_BIT(H, FB)
#define RtlpInsertFreeBlockDirect(H, FB, SIZE)
#define RtlpFastInsertFreeBlockDirect(H, FB, SIZE)
#define RtlpFastInsertDedicatedFreeBlockDirect(H, FB, SIZE)
#define RtlpFastInsertNonDedicatedFreeBlockDirect(H, FB, SIZE)
#define RtlpRemoveFreeBlock(H, FB)
#define RtlpFastRemoveFreeBlock(H, FB)
#define RtlpFastRemoveDedicatedFreeBlock(H, FB)
#define RtlpFastRemoveNonDedicatedFreeBlock(H, FB)
#define IS_HEAP_TAGGING_ENABLED()   (RtlGetNtGlobalFlags() & FLG_HEAP_ENABLE_TAGGING)

Typedefs

typedef enum _HEAP_TAG_ACTION HEAP_TAG_ACTION
typedef _HEAP_LOOKASIDE HEAP_LOOKASIDE
typedef _HEAP_LOOKASIDEPHEAP_LOOKASIDE

Enumerations

enum  _HEAP_TAG_ACTION {
  AllocationAction, VirtualAllocationAction, FreeAction, VirtualFreeAction,
  ReAllocationAction, VirtualReAllocationAction
}

Functions

BOOLEAN RtlpInitializeHeapSegment (IN PHEAP Heap, IN PHEAP_SEGMENT Segment, IN UCHAR SegmentIndex, IN ULONG Flags, IN PVOID BaseAddress, IN PVOID UnCommittedAddress, IN PVOID CommitLimitAddress)
PHEAP_FREE_ENTRY RtlpCoalesceFreeBlocks (IN PHEAP Heap, IN PHEAP_FREE_ENTRY FreeBlock, IN OUT PSIZE_T FreeSize, IN BOOLEAN RemoveFromFreeList)
VOID RtlpDeCommitFreeBlock (IN PHEAP Heap, IN PHEAP_FREE_ENTRY FreeBlock, IN SIZE_T FreeSize)
VOID RtlpInsertFreeBlock (IN PHEAP Heap, IN PHEAP_FREE_ENTRY FreeBlock, IN SIZE_T FreeSize)
PHEAP_FREE_ENTRY RtlpFindAndCommitPages (IN PHEAP Heap, IN PHEAP_SEGMENT Segment, IN OUT PSIZE_T Size, IN PVOID AddressWanted OPTIONAL)
PVOID RtlAllocateHeapSlowly (IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
BOOLEAN RtlFreeHeapSlowly (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress)
SIZE_T RtlpGetSizeOfBigBlock (IN PHEAP_ENTRY BusyBlock)
PHEAP_ENTRY_EXTRA RtlpGetExtraStuffPointer (PHEAP_ENTRY BusyBlock)
BOOLEAN RtlpCheckBusyBlockTail (IN PHEAP_ENTRY BusyBlock)
VOID RtlpAddHeapToProcessList (IN PHEAP Heap)
VOID RtlpRemoveHeapFromProcessList (IN PHEAP Heap)
PHEAP_FREE_ENTRY RtlpCoalesceHeap (IN PHEAP Heap)
BOOLEAN RtlpCheckHeapSignature (IN PHEAP Heap, IN PCHAR Caller)
BOOLEAN RtlpValidateHeapEntry (IN PHEAP Heap, IN PHEAP_ENTRY BusyBlock, IN PCHAR Reason)
BOOLEAN RtlpValidateHeap (IN PHEAP Heap, IN BOOLEAN AlwaysValidate)
VOID RtlpUpdateHeapListIndex (USHORT OldIndex, USHORT NewIndex)
BOOLEAN RtlpValidateHeapHeaders (IN PHEAP Heap, IN BOOLEAN Recompute)
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)
NTKERNELAPI VOID RtlpInitializeHeapLookaside (IN PHEAP_LOOKASIDE Lookaside, IN USHORT Depth)
NTKERNELAPI VOID RtlpDeleteHeapLookaside (IN PHEAP_LOOKASIDE Lookaside)
VOID RtlpAdjustHeapLookasideDepth (IN PHEAP_LOOKASIDE Lookaside)
NTKERNELAPI PVOID RtlpAllocateFromHeapLookaside (IN PHEAP_LOOKASIDE Lookaside)
NTKERNELAPI BOOLEAN RtlpFreeToHeapLookaside (IN PHEAP_LOOKASIDE Lookaside, IN PVOID Entry)

Variables

UCHAR CheckHeapFillPattern [CHECK_HEAP_TAIL_SIZE]


Define Documentation

#define CLEAR_FREELIST_BIT H,
FB   ) 
 

Value:

{ \ ULONG _Index_; \ ULONG _Bit_; \ \ HEAPASSERT((FB)->Size < HEAP_MAXIMUM_FREELISTS); \ \ _Index_ = (FB)->Size >> 3; \ _Bit_ = (1 << ((FB)->Size & 7)); \ \ HEAPASSERT((H)->u.FreeListsInUseBytes[ _Index_ ] & _Bit_); \ HEAPASSERT(IsListEmpty(&(H)->FreeLists[ (FB)->Size ])); \ \ (H)->u.FreeListsInUseBytes[ _Index_ ] ^= _Bit_; \ }

Definition at line 300 of file heappriv.h.

#define DEBUG_HEAP  )     ((F & HEAP_DEBUG_FLAGS) && !(F & HEAP_SKIP_VALIDATION_CHECKS))
 

Definition at line 103 of file heappriv.h.

Referenced by RtlAllocateHeapSlowly(), RtlCompactHeap(), RtlCreateHeap(), RtlCreateTagHeap(), RtlDestroyHeap(), RtlFreeHeapSlowly(), RtlGetUserInfoHeap(), RtlpGrowBlockInPlace(), RtlQueryTagHeap(), RtlReAllocateHeap(), RtlSetUserFlagsHeap(), RtlSetUserValueHeap(), RtlSizeHeap(), RtlUsageHeap(), RtlWalkHeap(), and RtlZeroHeap().

#define HEAP_DEBUG_FLAGS
 

Value:

Definition at line 98 of file heappriv.h.

#define HEAPASSERT exp   ) 
 

Definition at line 39 of file heappriv.h.

Referenced by RtlFreeHeap(), RtlFreeHeapSlowly(), and RtlpCoalesceFreeBlocks().

#define HeapDebugBreak _x_   ) 
 

Value:

{ \ VOID RtlpBreakPointHeap( PVOID BadAddress ); \ \ RtlpBreakPointHeap( (_x_) ); \ }

Definition at line 134 of file heappriv.h.

Referenced by RtlCreateHeap(), RtlDebugAllocateHeap(), RtlDebugCreateHeap(), RtlDebugFreeHeap(), RtlDebugReAllocateHeap(), RtlInitializeHeapManager(), RtlpCheckBusyBlockTail(), RtlpCheckHeapSignature(), RtlpFindAndCommitPages(), RtlpValidateHeap(), RtlpValidateHeapEntry(), and RtlReAllocateHeap().

#define HeapDebugPrint _x_   ) 
 

Value:

{ \ PLIST_ENTRY _Module; \ PLDR_DATA_TABLE_ENTRY _Entry; \ \ _Module = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink; \ _Entry = CONTAINING_RECORD( _Module, \ LDR_DATA_TABLE_ENTRY, \ InLoadOrderLinks); \ DbgPrint("HEAP[%wZ]: ", &_Entry->BaseDllName); \ DbgPrint _x_; \ }

Definition at line 121 of file heappriv.h.

Referenced by RtlCreateHeap(), RtlDebugAllocateHeap(), RtlDebugCreateHeap(), RtlDebugDestroyHeap(), RtlDebugFreeHeap(), RtlDebugReAllocateHeap(), RtlDestroyHeap(), RtlInitializeHeapManager(), RtlpCheckBusyBlockTail(), RtlpCheckHeapSignature(), RtlpDeCommitFreeBlock(), RtlpFindAndCommitPages(), RtlpInsertUnCommittedPages(), RtlProtectHeap(), RtlpValidateHeap(), RtlpValidateHeapEntry(), RtlpValidateHeapHeaders(), RtlpValidateHeapSegment(), and RtlReAllocateHeap().

 
#define IS_HEAP_TAGGING_ENABLED  )     (RtlGetNtGlobalFlags() & FLG_HEAP_ENABLE_TAGGING)
 

Definition at line 563 of file heappriv.h.

Referenced by RtlAllocateHeapSlowly(), RtlCreateHeap(), RtlCreateTagHeap(), RtlDebugAllocateHeap(), RtlDebugFreeHeap(), RtlDebugReAllocateHeap(), RtlFreeHeapSlowly(), RtlpGrowBlockInPlace(), RtlQueryTagHeap(), RtlReAllocateHeap(), RtlUsageHeap(), and RtlWalkHeap().

#define PREALLOCATE_EVENT_MASK   0x80000000
 

Definition at line 73 of file heappriv.h.

#define RtlAcquireLockRoutine  )     RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)(L))
 

Definition at line 78 of file heappriv.h.

Referenced by RtlAllocateHeap(), RtlAllocateHeapSlowly(), RtlCompactHeap(), RtlCreateTagHeap(), RtlDebugAllocateHeap(), RtlDebugCompactHeap(), RtlDebugCreateTagHeap(), RtlDebugFreeHeap(), RtlDebugGetUserInfoHeap(), RtlDebugQueryTagHeap(), RtlDebugReAllocateHeap(), RtlDebugSetUserFlagsHeap(), RtlDebugSetUserValueHeap(), RtlDebugSizeHeap(), RtlDebugUsageHeap(), RtlDebugZeroHeap(), RtlEnumProcessHeaps(), RtlExtendHeap(), RtlFreeHeap(), RtlFreeHeapSlowly(), RtlGetProcessHeaps(), RtlGetUserInfoHeap(), RtlLockHeap(), RtlpAddHeapToProcessList(), RtlpRemoveHeapFromProcessList(), RtlQueryTagHeap(), RtlReAllocateHeap(), RtlSetUserFlagsHeap(), RtlSetUserValueHeap(), RtlUsageHeap(), RtlValidateHeap(), and RtlZeroHeap().

#define RtlDeleteLockRoutine  )     RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)(L))
 

Definition at line 80 of file heappriv.h.

Referenced by RtlDestroyHeap().

#define RtlInitializeLockRoutine  )     RtlInitializeCriticalSectionAndSpinCount((PRTL_CRITICAL_SECTION)(L),(PREALLOCATE_EVENT_MASK | 4000))
 

Definition at line 77 of file heappriv.h.

Referenced by RtlCreateHeap(), RtlInitializeHeapManager(), and RtlpSerializeHeap().

#define RtlOkayToLockRoutine  )     NtdllOkayToLockRoutine((PVOID)(L))
 

Definition at line 81 of file heappriv.h.

#define RtlpFastInsertDedicatedFreeBlockDirect H,
FB,
SIZE   ) 
 

Value:

{ \ PLIST_ENTRY _HEAD; \ \ HEAPASSERT((FB)->Size == (SIZE)); \ \ if (!((FB)->Flags & HEAP_ENTRY_LAST_ENTRY)) { \ \ HEAPASSERT(((PHEAP_ENTRY)(FB) + (SIZE))->PreviousSize == (SIZE)); \ } \ \ (FB)->Flags &= HEAP_ENTRY_LAST_ENTRY; \ \ _HEAD = &(H)->FreeLists[ (SIZE) ]; \ \ if (IsListEmpty(_HEAD)) { \ \ SET_FREELIST_BIT( H, FB ); \ } \ \ InsertTailList( _HEAD, &(FB)->FreeList ); \ }

Definition at line 397 of file heappriv.h.

Referenced by RtlFreeHeap().

#define RtlpFastInsertFreeBlockDirect H,
FB,
SIZE   ) 
 

Value:

{ \ if ((SIZE) < HEAP_MAXIMUM_FREELISTS) { \ \ RtlpFastInsertDedicatedFreeBlockDirect( H, FB, SIZE ); \ \ } else { \ \ RtlpFastInsertNonDedicatedFreeBlockDirect( H, FB, SIZE ); \ } \ }

Definition at line 380 of file heappriv.h.

Referenced by RtlAllocateHeap().

#define RtlpFastInsertNonDedicatedFreeBlockDirect H,
FB,
SIZE   ) 
 

Definition at line 425 of file heappriv.h.

Referenced by RtlFreeHeap().

#define RtlpFastRemoveDedicatedFreeBlock H,
FB   ) 
 

Value:

{ \ PLIST_ENTRY _EX_Blink; \ PLIST_ENTRY _EX_Flink; \ \ _EX_Flink = (FB)->FreeList.Flink; \ _EX_Blink = (FB)->FreeList.Blink; \ \ _EX_Blink->Flink = _EX_Flink; \ _EX_Flink->Blink = _EX_Blink; \ \ if (_EX_Flink == _EX_Blink) { \ \ CLEAR_FREELIST_BIT( H, FB ); \ } \ }

Definition at line 525 of file heappriv.h.

Referenced by RtlAllocateHeap().

#define RtlpFastRemoveFreeBlock H,
FB   ) 
 

Value:

{ \ PLIST_ENTRY _EX_Blink; \ PLIST_ENTRY _EX_Flink; \ \ _EX_Flink = (FB)->FreeList.Flink; \ _EX_Blink = (FB)->FreeList.Blink; \ \ _EX_Blink->Flink = _EX_Flink; \ _EX_Flink->Blink = _EX_Blink; \ \ if ((_EX_Flink == _EX_Blink) && \ ((FB)->Size < HEAP_MAXIMUM_FREELISTS)) { \ \ CLEAR_FREELIST_BIT( H, FB ); \ } \ }

Definition at line 502 of file heappriv.h.

Referenced by RtlAllocateHeap().

#define RtlpFastRemoveNonDedicatedFreeBlock H,
FB   ) 
 

Value:

{ \ RemoveEntryList(&(FB)->FreeList) \ }

Definition at line 547 of file heappriv.h.

Referenced by RtlAllocateHeap().

#define RtlpInsertFreeBlockDirect H,
FB,
SIZE   ) 
 

Definition at line 322 of file heappriv.h.

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

#define RtlpRemoveFreeBlock H,
FB   ) 
 

Definition at line 465 of file heappriv.h.

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

#define RtlReleaseLockRoutine  )     RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)(L))
 

Definition at line 79 of file heappriv.h.

Referenced by RtlAllocateHeap(), RtlAllocateHeapSlowly(), RtlCompactHeap(), RtlCreateTagHeap(), RtlDebugAllocateHeap(), RtlDebugCompactHeap(), RtlDebugCreateTagHeap(), RtlDebugFreeHeap(), RtlDebugGetUserInfoHeap(), RtlDebugQueryTagHeap(), RtlDebugReAllocateHeap(), RtlDebugSetUserFlagsHeap(), RtlDebugSetUserValueHeap(), RtlDebugSizeHeap(), RtlDebugUsageHeap(), RtlDebugZeroHeap(), RtlEnumProcessHeaps(), RtlExtendHeap(), RtlFreeHeap(), RtlFreeHeapSlowly(), RtlGetProcessHeaps(), RtlGetUserInfoHeap(), RtlpAddHeapToProcessList(), RtlpRemoveHeapFromProcessList(), RtlQueryTagHeap(), RtlReAllocateHeap(), RtlSetUserFlagsHeap(), RtlSetUserValueHeap(), RtlUnlockHeap(), RtlUsageHeap(), RtlValidateHeap(), and RtlZeroHeap().

#define SET_FREELIST_BIT H,
FB   ) 
 

Value:

{ \ ULONG _Index_; \ ULONG _Bit_; \ \ HEAPASSERT((FB)->Size < HEAP_MAXIMUM_FREELISTS); \ \ _Index_ = (FB)->Size >> 3; \ _Bit_ = (1 << ((FB)->Size & 7)); \ \ HEAPASSERT(((H)->u.FreeListsInUseBytes[ _Index_ ] & _Bit_) == 0); \ \ (H)->u.FreeListsInUseBytes[ _Index_ ] |= _Bit_; \ }

Definition at line 280 of file heappriv.h.

#define SET_LAST_STATUS  )     {NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError( NtCurrentTeb()->LastStatusValue = (ULONG)(S) );}
 

Definition at line 104 of file heappriv.h.

Referenced by RtlAllocateHeap(), RtlAllocateHeapSlowly(), RtlCompactHeap(), RtlDebugAllocateHeap(), RtlDebugCompactHeap(), RtlDebugCreateTagHeap(), RtlDebugFreeHeap(), RtlDebugGetUserInfoHeap(), RtlDebugQueryTagHeap(), RtlDebugReAllocateHeap(), RtlDebugSetUserFlagsHeap(), RtlDebugSetUserValueHeap(), RtlDebugSizeHeap(), RtlDebugWalkHeap(), RtlFreeHeap(), RtlFreeHeapSlowly(), RtlGetUserInfoHeap(), RtlReAllocateHeap(), RtlSetUserFlagsHeap(), RtlSetUserValueHeap(), RtlSizeHeap(), and RtlValidateHeap().


Typedef Documentation

typedef struct _HEAP_LOOKASIDE HEAP_LOOKASIDE
 

Referenced by RtlCreateHeap().

typedef enum _HEAP_TAG_ACTION HEAP_TAG_ACTION
 

Referenced by RtlpUpdateTagEntry().

typedef struct _HEAP_LOOKASIDE * PHEAP_LOOKASIDE
 

Referenced by RtlCreateHeap().


Enumeration Type Documentation

enum _HEAP_TAG_ACTION
 

Enumeration values:
AllocationAction 
VirtualAllocationAction 
FreeAction 
VirtualFreeAction 
ReAllocationAction 
VirtualReAllocationAction 

Definition at line 571 of file heappriv.h.


Function Documentation

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

Definition at line 2075 of file rtl/heap.c.

References _HEAP::AlignMask, _HEAP::AlignRound, ALLOC_HEAP_FILL, AllocationAction, CHECK_HEAP_TAIL_FILL, CHECK_HEAP_TAIL_SIZE, DEBUG_HEAP, EXCEPTION_CONTINUE_SEARCH, EXCEPTION_EXECUTE_HANDLER, FALSE, _HEAP::Flags, _HEAP_ENTRY::Flags, _HEAP_FREE_ENTRY::Flags, _HEAP::FreeLists, HEAP_ENTRY_BUSY, HEAP_ENTRY_EXTRA, HEAP_ENTRY_EXTRA_PRESENT, HEAP_ENTRY_FILL_PATTERN, HEAP_ENTRY_LAST_ENTRY, HEAP_ENTRY_VIRTUAL_ALLOC, HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_BLOCK_SIZE, HEAP_MAXIMUM_FREELISTS, HEAP_NEED_EXTRA_FLAGS, HEAP_SMALL_TAG_MASK, HeapHandle, IS_HEAP_TAGGING_ENABLED, _HEAP_SEGMENT::LastEntryInSegment, _HEAP::LockVariable, NT_SUCCESS, NTSTATUS(), NULL, PHEAP_ENTRY_EXTRA, _HEAP_FREE_ENTRY::PreviousSize, _HEAP::PseudoTagEntries, RTL_PAGED_CODE, RtlAcquireLockRoutine, RtlDebugAllocateHeap(), RtlFindFirstSetRightMember, RtlpExtendHeap(), RtlpGetExtraStuffPointer(), RtlpInsertFreeBlock(), RtlpInsertFreeBlockDirect, RtlpRemoveFreeBlock, RtlpUpdateTagEntry(), RtlRaiseException(), RtlReleaseLockRoutine, _HEAP_ENTRY::SegmentIndex, _HEAP_FREE_ENTRY::SegmentIndex, _HEAP::Segments, SET_LAST_STATUS, _HEAP_ENTRY::Size, _HEAP_FREE_ENTRY::Size, Size, Status, _HEAP::TotalFreeSize, TRUE, _HEAP::u, _HEAP_ENTRY::UnusedBytes, USHORT, VirtualAllocationAction, _HEAP::VirtualAllocdBlocks, and _HEAP::VirtualMemoryThreshold.

Referenced by RtlAllocateHeap(), and RtlDebugAllocateHeap().

02083 : 02084 02085 This routine does the equivalent of Rtl Allocate Heap but it does it will 02086 additional heap consistency checking logic and tagging. 02087 02088 Arguments: 02089 02090 HeapHandle - Supplies a pointer to an initialized heap structure 02091 02092 Flags - Specifies the set of flags to use to control the allocation 02093 02094 Size - Specifies the size, in bytes, of the allocation 02095 02096 Return Value: 02097 02098 PVOID - returns a pointer to the newly allocated block 02099 02100 --*/ 02101 02102 { 02103 PHEAP Heap = (PHEAP)HeapHandle; 02104 BOOLEAN LockAcquired = FALSE; 02105 PVOID ReturnValue = NULL; 02106 PULONG FreeListsInUse; 02107 ULONG FreeListsInUseUlong; 02108 SIZE_T AllocationSize; 02109 SIZE_T FreeSize, AllocationIndex; 02110 UCHAR EntryFlags, FreeFlags; 02111 PLIST_ENTRY FreeListHead, Next; 02112 PHEAP_ENTRY BusyBlock; 02113 PHEAP_FREE_ENTRY FreeBlock, SplitBlock, SplitBlock2; 02114 PHEAP_ENTRY_EXTRA ExtraStuff; 02115 NTSTATUS Status; 02116 EXCEPTION_RECORD ExceptionRecord; 02117 SIZE_T ZeroSize = 0; 02118 02119 RTL_PAGED_CODE(); 02120 02121 // 02122 // Note that Flags has already been OR'd with Heap->ForceFlags. 02123 // 02124 02125 #ifndef NTOS_KERNEL_RUNTIME 02126 02127 // 02128 // In the non kernel case check if we should be using the debug version 02129 // of heap allocation 02130 // 02131 02132 if (DEBUG_HEAP( Flags )) { 02133 02134 return RtlDebugAllocateHeap( HeapHandle, Flags, Size ); 02135 } 02136 02137 #endif // NTOS_KERNEL_RUNTIME 02138 02139 // 02140 // If the size is greater than maxlong then say we can't allocate that 02141 // much and return the error to our caller 02142 // 02143 02144 if (Size > 0x7fffffff) { 02145 02146 SET_LAST_STATUS( STATUS_NO_MEMORY ); 02147 02148 return NULL; 02149 } 02150 02151 // 02152 // Round up the requested size to the allocation granularity. Note 02153 // that if the request is for zero bytes we will still allocate memory, 02154 // 02155 // Allocation size will be either 16, 24, 32, ... 02156 // Allocation index will be 2, 3, 4, ... 02157 // 02158 02159 AllocationSize = ((Size ? Size : 1) + Heap->AlignRound) & Heap->AlignMask; 02160 02161 // 02162 // Generate the flags needed for this heap entry. Mark it busy and add 02163 // any user settable bits. Also if the input flag indicates any entry 02164 // extra fields and we have a tag to use then make room for the extra 02165 // fields in the heap entry 02166 // 02167 02168 EntryFlags = (UCHAR)(HEAP_ENTRY_BUSY | ((Flags & HEAP_SETTABLE_USER_FLAGS) >> 4)); 02169 02170 if ((Flags & HEAP_NEED_EXTRA_FLAGS) || (Heap->PseudoTagEntries != NULL)) { 02171 02172 EntryFlags |= HEAP_ENTRY_EXTRA_PRESENT; 02173 AllocationSize += sizeof( HEAP_ENTRY_EXTRA ); 02174 } 02175 02176 AllocationIndex = AllocationSize >> HEAP_GRANULARITY_SHIFT; 02177 02178 try { 02179 02180 // 02181 // Lock the free list. 02182 // 02183 02184 if (!(Flags & HEAP_NO_SERIALIZE)) { 02185 02186 RtlAcquireLockRoutine( Heap->LockVariable ); 02187 02188 LockAcquired = TRUE; 02189 } 02190 02191 // 02192 // Do all the actual heap work under the protection of a try-except clause 02193 // to protect us from corruption 02194 // 02195 02196 try { 02197 02198 // 02199 // If the allocation index is less than the maximum free list size 02200 // then we can use the index to check the free list otherwise we have 02201 // to either pull the entry off of the [0] index list or allocate 02202 // memory directly for this request. 02203 // 02204 02205 if (AllocationIndex < HEAP_MAXIMUM_FREELISTS) { 02206 02207 // 02208 // With a size that matches a free list size grab the head 02209 // of the list and check if there is an available entry 02210 // 02211 02212 FreeListHead = &Heap->FreeLists[ AllocationIndex ]; 02213 02214 if ( !IsListEmpty( FreeListHead )) { 02215 02216 // 02217 // We're in luck the list has an entry so now get the free 02218 // entry, copy its flags, remove it from the free list 02219 // 02220 02221 FreeBlock = CONTAINING_RECORD( FreeListHead->Flink, 02222 HEAP_FREE_ENTRY, 02223 FreeList ); 02224 02225 FreeFlags = FreeBlock->Flags; 02226 02227 RtlpRemoveFreeBlock( Heap, FreeBlock ); 02228 02229 // 02230 // Adjust the total number of bytes free in the heap 02231 // 02232 02233 Heap->TotalFreeSize -= AllocationIndex; 02234 02235 // 02236 // Mark the block as busy and and set the number of bytes 02237 // unused and tag index. Also if it is the last entry 02238 // then keep that flag. 02239 // 02240 02241 BusyBlock = (PHEAP_ENTRY)FreeBlock; 02242 BusyBlock->Flags = EntryFlags | (FreeFlags & HEAP_ENTRY_LAST_ENTRY); 02243 BusyBlock->UnusedBytes = (UCHAR)(AllocationSize - Size); 02244 02245 } else { 02246 02247 // 02248 // The free list that matches our request is empty. We know 02249 // that there are 128 free lists managed by a 4 ulong bitmap. 02250 // The next big if-else-if statement will decide which ulong 02251 // we tackle 02252 // 02253 // Check if the requested allocation index within the first 02254 // quarter of the free lists. 02255 // 02256 02257 if (AllocationIndex < (HEAP_MAXIMUM_FREELISTS * 1) / 4) { 02258 02259 // 02260 // Grab a pointer to the corresponding bitmap ulong, and 02261 // then get the bit we're actually interested in to be the 02262 // first bit of the ulong. 02263 // 02264 02265 FreeListsInUse = &Heap->u.FreeListsInUseUlong[ 0 ]; 02266 FreeListsInUseUlong = *FreeListsInUse++ >> ((ULONG) AllocationIndex & 0x1F); 02267 02268 // 02269 // If the remaining bitmap has any bits set then we know 02270 // there is a non empty list that is larger than our 02271 // requested index so find that bit and compute the list 02272 // head of the next non empty list 02273 // 02274 02275 if (FreeListsInUseUlong) { 02276 02277 FreeListHead += RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02278 02279 } else { 02280 02281 // 02282 // The rest of the first ulong is all zeros so we need 02283 // to move to the second ulong 02284 // 02285 02286 FreeListsInUseUlong = *FreeListsInUse++; 02287 02288 // 02289 // Check if the second ulong has any bits set and if 02290 // so then compute the list head of the next non empty 02291 // list 02292 // 02293 02294 if (FreeListsInUseUlong) { 02295 02296 FreeListHead += ((HEAP_MAXIMUM_FREELISTS * 1) / 4) - 02297 (AllocationIndex & 0x1F) + 02298 RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02299 02300 } else { 02301 02302 // 02303 // Do the same test for the third ulong 02304 // 02305 02306 FreeListsInUseUlong = *FreeListsInUse++; 02307 02308 if (FreeListsInUseUlong) { 02309 02310 FreeListHead += ((HEAP_MAXIMUM_FREELISTS * 2) / 4) - 02311 (AllocationIndex & 0x1F) + 02312 RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02313 02314 } else { 02315 02316 // 02317 // Repeat the test for the forth ulong, and if 02318 // that one is also empty then we need to grab 02319 // the allocation off of the [0] index list 02320 // 02321 02322 FreeListsInUseUlong = *FreeListsInUse++; 02323 02324 if (FreeListsInUseUlong) { 02325 02326 FreeListHead += ((HEAP_MAXIMUM_FREELISTS * 3) / 4) - 02327 (AllocationIndex & 0x1F) + 02328 RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02329 02330 } else { 02331 02332 goto LookInNonDedicatedList; 02333 } 02334 } 02335 } 02336 } 02337 02338 // 02339 // Otherwise check if the requested allocation index lies 02340 // within the second quarter of the free lists. We repeat the 02341 // test just like we did above on the second, third, and forth 02342 // bitmap ulongs. 02343 // 02344 02345 } else if (AllocationIndex < (HEAP_MAXIMUM_FREELISTS * 2) / 4) { 02346 02347 FreeListsInUse = &Heap->u.FreeListsInUseUlong[ 1 ]; 02348 FreeListsInUseUlong = *FreeListsInUse++ >> ((ULONG) AllocationIndex & 0x1F); 02349 02350 if (FreeListsInUseUlong) { 02351 02352 FreeListHead += RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02353 02354 } else { 02355 02356 FreeListsInUseUlong = *FreeListsInUse++; 02357 02358 if (FreeListsInUseUlong) { 02359 02360 FreeListHead += ((HEAP_MAXIMUM_FREELISTS * 1) / 4) - 02361 (AllocationIndex & 0x1F) + 02362 RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02363 02364 } else { 02365 02366 FreeListsInUseUlong = *FreeListsInUse++; 02367 02368 if (FreeListsInUseUlong) { 02369 02370 FreeListHead += ((HEAP_MAXIMUM_FREELISTS * 2) / 4) - 02371 (AllocationIndex & 0x1F) + 02372 RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02373 02374 } else { 02375 02376 goto LookInNonDedicatedList; 02377 } 02378 } 02379 } 02380 02381 // 02382 // Otherwise check if the requested allocation index lies 02383 // within the third quarter of the free lists. We repeat the 02384 // test just like we did above on the third and forth bitmap 02385 // ulongs 02386 // 02387 02388 } else if (AllocationIndex < (HEAP_MAXIMUM_FREELISTS * 3) / 4) { 02389 02390 FreeListsInUse = &Heap->u.FreeListsInUseUlong[ 2 ]; 02391 FreeListsInUseUlong = *FreeListsInUse++ >> ((ULONG) AllocationIndex & 0x1F); 02392 02393 if (FreeListsInUseUlong) { 02394 02395 FreeListHead += RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02396 02397 } else { 02398 02399 FreeListsInUseUlong = *FreeListsInUse++; 02400 02401 if (FreeListsInUseUlong) { 02402 02403 FreeListHead += ((HEAP_MAXIMUM_FREELISTS * 1) / 4) - 02404 (AllocationIndex & 0x1F) + 02405 RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02406 02407 } else { 02408 02409 goto LookInNonDedicatedList; 02410 } 02411 } 02412 02413 // 02414 // Lastly the requested allocation index must lie within the 02415 // last quarter of the free lists. We repeat the test just 02416 // like we did above on the forth ulong 02417 // 02418 02419 } else { 02420 02421 FreeListsInUse = &Heap->u.FreeListsInUseUlong[ 3 ]; 02422 FreeListsInUseUlong = *FreeListsInUse++ >> ((ULONG) AllocationIndex & 0x1F); 02423 02424 if (FreeListsInUseUlong) { 02425 02426 FreeListHead += RtlFindFirstSetRightMember( FreeListsInUseUlong ); 02427 02428 } else { 02429 02430 goto LookInNonDedicatedList; 02431 } 02432 } 02433 02434 // 02435 // At this point the free list head points to a non empty free 02436 // list that is of greater size than we need. 02437 // 02438 02439 FreeBlock = CONTAINING_RECORD( FreeListHead->Flink, 02440 HEAP_FREE_ENTRY, 02441 FreeList ); 02442 02443 SplitFreeBlock: 02444 02445 // 02446 // Remember the flags that go with this block and remove it 02447 // from its list 02448 // 02449 02450 FreeFlags = FreeBlock->Flags; 02451 02452 RtlpRemoveFreeBlock( Heap, FreeBlock ); 02453 02454 // 02455 // Adjust the amount free in the heap 02456 // 02457 02458 Heap->TotalFreeSize -= FreeBlock->Size; 02459 02460 // 02461 // Mark the block busy 02462 // 02463 02464 BusyBlock = (PHEAP_ENTRY)FreeBlock; 02465 BusyBlock->Flags = EntryFlags; 02466 02467 // 02468 // Compute the size (i.e., index) of the amount from this 02469 // block that we don't need and can return to the free list 02470 // 02471 02472 FreeSize = BusyBlock->Size - AllocationIndex; 02473 02474 // 02475 // Finish setting up the rest of the new busy block 02476 // 02477 02478 BusyBlock->Size = (USHORT)AllocationIndex; 02479 BusyBlock->UnusedBytes = (UCHAR)(AllocationSize - Size); 02480 02481 // 02482 // Now if the size that we are going to free up is not zero 02483 // then lets get to work and to the split. 02484 // 02485 02486 if (FreeSize != 0) { 02487 02488 // 02489 // But first we won't ever bother doing a split that only 02490 // gives us 8 bytes back. So if free size is one then 02491 // just bump up the size of the new busy block 02492 // 02493 02494 if (FreeSize == 1) { 02495 02496 BusyBlock->Size += 1; 02497 BusyBlock->UnusedBytes += sizeof( HEAP_ENTRY ); 02498 02499 } else { 02500 02501 // 02502 // Get a pointer to where the new free block will be. 02503 // When we split a block the first part goes to the 02504 // new busy block and the second part goes back to the 02505 // free list 02506 // 02507 02508 SplitBlock = (PHEAP_FREE_ENTRY)(BusyBlock + AllocationIndex); 02509 02510 // 02511 // Reset the flags that we copied from the original 02512 // free list header, and set it other size fields. 02513 // 02514 02515 SplitBlock->Flags = FreeFlags; 02516 SplitBlock->PreviousSize = (USHORT)AllocationIndex; 02517 SplitBlock->SegmentIndex = BusyBlock->SegmentIndex; 02518 SplitBlock->Size = (USHORT)FreeSize; 02519 02520 // 02521 // If nothing else follows this entry then we will 02522 // insert this into the corresponding free list 02523 // 02524 02525 if (FreeFlags & HEAP_ENTRY_LAST_ENTRY) { 02526 02527 RtlpInsertFreeBlockDirect( Heap, SplitBlock, (USHORT)FreeSize ); 02528 02529 Heap->TotalFreeSize += FreeSize; 02530 02531 } else { 02532 02533 // 02534 // Otherwise we need to check the following block 02535 // and if it is busy then update its previous size 02536 // before inserting our new free block into the 02537 // free list 02538 // 02539 02540 SplitBlock2 = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize); 02541 02542 if (SplitBlock2->Flags & HEAP_ENTRY_BUSY) { 02543 02544 SplitBlock2->PreviousSize = (USHORT)FreeSize; 02545 02546 RtlpInsertFreeBlockDirect( Heap, SplitBlock, (USHORT)FreeSize ); 02547 02548 Heap->TotalFreeSize += FreeSize; 02549 02550 } else { 02551 02552 // 02553 // The following block is free so we'll merge 02554 // these to blocks. by first merging the flags 02555 // 02556 02557 SplitBlock->Flags = SplitBlock2->Flags; 02558 02559 // 02560 // Removing the second block from its free 02561 // list 02562 // 02563 02564 RtlpRemoveFreeBlock( Heap, SplitBlock2 ); 02565 02566 // 02567 // Updating the free total number of free 02568 // bytes in the heap and updating the size of 02569 // the new free block 02570 // 02571 02572 Heap->TotalFreeSize -= SplitBlock2->Size; 02573 FreeSize += SplitBlock2->Size; 02574 02575 // 02576 // If the new free block is still less than 02577 // the maximum heap block size then we'll 02578 // simply insert it back in the free list 02579 // 02580 02581 if (FreeSize <= HEAP_MAXIMUM_BLOCK_SIZE) { 02582 02583 SplitBlock->Size = (USHORT)FreeSize; 02584 02585 // 02586 // Again check if the new following block 02587 // exists and if so then updsate is 02588 // previous size 02589 // 02590 02591 if (!(SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY)) { 02592 02593 ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize))->PreviousSize = (USHORT)FreeSize; 02594 } 02595 02596 // 02597 // Insert the new free block into the free 02598 // list and update the free heap size 02599 // 02600 02601 RtlpInsertFreeBlockDirect( Heap, SplitBlock, (USHORT)FreeSize ); 02602 02603 Heap->TotalFreeSize += FreeSize; 02604 02605 } else { 02606 02607 // 02608 // The new free block is pretty large so 02609 // we need to call a private routine to do 02610 // the insert 02611 // 02612 02613 RtlpInsertFreeBlock( Heap, SplitBlock, FreeSize ); 02614 } 02615 } 02616 } 02617 02618 // 02619 // Now that free flags made it back into a free block 02620 // we can zero out what we saved. 02621 // 02622 02623 FreeFlags = 0; 02624 02625 // 02626 // If splitblock now last, update LastEntryInSegment 02627 // 02628 02629 if (SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY) { 02630 02631 PHEAP_SEGMENT Segment; 02632 02633 Segment = Heap->Segments[SplitBlock->SegmentIndex]; 02634 Segment->LastEntryInSegment = (PHEAP_ENTRY)SplitBlock; 02635 } 02636 02637 } 02638 } 02639 02640 // 02641 // If there are no following entries then mark the new block 02642 // as such 02643 // 02644 02645 if (FreeFlags & HEAP_ENTRY_LAST_ENTRY) { 02646 02647 BusyBlock->Flags |= HEAP_ENTRY_LAST_ENTRY; 02648 } 02649 } 02650 02651 // 02652 // Return the address of the user portion of the allocated block. 02653 // This is the byte following the header. 02654 // 02655 02656 ReturnValue = BusyBlock + 1; 02657 02658 // 02659 // If the flags indicate that we should zero memory then 02660 // remember how much to zero. We'll do the zeroing later 02661 // 02662 02663 if (Flags & HEAP_ZERO_MEMORY) { 02664 02665 ZeroSize = Size; 02666 02667 // 02668 // Otherwise if the flags indicate that we should fill heap then 02669 // it it now. 02670 // 02671 02672 } else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED) { 02673 02674 RtlFillMemoryUlong( (PCHAR)(BusyBlock + 1), Size & ~0x3, ALLOC_HEAP_FILL ); 02675 } 02676 02677 // 02678 // If the flags indicate that we should do tail checking then copy 02679 // the fill pattern right after the heap block. 02680 // 02681 02682 if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED) { 02683 02684 RtlFillMemory( (PCHAR)ReturnValue + Size, 02685 CHECK_HEAP_TAIL_SIZE, 02686 CHECK_HEAP_TAIL_FILL ); 02687 02688 BusyBlock->Flags |= HEAP_ENTRY_FILL_PATTERN; 02689 } 02690 02691 BusyBlock->SmallTagIndex = 0; 02692 02693 // 02694 // If the flags indicate that there is an extra block persent then 02695 // we'll fill it in 02696 // 02697 02698 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 02699 02700 ExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 02701 02702 RtlZeroMemory( ExtraStuff, sizeof( *ExtraStuff )); 02703 02704 #ifndef NTOS_KERNEL_RUNTIME 02705 02706 // 02707 // In the non kernel case the tagging goes in either the extra 02708 // stuff of the busy block small tag index 02709 // 02710 02711 if (IS_HEAP_TAGGING_ENABLED()) { 02712 02713 ExtraStuff->TagIndex = RtlpUpdateTagEntry( Heap, 02714 (USHORT)((Flags & HEAP_TAG_MASK) >> HEAP_TAG_SHIFT), 02715 0, 02716 BusyBlock->Size, 02717 AllocationAction ); 02718 } 02719 02720 } else if (IS_HEAP_TAGGING_ENABLED()) { 02721 02722 BusyBlock->SmallTagIndex = (UCHAR)RtlpUpdateTagEntry( Heap, 02723 (USHORT)((Flags & HEAP_SMALL_TAG_MASK) >> HEAP_TAG_SHIFT), 02724 0, 02725 BusyBlock->Size, 02726 AllocationAction ); 02727 02728 #endif // NTOS_KERNEL_RUNTIME 02729 02730 } 02731 02732 // 02733 // Return the address of the user portion of the allocated block. 02734 // This is the byte following the header. 02735 // 02736 02737 leave; 02738 02739 // 02740 // Otherwise the allocation request is bigger than the last dedicated 02741 // free list size. Now check if the size is within our threshold. 02742 // Meaning that it could be in the [0] free list 02743 // 02744 02745 } else if (AllocationIndex <= Heap->VirtualMemoryThreshold) { 02746 02747 LookInNonDedicatedList: 02748 02749 // 02750 // The following code cycles through the [0] free list until 02751 // it finds a block that satisfies the request. The list 02752 // is sorted so the search is can be terminated early on success 02753 // 02754 02755 FreeListHead = &Heap->FreeLists[ 0 ]; 02756 Next = FreeListHead->Flink; 02757 02758 while (FreeListHead != Next) { 02759 02760 FreeBlock = CONTAINING_RECORD( Next, HEAP_FREE_ENTRY, FreeList ); 02761 02762 if (FreeBlock->Size >= AllocationIndex) { 02763 02764 // 02765 // We've found something that we can use so now go to 02766 // where we treat spliting a free block. Note that 02767 // the block we found here might actually be the exact 02768 // size we need and that is why in the split free block 02769 // case we have to consider having nothing free after the 02770 // split 02771 // 02772 02773 goto SplitFreeBlock; 02774 02775 } else { 02776 02777 Next = Next->Flink; 02778 } 02779 } 02780 02781 // 02782 // The [0] list is either empty or everything is too small 02783 // so now extend the heap which should get us something less 02784 // than or equal to the virtual memory threshold 02785 // 02786 02787 FreeBlock = RtlpExtendHeap( Heap, AllocationSize ); 02788 02789 // 02790 // And provided we got something we'll treat it just like the 02791 // previous split free block cases 02792 // 02793 02794 if (FreeBlock != NULL) { 02795 02796 goto SplitFreeBlock; 02797 } 02798 02799 // 02800 // We weren't able to extend the heap so we must be out of memory 02801 // 02802 02803 Status = STATUS_NO_MEMORY; 02804 02805 // 02806 // At this point the allocation is way too big for any of the free 02807 // lists and we can only satisfy this request if the heap is growable 02808 // 02809 02810 } else if (Heap->Flags & HEAP_GROWABLE) { 02811 02812 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock; 02813 02814 VirtualAllocBlock = NULL; 02815 02816 // 02817 // Compute how much memory we will need for this allocation which 02818 // will include the allocation size plus a header, and then go 02819 // get the committed memory 02820 // 02821 02822 AllocationSize += FIELD_OFFSET( HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock ); 02823 02824 Status = ZwAllocateVirtualMemory( NtCurrentProcess(), 02825 (PVOID *)&VirtualAllocBlock, 02826 0, 02827 &AllocationSize, 02828 MEM_COMMIT, 02829 PAGE_READWRITE ); 02830 02831 if (NT_SUCCESS( Status )) { 02832 02833 // 02834 // Just committed, already zero. Fill in the new block 02835 // and insert it in the list of big allocation 02836 // 02837 02838 VirtualAllocBlock->BusyBlock.Size = (USHORT)(AllocationSize - Size); 02839 VirtualAllocBlock->BusyBlock.Flags = EntryFlags | HEAP_ENTRY_VIRTUAL_ALLOC | HEAP_ENTRY_EXTRA_PRESENT; 02840 VirtualAllocBlock->CommitSize = AllocationSize; 02841 VirtualAllocBlock->ReserveSize = AllocationSize; 02842 02843 #ifndef NTOS_KERNEL_RUNTIME 02844 02845 // 02846 // In the non kernel case see if we need to add heap tagging 02847 // 02848 02849 if (IS_HEAP_TAGGING_ENABLED()) { 02850 02851 VirtualAllocBlock->ExtraStuff.TagIndex = 02852 RtlpUpdateTagEntry( Heap, 02853 (USHORT)((Flags & HEAP_SMALL_TAG_MASK) >> HEAP_TAG_SHIFT), 02854 0, 02855 VirtualAllocBlock->CommitSize >> HEAP_GRANULARITY_SHIFT, 02856 VirtualAllocationAction ); 02857 } 02858 02859 #endif // NTOS_KERNEL_RUNTIME 02860 02861 InsertTailList( &Heap->VirtualAllocdBlocks, (PLIST_ENTRY)VirtualAllocBlock ); 02862 02863 // 02864 // Return the address of the user portion of the allocated 02865 // block. This is the byte following the header. 02866 // 02867 02868 ReturnValue = (PHEAP_ENTRY)(VirtualAllocBlock + 1); 02869 02870 leave; 02871 } 02872 02873 // 02874 // Otherwise we have an error condition 02875 // 02876 02877 } else { 02878 02879 Status = STATUS_BUFFER_TOO_SMALL; 02880 } 02881 02882 SET_LAST_STATUS( Status ); 02883 02884 if (Flags & HEAP_GENERATE_EXCEPTIONS) { 02885 02886 // 02887 // Construct an exception record. 02888 // 02889 02890 ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY; 02891 ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)NULL; 02892 ExceptionRecord.NumberParameters = 1; 02893 ExceptionRecord.ExceptionFlags = 0; 02894 ExceptionRecord.ExceptionInformation[ 0 ] = AllocationSize; 02895 02896 RtlRaiseException( &ExceptionRecord ); 02897 } 02898 02899 } except( GetExceptionCode() == STATUS_NO_MEMORY ? EXCEPTION_CONTINUE_SEARCH : 02900 EXCEPTION_EXECUTE_HANDLER ) { 02901 02902 SET_LAST_STATUS( GetExceptionCode() ); 02903 } 02904 02905 // 02906 // Check if there is anything to zero out 02907 // 02908 02909 if ( ZeroSize ) { 02910 02911 RtlZeroMemory( ReturnValue, ZeroSize ); 02912 } 02913 02914 } finally { 02915 02916 if (LockAcquired) { 02917 02918 RtlReleaseLockRoutine( Heap->LockVariable ); 02919 } 02920 } 02921 02922 // 02923 // And return to our caller 02924 // 02925 02926 return ReturnValue; 02927 }

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

Definition at line 3273 of file rtl/heap.c.

References _HEAP_VIRTUAL_ALLOC_ENTRY::CommitSize, DEBUG_HEAP, _HEAP::DeCommitFreeBlockThreshold, _HEAP::DeCommitTotalFreeThreshold, _HEAP_VIRTUAL_ALLOC_ENTRY::Entry, EXCEPTION_EXECUTE_HANDLER, _HEAP_VIRTUAL_ALLOC_ENTRY::ExtraStuff, FALSE, _HEAP_FREE_ENTRY::Flags, _HEAP::Flags, _HEAP_ENTRY::Flags, FreeAction, _HEAP_FREE_ENTRY_EXTRA::FreeBackTraceIndex, HEAP_CAPTURE_STACK_BACKTRACES, HEAP_ENTRY_BUSY, HEAP_ENTRY_EXTRA_PRESENT, HEAP_ENTRY_LAST_ENTRY, HEAP_ENTRY_VIRTUAL_ALLOC, HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_BLOCK_SIZE, HEAP_MAXIMUM_SEGMENTS, HEAPASSERT, HeapHandle, IS_HEAP_TAGGING_ENABLED, _HEAP::LockVariable, NT_SUCCESS, NTSTATUS(), PHEAP_FREE_ENTRY_EXTRA, RTL_PAGED_CODE, RtlAcquireLockRoutine, RtlDebugFreeHeap(), RtlpCoalesceFreeBlocks(), RtlpDeCommitFreeBlock(), RtlpInsertFreeBlock(), RtlpInsertFreeBlockDirect, RtlpUpdateTagEntry(), RtlReleaseLockRoutine, _HEAP_ENTRY::SegmentIndex, SET_LAST_STATUS, _HEAP_ENTRY::Size, _HEAP_ENTRY::SmallTagIndex, Status, _HEAP_FREE_ENTRY_EXTRA::TagIndex, _HEAP_ENTRY_EXTRA::TagIndex, _HEAP::TotalFreeSize, TRUE, USHORT, and VirtualFreeAction.

Referenced by RtlDebugFreeHeap(), and RtlFreeHeap().

03281 : 03282 03283 This routine returns a previously allocated block back to its heap. 03284 It is the slower version of Rtl Free Heap and does more checking and 03285 tagging control. 03286 03287 Arguments: 03288 03289 HeapHandle - Supplies a pointer to the owning heap structure 03290 03291 Flags - Specifies the set of flags to use in the deallocation 03292 03293 BaseAddress - Supplies a pointer to the block being freed 03294 03295 Return Value: 03296 03297 BOOLEAN - TRUE if the block was properly freed and FALSE otherwise 03298 03299 --*/ 03300 03301 { 03302 NTSTATUS Status; 03303 PHEAP Heap = (PHEAP)HeapHandle; 03304 PHEAP_ENTRY BusyBlock; 03305 PHEAP_ENTRY_EXTRA ExtraStuff; 03306 SIZE_T FreeSize; 03307 BOOLEAN Result; 03308 BOOLEAN LockAcquired = FALSE; 03309 03310 #ifndef NTOS_KERNEL_RUNTIME 03311 03312 USHORT TagIndex; 03313 03314 #endif // NTOS_KERNEL_RUNTIME 03315 03316 RTL_PAGED_CODE(); 03317 03318 // 03319 // Note that Flags has already been OR'd with Heap->ForceFlags. 03320 // 03321 03322 #ifndef NTOS_KERNEL_RUNTIME 03323 03324 // 03325 // In the non kernel case see if we should be calling the debug version to 03326 // free the heap 03327 // 03328 03329 if (DEBUG_HEAP( Flags )) { 03330 03331 return RtlDebugFreeHeap( HeapHandle, Flags, BaseAddress ); 03332 } 03333 03334 #endif // NTOS_KERNEL_RUNTIME 03335 03336 // 03337 // Until we figure out otherwise we'll assume that this call will fail 03338 // 03339 03340 Result = FALSE; 03341 03342 try { 03343 03344 // 03345 // Lock the heap 03346 // 03347 03348 if (!(Flags & HEAP_NO_SERIALIZE)) { 03349 03350 RtlAcquireLockRoutine( Heap->LockVariable ); 03351 03352 LockAcquired = TRUE; 03353 } 03354 03355 try { 03356 03357 // 03358 // Backup to get a pointer to the start of the block 03359 // 03360 03361 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 03362 03363 // 03364 // Protect ourselves from idiots by refusing to free blocks 03365 // that do not have the busy bit set. 03366 // 03367 // Also refuse to free blocks that are not eight-byte aligned. 03368 // The specific idiot in this case is Office95, which likes 03369 // to free a random pointer when you start Word95 from a desktop 03370 // shortcut. 03371 // 03372 // As further insurance against idiots, check the segment index 03373 // to make sure it is less than HEAP_MAXIMUM_SEGMENTS (16). This 03374 // should fix all the dorks who have ASCII or Unicode where the 03375 // heap header is supposed to be. 03376 // 03377 // Note that this test is just opposite from the test used in 03378 // Rtl Free Heap 03379 // 03380 03381 if ((BusyBlock->Flags & HEAP_ENTRY_BUSY) && 03382 (((ULONG_PTR)BaseAddress & 0x7) == 0) && 03383 (BusyBlock->SegmentIndex < HEAP_MAXIMUM_SEGMENTS)) { 03384 03385 // 03386 // Check if this is a virtual block allocation 03387 // 03388 03389 if (BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) { 03390 03391 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock; 03392 03393 // 03394 // This is a big virtual block allocation. To free it 03395 // we only have to remove it from the heaps list of 03396 // virtual allocated blocks, unlock the heap, and return 03397 // the block to vm 03398 // 03399 03400 VirtualAllocBlock = CONTAINING_RECORD( BusyBlock, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock ); 03401 03402 RemoveEntryList( &VirtualAllocBlock->Entry ); 03403 03404 #ifndef NTOS_KERNEL_RUNTIME 03405 03406 // 03407 // In the non kernel case see if we need to free the tag 03408 // 03409 03410 if (IS_HEAP_TAGGING_ENABLED()) { 03411 03412 RtlpUpdateTagEntry( Heap, 03413 VirtualAllocBlock->ExtraStuff.TagIndex, 03414 VirtualAllocBlock->CommitSize >> HEAP_GRANULARITY_SHIFT, 03415 0, 03416 VirtualFreeAction ); 03417 } 03418 03419 #endif // NTOS_KERNEL_RUNTIME 03420 03421 FreeSize = 0; 03422 03423 Status = ZwFreeVirtualMemory( NtCurrentProcess(), 03424 (PVOID *)&VirtualAllocBlock, 03425 &FreeSize, 03426 MEM_RELEASE ); 03427 03428 // 03429 // Check if everything worked okay, if we had trouble freeing 03430 // the block back to vm return an error if necessary, 03431 // 03432 03433 if (NT_SUCCESS( Status )) { 03434 03435 Result = TRUE; 03436 03437 } else { 03438 03439 SET_LAST_STATUS( Status ); 03440 } 03441 03442 } else { 03443 03444 // 03445 // This block is not a big allocation so we need to 03446 // to get its size, and coalesce the blocks note that 03447 // the user mode heap does this conditionally on a heap 03448 // flag. The coalesce function returns the newly formed 03449 // free block and the new size. 03450 // 03451 03452 #ifndef NTOS_KERNEL_RUNTIME 03453 03454 // 03455 // First in the non kernel case remove any tagging we might 03456 // have been using. Note that the will either be in 03457 // the heap header, or in the extra block if present 03458 // 03459 03460 if (IS_HEAP_TAGGING_ENABLED()) { 03461 03462 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 03463 03464 ExtraStuff = (PHEAP_ENTRY_EXTRA)(BusyBlock + BusyBlock->Size - 1); 03465 03466 TagIndex = RtlpUpdateTagEntry( Heap, 03467 ExtraStuff->TagIndex, 03468 BusyBlock->Size, 03469 0, 03470 FreeAction ); 03471 03472 } else { 03473 03474 TagIndex = RtlpUpdateTagEntry( Heap, 03475 BusyBlock->SmallTagIndex, 03476 BusyBlock->Size, 03477 0, 03478 FreeAction ); 03479 } 03480 03481 } else { 03482 03483 TagIndex = 0; 03484 } 03485 03486 #endif // NTOS_KERNEL_RUNTIME 03487 03488 // 03489 // This is the size of the block we are freeing 03490 // 03491 03492 FreeSize = BusyBlock->Size; 03493 03494 #ifndef NTOS_KERNEL_RUNTIME 03495 03496 // 03497 // In the non kernel case see if we should coalesce on free 03498 // 03499 03500 if (!(Heap->Flags & HEAP_DISABLE_COALESCE_ON_FREE)) { 03501 03502 #endif // NTOS_KERNEL_RUNTIME 03503 03504 // 03505 // In kernel case and in the tested user mode case we 03506 // now coalesce free blocks 03507 // 03508 03509 BusyBlock = (PHEAP_ENTRY)RtlpCoalesceFreeBlocks( Heap, (PHEAP_FREE_ENTRY)BusyBlock, &FreeSize, FALSE ); 03510 03511 #ifndef NTOS_KERNEL_RUNTIME 03512 03513 } 03514 03515 #endif // NTOS_KERNEL_RUNTIME 03516 03517 // 03518 // If the block should not be decommit then try and put it 03519 // on a free list 03520 // 03521 03522 if ((FreeSize < Heap->DeCommitFreeBlockThreshold) || 03523 ((Heap->TotalFreeSize + FreeSize) < Heap->DeCommitTotalFreeThreshold)) { 03524 03525 // 03526 // Check if the block can fit on one of the dedicated free 03527 // lists 03528 // 03529 03530 if (FreeSize <= (ULONG)HEAP_MAXIMUM_BLOCK_SIZE) { 03531 03532 // 03533 // It can fit on a dedicated free list so insert it on 03534 // 03535 03536 RtlpInsertFreeBlockDirect( Heap, (PHEAP_FREE_ENTRY)BusyBlock, (USHORT)FreeSize ); 03537 03538 // 03539 // If there is a following entry then make sure the 03540 // sizes agree 03541 // 03542 03543 if (!(BusyBlock->Flags & HEAP_ENTRY_LAST_ENTRY)) { 03544 03545 HEAPASSERT((BusyBlock + FreeSize)->PreviousSize == (USHORT)FreeSize); 03546 } 03547 03548 // 03549 // Update the heap with the amount of free space 03550 // available 03551 // 03552 03553 Heap->TotalFreeSize += FreeSize; 03554 03555 } else { 03556 03557 // 03558 // The block goes on the non dedicated free list 03559 // 03560 03561 RtlpInsertFreeBlock( Heap, (PHEAP_FREE_ENTRY)BusyBlock, FreeSize ); 03562 } 03563 03564 #ifndef NTOS_KERNEL_RUNTIME 03565 03566 // 03567 // In the non kernel case see if the there was tag and if 03568 // so then update the entry to show that it's been freed 03569 // 03570 03571 if (TagIndex != 0) { 03572 03573 PHEAP_FREE_ENTRY_EXTRA FreeExtra; 03574 03575 BusyBlock->Flags |= HEAP_ENTRY_EXTRA_PRESENT; 03576 03577 FreeExtra = (PHEAP_FREE_ENTRY_EXTRA)(BusyBlock + BusyBlock->Size) - 1; 03578 03579 FreeExtra->TagIndex = TagIndex; 03580 FreeExtra->FreeBackTraceIndex = 0; 03581 03582 #if i386 03583 03584 // 03585 // In the x86 case we can also capture the stack 03586 // backtrace 03587 // 03588 03589 if (Heap->Flags & HEAP_CAPTURE_STACK_BACKTRACES) { 03590 03591 FreeExtra->FreeBackTraceIndex = (USHORT)RtlLogStackBackTrace(); 03592 } 03593 03594 #endif // i386 03595 03596 } 03597 03598 #endif // NTOS_KERNEL_RUNTIME 03599 03600 } else { 03601 03602 // 03603 // Otherwise the block is big enough to decommit so have a 03604 // worker routine to do the decommit 03605 // 03606 03607 RtlpDeCommitFreeBlock( Heap, (PHEAP_FREE_ENTRY)BusyBlock, FreeSize ); 03608 } 03609 03610 // 03611 // And say the free worked fine 03612 // 03613 03614 Result = TRUE; 03615 } 03616 03617 } else { 03618 03619 // 03620 // Not a busy block, or it's not aligned or the segment is 03621 // to big, meaning it's corrupt 03622 // 03623 03624 SET_LAST_STATUS( STATUS_INVALID_PARAMETER ); 03625 } 03626 03627 } except( EXCEPTION_EXECUTE_HANDLER ) { 03628 03629 SET_LAST_STATUS( GetExceptionCode() ); 03630 03631 Result = FALSE; 03632 } 03633 03634 } finally { 03635 03636 // 03637 // Unlock the heap 03638 // 03639 03640 if (LockAcquired) { 03641 03642 RtlReleaseLockRoutine( Heap->LockVariable ); 03643 } 03644 } 03645 03646 // 03647 // And return to our caller 03648 // 03649 03650 return Result; 03651 }

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 }

VOID RtlpAdjustHeapLookasideDepth IN PHEAP_LOOKASIDE  Lookaside  ) 
 

Definition at line 130 of file rtl/lookasid.c.

References MINIMUM_ALLOCATION_THRESHOLD, MINIMUM_LOOKASIDE_DEPTH, and USHORT.

Referenced by RtlAllocateHeap().

00136 : 00137 00138 This function is called periodically to adjust the maximum depth of 00139 a single heap lookaside list. 00140 00141 Arguments: 00142 00143 Lookaside - Supplies a pointer to a heap lookaside list structure. 00144 00145 Return Value: 00146 00147 None. 00148 00149 --*/ 00150 00151 { 00152 ULONG Allocates; 00153 ULONG Misses; 00154 00155 // 00156 // Compute the total number of allocations and misses for this scan 00157 // period. 00158 // 00159 00160 Allocates = Lookaside->TotalAllocates - Lookaside->LastTotalAllocates; 00161 Lookaside->LastTotalAllocates = Lookaside->TotalAllocates; 00162 Misses = Lookaside->AllocateMisses - Lookaside->LastAllocateMisses; 00163 Lookaside->LastAllocateMisses = Lookaside->AllocateMisses; 00164 00165 // 00166 // Compute target depth of lookaside list. 00167 // 00168 00169 { 00170 ULONG Ratio; 00171 ULONG Target; 00172 00173 // 00174 // If the allocate rate is less than the mimimum threshold, then lower 00175 // the maximum depth of the lookaside list. Otherwise, if the miss rate 00176 // is less than .5%, then lower the maximum depth. Otherwise, raise the 00177 // maximum depth based on the miss rate. 00178 // 00179 00180 if (Misses >= Allocates) { 00181 Misses = Allocates; 00182 } 00183 00184 if (Allocates == 0) { 00185 Allocates = 1; 00186 } 00187 00188 Ratio = (Misses * 1000) / Allocates; 00189 Target = Lookaside->Depth; 00190 if (Allocates < MINIMUM_ALLOCATION_THRESHOLD) { 00191 if (Target > (MINIMUM_LOOKASIDE_DEPTH + 10)) { 00192 Target -= 10; 00193 00194 } else { 00195 Target = MINIMUM_LOOKASIDE_DEPTH; 00196 } 00197 00198 } else if (Ratio < 5) { 00199 if (Target > (MINIMUM_LOOKASIDE_DEPTH + 1)) { 00200 Target -= 1; 00201 00202 } else { 00203 Target = MINIMUM_LOOKASIDE_DEPTH; 00204 } 00205 00206 } else { 00207 Target += ((Ratio * Lookaside->MaximumDepth) / (1000 * 2)) + 5; 00208 if (Target > Lookaside->MaximumDepth) { 00209 Target = Lookaside->MaximumDepth; 00210 } 00211 } 00212 00213 Lookaside->Depth = (USHORT)Target; 00214 } 00215 00216 return; 00217 }

NTKERNELAPI PVOID RtlpAllocateFromHeapLookaside IN PHEAP_LOOKASIDE  Lookaside  ) 
 

Definition at line 222 of file rtl/lookasid.c.

References EXCEPTION_EXECUTE_HANDLER, NULL, and RtlpInterlockedPopEntrySList().

Referenced by RtlAllocateHeap(), RtlValidateHeap(), and RtlWalkHeap().

00228 : 00229 00230 This function removes (pops) the first entry from the specified 00231 heap lookaside list. 00232 00233 Arguments: 00234 00235 Lookaside - Supplies a pointer to a paged lookaside list structure. 00236 00237 Return Value: 00238 00239 If an entry is removed from the specified lookaside list, then the 00240 address of the entry is returned as the function value. Otherwise, 00241 NULL is returned. 00242 00243 --*/ 00244 00245 { 00246 00247 PVOID Entry; 00248 00249 Lookaside->TotalAllocates += 1; 00250 00251 // 00252 // We need to protect ourselves from a second thread that can cause us 00253 // to fault on the pop. If we do fault then we'll just do a regular pop 00254 // operation 00255 // 00256 00257 #if defined(_X86_) 00258 00259 if (USER_SHARED_DATA->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE]) { 00260 00261 #endif // defined(_X86_) 00262 00263 try { 00264 00265 Entry = RtlpInterlockedPopEntrySList(&Lookaside->ListHead); 00266 00267 } except (EXCEPTION_EXECUTE_HANDLER) { 00268 00269 Entry = NULL; 00270 } 00271 00272 if (Entry != NULL) { 00273 00274 return Entry; 00275 } 00276 #if defined(_X86_) 00277 00278 } 00279 00280 #endif // defined(_X86_) 00281 00282 Lookaside->AllocateMisses += 1; 00283 return NULL; 00284 }

BOOLEAN RtlpCheckBusyBlockTail IN PHEAP_ENTRY  BusyBlock  ) 
 

Definition at line 6117 of file rtl/heap.c.

References CHECK_HEAP_TAIL_SIZE, CheckHeapFillPattern, FALSE, HEAP_ENTRY_VIRTUAL_ALLOC, HEAP_GRANULARITY_SHIFT, HeapDebugBreak, HeapDebugPrint, RTL_PAGED_CODE, RtlpGetSizeOfBigBlock(), Size, and TRUE.

Referenced by RtlpValidateHeap(), RtlpValidateHeapEntry(), and RtlpValidateHeapSegment().

06123 : 06124 06125 This routine checks to see if the bytes beyond the user specified 06126 allocation have been modified. It does this by checking for a tail 06127 fill pattern 06128 06129 Arguments: 06130 06131 BusyBlock - Supplies the heap block being queried 06132 06133 Return Value: 06134 06135 BOOLEAN - TRUE if the tail is still okay and FALSE otherwise 06136 06137 --*/ 06138 06139 { 06140 PCHAR Tail; 06141 SIZE_T Size, cbEqual; 06142 06143 RTL_PAGED_CODE(); 06144 06145 // 06146 // Compute the user allocated size of the input heap block 06147 // 06148 06149 if (BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) { 06150 06151 Size = RtlpGetSizeOfBigBlock( BusyBlock ); 06152 06153 } else { 06154 06155 Size = (BusyBlock->Size << HEAP_GRANULARITY_SHIFT) - BusyBlock->UnusedBytes; 06156 } 06157 06158 // 06159 // Compute a pointer to the tail of the input block. This would 06160 // be the space right after the user allocated portion 06161 // 06162 06163 Tail = (PCHAR)(BusyBlock + 1) + Size; 06164 06165 // 06166 // Check if the tail fill pattern is still there 06167 // 06168 06169 cbEqual = RtlCompareMemory( Tail, 06170 CheckHeapFillPattern, 06171 CHECK_HEAP_TAIL_SIZE ); 06172 06173 // 06174 // If the number we get back isn't equal to the tail size then 06175 // someone modified the block beyond its user specified allocation 06176 // size 06177 // 06178 06179 if (cbEqual != CHECK_HEAP_TAIL_SIZE) { 06180 06181 // 06182 // Do some debug printing 06183 // 06184 06185 HeapDebugPrint(( "Heap block at %p modified at %p past requested size of %lx\n", 06186 BusyBlock, 06187 Tail + cbEqual, 06188 Size )); 06189 06190 HeapDebugBreak( BusyBlock ); 06191 06192 // 06193 // And tell our caller there was an error 06194 // 06195 06196 return FALSE; 06197 06198 } else { 06199 06200 // 06201 // And return to our caller that the tail is fine 06202 // 06203 06204 return TRUE; 06205 } 06206 } }

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 RtlpCoalesceFreeBlocks IN PHEAP  Heap,
IN PHEAP_FREE_ENTRY  FreeBlock,
IN OUT PSIZE_T  FreeSize,
IN BOOLEAN  RemoveFromFreeList
 

Definition at line 5312 of file rtl/heap.c.

References FALSE, _HEAP_FREE_ENTRY::Flags, HEAP_ENTRY_BUSY, HEAP_ENTRY_LAST_ENTRY, HEAP_MAXIMUM_BLOCK_SIZE, HEAPASSERT, _HEAP_SEGMENT::LastEntryInSegment, _HEAP_FREE_ENTRY::PreviousSize, RTL_PAGED_CODE, RtlpRemoveFreeBlock, _HEAP_FREE_ENTRY::SegmentIndex, _HEAP_FREE_ENTRY::Size, and USHORT.

Referenced by RtlFreeHeap(), RtlFreeHeapSlowly(), RtlpCoalesceHeap(), RtlpExtendHeap(), and RtlpGrowBlockInPlace().

05321 : 05322 05323 This routine coalesces the free block together. 05324 05325 Arguments: 05326 05327 Heap - Supplies a pointer to the heap being manipulated 05328 05329 FreeBlock - Supplies a pointer to the free block that we want coalesced 05330 05331 FreeSize - Supplies the size, in bytes, of the free block. On return it 05332 contains the size, in bytes, of the of the newly coalesced free block 05333 05334 RemoveFromFreeList - Indicates if the input free block is already on a 05335 free list and needs to be removed to before coalescing 05336 05337 Return Value: 05338 05339 PHEAP_FREE_ENTRY - returns a pointer to the newly coalesced free block 05340 05341 --*/ 05342 05343 { 05344 PHEAP_FREE_ENTRY FreeBlock1, NextFreeBlock; 05345 05346 RTL_PAGED_CODE(); 05347 05348 // 05349 // Point to the preceding block 05350 // 05351 05352 FreeBlock1 = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeBlock - FreeBlock->PreviousSize); 05353 05354 // 05355 // Check if there is a preceding block, and if it is free, and the two sizes 05356 // put together will still fit on a free lists. 05357 // 05358 05359 if ((FreeBlock1 != FreeBlock) && 05360 !(FreeBlock1->Flags & HEAP_ENTRY_BUSY) && 05361 ((*FreeSize + FreeBlock1->Size) <= HEAP_MAXIMUM_BLOCK_SIZE)) { 05362 05363 // 05364 // We are going to merge ourselves with the preceding block 05365 // 05366 05367 HEAPASSERT(FreeBlock->PreviousSize == FreeBlock1->Size); 05368 05369 // 05370 // Check if we need to remove the input block from the free list 05371 // 05372 05373 if (RemoveFromFreeList) { 05374 05375 RtlpRemoveFreeBlock( Heap, FreeBlock ); 05376 05377 Heap->TotalFreeSize -= FreeBlock->Size; 05378 05379 // 05380 // We're removed so we don't have to do it again 05381 // 05382 05383 RemoveFromFreeList = FALSE; 05384 } 05385 05386 // 05387 // Remove the preceding block from its free list 05388 // 05389 05390 RtlpRemoveFreeBlock( Heap, FreeBlock1 ); 05391 05392 // 05393 // Copy over the last entry flag if necessary from what we're freeing 05394 // to the preceding block 05395 // 05396 05397 FreeBlock1->Flags = FreeBlock->Flags & HEAP_ENTRY_LAST_ENTRY; 05398 05399 if( FreeBlock1->Flags & HEAP_ENTRY_LAST_ENTRY ) { 05400 05401 PHEAP_SEGMENT Segment; 05402 05403 Segment = Heap->Segments[FreeBlock1->SegmentIndex]; 05404 Segment->LastEntryInSegment = (PHEAP_ENTRY)FreeBlock1; 05405 } 05406 05407 // 05408 // Point to the preceding block, and adjust the sizes for the 05409 // new free block. It is the total of both blocks. 05410 // 05411 05412 FreeBlock = FreeBlock1; 05413 05414 *FreeSize += FreeBlock1->Size; 05415 05416 Heap->TotalFreeSize -= FreeBlock1->Size; 05417 05418 FreeBlock->Size = (USHORT)*FreeSize; 05419 05420 // 05421 // Check if we need to update the previous size of the next 05422 // entry 05423 // 05424 05425 if (!(FreeBlock->Flags & HEAP_ENTRY_LAST_ENTRY)) { 05426 05427 ((PHEAP_ENTRY)FreeBlock + *FreeSize)->PreviousSize = (USHORT)*FreeSize; 05428 } 05429 } 05430 05431 // 05432 // Check if there is a following block. 05433 // 05434 05435 if (!(FreeBlock->Flags & HEAP_ENTRY_LAST_ENTRY)) { 05436 05437 // 05438 // There is a following block so now get a pointer to it 05439 // and check if it is free and if putting the two blocks together 05440 // still fits on a free list 05441 // 05442 05443 NextFreeBlock = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeBlock + *FreeSize); 05444 05445 if (!(NextFreeBlock->Flags & HEAP_ENTRY_BUSY) && 05446 ((*FreeSize + NextFreeBlock->Size) <= HEAP_MAXIMUM_BLOCK_SIZE)) { 05447 05448 // 05449 // We are going to merge ourselves with the following block 05450 // 05451 05452 HEAPASSERT(*FreeSize == NextFreeBlock->PreviousSize); 05453 05454 // 05455 // Check if we need to remove the input block from the free list 05456 // 05457 05458 if (RemoveFromFreeList) { 05459 05460 RtlpRemoveFreeBlock( Heap, FreeBlock ); 05461 05462 Heap->TotalFreeSize -= FreeBlock->Size; 05463 05464 // 05465 // **** this assignment isn't necessary because there isn't 05466 // **** any more merging after this one 05467 // 05468 05469 RemoveFromFreeList = FALSE; 05470 } 05471 05472 // 05473 // Copy up the last entry flag if necessary from the following 05474 // block to our input block 05475 // 05476 05477 FreeBlock->Flags = NextFreeBlock->Flags & HEAP_ENTRY_LAST_ENTRY; 05478 05479 if( FreeBlock->Flags & HEAP_ENTRY_LAST_ENTRY ) { 05480 05481 PHEAP_SEGMENT Segment; 05482 05483 Segment = Heap->Segments[FreeBlock->SegmentIndex]; 05484 Segment->LastEntryInSegment = (PHEAP_ENTRY)FreeBlock; 05485 } 05486 05487 // 05488 // Remove the following block from its free list 05489 // 05490 05491 RtlpRemoveFreeBlock( Heap, NextFreeBlock ); 05492 05493 // 05494 // Adjust the size for the newly combined block 05495 // 05496 05497 *FreeSize += NextFreeBlock->Size; 05498 05499 Heap->TotalFreeSize -= NextFreeBlock->Size; 05500 05501 FreeBlock->Size = (USHORT)*FreeSize; 05502 05503 // 05504 // Check if we need to update the previous size of the next block 05505 // 05506 05507 if (!(FreeBlock->Flags & HEAP_ENTRY_LAST_ENTRY)) { 05508 05509 ((PHEAP_ENTRY)FreeBlock + *FreeSize)->PreviousSize = (USHORT)*FreeSize; 05510 } 05511 } 05512 } 05513 05514 // 05515 // And return the free block to our caller 05516 // 05517 05518 return FreeBlock; 05519 }

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 RtlpDeCommitFreeBlock IN PHEAP  Heap,
IN PHEAP_FREE_ENTRY  FreeBlock,
IN SIZE_T  FreeSize
 

Definition at line 5527 of file rtl/heap.c.

References _HEAP_SEGMENT::Entry, _HEAP_SEGMENT::FirstEntry, _HEAP_ENTRY::Flags, _HEAP_FREE_ENTRY::Flags, HEAP_ENTRY_LAST_ENTRY, HEAP_GRANULARITY_SHIFT, HeapDebugPrint, _HEAP_SEGMENT::LastEntryInSegment, NT_SUCCESS, NTSTATUS(), NULL, _HEAP_SEGMENT::NumberOfUnCommittedPages, PAGE_SIZE, _HEAP_ENTRY::PreviousSize, _HEAP_FREE_ENTRY::PreviousSize, ROUND_DOWN_TO_POWER2, ROUND_UP_TO_POWER2, RTL_PAGED_CODE, RtlpCreateUnCommittedRange(), RtlpDestroyUnCommittedRange(), RtlpInsertFreeBlock(), RtlpInsertFreeBlockDirect, RtlpInsertUnCommittedPages(), _HEAP_ENTRY::SegmentIndex, _HEAP_FREE_ENTRY::Size, Status, and USHORT.

Referenced by RtlFreeHeap(), RtlFreeHeapSlowly(), and RtlpCoalesceHeap().

05535 : 05536 05537 This routine takes a free block and decommits it. This is usually called 05538 because the block is beyond the decommit threshold 05539 05540 Arguments: 05541 05542 Heap - Supplies a pointer to the heap being manipulated 05543 05544 FreeBlock - Supplies a pointer to the block being decommitted 05545 05546 FreeSize - Supplies the size, in bytes, of the free block being decommitted 05547 05548 Return Value: 05549 05550 None. 05551 05552 --*/ 05553 05554 { 05555 NTSTATUS Status; 05556 ULONG_PTR DeCommitAddress; 05557 SIZE_T DeCommitSize; 05558 USHORT LeadingFreeSize, TrailingFreeSize; 05559 PHEAP_SEGMENT Segment; 05560 PHEAP_FREE_ENTRY LeadingFreeBlock, TrailingFreeBlock; 05561 PHEAP_ENTRY LeadingBusyBlock, TrailingBusyBlock; 05562 PHEAP_UNCOMMMTTED_RANGE UnCommittedRange; 05563 05564 RTL_PAGED_CODE(); 05565 05566 // 05567 // If the heap has a user specified decommit routine then we won't really 05568 // decommit anything instead we'll call a worker routine to chop it up 05569 // into pieces that will fit on the free lists 05570 // 05571 05572 if (Heap->CommitRoutine != NULL) { 05573 05574 RtlpInsertFreeBlock( Heap, FreeBlock, FreeSize ); 05575 05576 return; 05577 } 05578 05579 // 05580 // Get a pointer to the owning segment 05581 // 05582 05583 Segment = Heap->Segments[ FreeBlock->SegmentIndex ]; 05584 05585 // 05586 // The leading busy block identifies the preceding in use block before 05587 // what we are trying to decommit. It is only used if what we are trying 05588 // decommit is right on a page boundary and then it is the block right 05589 // before us if it exists. 05590 // 05591 // The leading free block is used to identify whatever space is needed 05592 // to round up the callers specified address to a page address. If the 05593 // caller already gave us a page aligned address then the free block 05594 // address is identical to what the caller supplied. 05595 // 05596 05597 LeadingBusyBlock = NULL; 05598 LeadingFreeBlock = FreeBlock; 05599 05600 // 05601 // Make sure the block we are trying to decommit start on the next full 05602 // page boundary. The leading free size is the size of whatever it takes 05603 // to round up the free block to the next page specified in units of 05604 // heap entries. 05605 // 05606 05607 DeCommitAddress = ROUND_UP_TO_POWER2( LeadingFreeBlock, PAGE_SIZE ); 05608 LeadingFreeSize = (USHORT)((PHEAP_ENTRY)DeCommitAddress - (PHEAP_ENTRY)LeadingFreeBlock); 05609 05610 // 05611 // If we leading free size only has space for one heap entry then we'll 05612 // bump it up to include the next page, because we don't want to leave 05613 // anything that small laying around. Otherwise if we have a preceding 05614 // block and the leading free size is zero then identify the preceding 05615 // block as the leading busy block 05616 // 05617 05618 if (LeadingFreeSize == 1) { 05619 05620 DeCommitAddress += PAGE_SIZE; 05621 LeadingFreeSize += PAGE_SIZE >> HEAP_GRANULARITY_SHIFT; 05622 05623 } else if (LeadingFreeBlock->PreviousSize != 0) { 05624 05625 if (DeCommitAddress == (ULONG_PTR)LeadingFreeBlock) { 05626 05627 LeadingBusyBlock = (PHEAP_ENTRY)LeadingFreeBlock - LeadingFreeBlock->PreviousSize; 05628 } 05629 } 05630 05631 // 05632 // The trailing busy block identifies the block immediately after the one 05633 // we are trying to decommit provided what we are decommitting ends right 05634 // on a page boundary otherwise the trailing busy block stays null and 05635 // the trailing free block value is used. 05636 // 05637 // **** gdk **** 05638 // **** the assignment of tailing free block doesn't seem right because 05639 // **** Free size should be in bytes, and not heap entries 05640 // 05641 05642 TrailingBusyBlock = NULL; 05643 TrailingFreeBlock = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeBlock + FreeSize); 05644 05645 // 05646 // Make sure the block we are trying to decommit ends on a page boundary. 05647 // 05648 // And compute how many heap entries we had to backup to make it land on a 05649 // page boundary. 05650 // 05651 05652 DeCommitSize = ROUND_DOWN_TO_POWER2( (ULONG_PTR)TrailingFreeBlock, PAGE_SIZE ); 05653 TrailingFreeSize = (USHORT)((PHEAP_ENTRY)TrailingFreeBlock - (PHEAP_ENTRY)DeCommitSize); 05654 05655 // 05656 // If the trailing free size is exactly one heap in size then we will 05657 // nibble off a bit more from the decommit size because free block of 05658 // exactly one heap entry in size are useless. Otherwise if we actually 05659 // ended on a page boundary and there is a block after us then indicate 05660 // that we have a trailing busy block 05661 // 05662 05663 if (TrailingFreeSize == (sizeof( HEAP_ENTRY ) >> HEAP_GRANULARITY_SHIFT)) { 05664 05665 DeCommitSize -= PAGE_SIZE; 05666 TrailingFreeSize += PAGE_SIZE >> HEAP_GRANULARITY_SHIFT; 05667 05668 } else if ((TrailingFreeSize == 0) && !(FreeBlock->Flags & HEAP_ENTRY_LAST_ENTRY)) { 05669 05670 TrailingBusyBlock = (PHEAP_ENTRY)TrailingFreeBlock; 05671 } 05672 05673 // 05674 // Now adjust the trailing free block to compensate for the trailing free size 05675 // we just computed. 05676 // 05677 05678 TrailingFreeBlock = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)TrailingFreeBlock - TrailingFreeSize); 05679 05680 // 05681 // Right now DeCommit size is really a pointer. If it points at is beyond 05682 // the decommit address then make the size really be just the byte count 05683 // to decommit. Otherwise the decommit size is zero. 05684 // 05685 05686 if (DeCommitSize > DeCommitAddress) { 05687 05688 DeCommitSize -= DeCommitAddress; 05689 05690 } else { 05691 05692 DeCommitSize = 0; 05693 } 05694 05695 // 05696 // **** this next test is bogus given the if-then-else that just preceded it 05697 // 05698 // Now check if we still have something to decommit 05699 // 05700 05701 if (DeCommitSize != 0) { 05702 05703 // 05704 // Before freeing the memory to MM we have to be sure we can create 05705 // a PHEAP_UNCOMMMTTED_RANGE later. So we do it right now 05706 // 05707 05708 UnCommittedRange = RtlpCreateUnCommittedRange(Segment); 05709 05710 if (UnCommittedRange == NULL) { 05711 05712 HeapDebugPrint(( "Failing creating uncommitted range (%x for %x)\n", DeCommitAddress, DeCommitSize )); 05713 05714 // 05715 // We weren't successful in the decommit so now simply 05716 // add the leading free block to the free list 05717 // 05718 05719 RtlpInsertFreeBlock( Heap, LeadingFreeBlock, FreeSize ); 05720 05721 return; 05722 } 05723 05724 // 05725 // Decommit the memory 05726 // 05727 05728 Status = ZwFreeVirtualMemory( NtCurrentProcess(), 05729 (PVOID *)&DeCommitAddress, 05730 &DeCommitSize, 05731 MEM_DECOMMIT ); 05732 05733 // 05734 // Push back the UnCommittedRange structure. Now the insert cannot fail 05735 // 05736 05737 RtlpDestroyUnCommittedRange( Segment, UnCommittedRange ); 05738 05739 if (NT_SUCCESS( Status )) { 05740 05741 // 05742 // Insert information regarding the pages we just decommitted 05743 // to the lsit of uncommited pages in the segment 05744 // 05745 05746 RtlpInsertUnCommittedPages( Segment, 05747 DeCommitAddress, 05748 DeCommitSize ); 05749 // 05750 // Adjust the segments count of uncommitted pages 05751 // 05752 05753 Segment->NumberOfUnCommittedPages += (ULONG)(DeCommitSize / PAGE_SIZE); 05754 05755 // 05756 // If we have a leading free block then mark its proper state 05757 // update the heap, and put it on the free list 05758 // 05759 05760 if (LeadingFreeSize != 0) { 05761 05762 LeadingFreeBlock->Flags = HEAP_ENTRY_LAST_ENTRY; 05763 LeadingFreeBlock->Size = LeadingFreeSize; 05764 Heap->TotalFreeSize += LeadingFreeSize; 05765 05766 Segment->LastEntryInSegment = (PHEAP_ENTRY)LeadingFreeBlock; 05767 05768 RtlpInsertFreeBlockDirect( Heap, LeadingFreeBlock, LeadingFreeSize ); 05769 05770 // 05771 // Otherwise if we actually have a leading busy block then 05772 // make sure the busy block knows we're uncommitted 05773 // 05774 05775 } else if (LeadingBusyBlock != NULL) { 05776 05777 LeadingBusyBlock->Flags |= HEAP_ENTRY_LAST_ENTRY; 05778 05779 Segment->LastEntryInSegment = LeadingBusyBlock; 05780 05781 } else if ((Segment->LastEntryInSegment >= (PHEAP_ENTRY)DeCommitAddress) 05782 && 05783 ((PCHAR)Segment->LastEntryInSegment < ((PCHAR)DeCommitAddress + DeCommitSize))) { 05784 05785 Segment->LastEntryInSegment = Segment->FirstEntry; 05786 } 05787 05788 // 05789 // If there is a trailing free block then sets its state, 05790 // update the heap, and insert it on a free list 05791 // 05792 05793 if (TrailingFreeSize != 0) { 05794 05795 TrailingFreeBlock->PreviousSize = 0; 05796 TrailingFreeBlock->SegmentIndex = Segment->Entry.SegmentIndex; 05797 TrailingFreeBlock->Flags = 0; 05798 TrailingFreeBlock->Size = TrailingFreeSize; 05799 05800 ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)TrailingFreeBlock + TrailingFreeSize))->PreviousSize = (USHORT)TrailingFreeSize; 05801 05802 RtlpInsertFreeBlockDirect( Heap, TrailingFreeBlock, TrailingFreeSize ); 05803 05804 Heap->TotalFreeSize += TrailingFreeSize; 05805 05806 // 05807 // Otherwise if we actually have a succeeding block then 05808 // make it know we are uncommitted 05809 // 05810 05811 } else if (TrailingBusyBlock != NULL) { 05812 05813 TrailingBusyBlock->PreviousSize = 0; 05814 } 05815 05816 } else { 05817 05818 // 05819 // We weren't successful in the decommit so now simply 05820 // add the leading free block to the free list 05821 // 05822 05823 RtlpInsertFreeBlock( Heap, LeadingFreeBlock, FreeSize ); 05824 } 05825 05826 } else { 05827 05828 // 05829 // There is nothing left to decommit to take our leading free block 05830 // and put it on a free list 05831 // 05832 05833 RtlpInsertFreeBlock( Heap, LeadingFreeBlock, FreeSize ); 05834 } 05835 05836 // 05837 // And return to our caller 05838 // 05839 05840 return; 05841 }

NTKERNELAPI VOID RtlpDeleteHeapLookaside IN PHEAP_LOOKASIDE  Lookaside  ) 
 

Definition at line 101 of file rtl/lookasid.c.

00107 : 00108 00109 This function frees any entries specified by the lookaside structure. 00110 00111 Arguments: 00112 00113 Lookaside - Supplies a pointer to a heap lookaside list structure. 00114 00115 Return Value: 00116 00117 None. 00118 00119 --*/ 00120 00121 { 00122 00123 PVOID Entry; 00124 00125 return; 00126 }

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 }

PHEAP_FREE_ENTRY RtlpFindAndCommitPages IN PHEAP  Heap,
IN PHEAP_SEGMENT  Segment,
IN OUT PSIZE_T  Size,
IN PVOID AddressWanted  OPTIONAL
 

Definition at line 4422 of file rtl/heap.c.

References _HEAP_UNCOMMMTTED_RANGE::Address, _HEAP_ENTRY::Flags, HEAP_ENTRY_LAST_ENTRY, HEAP_GRANULARITY_SHIFT, HeapDebugBreak, HeapDebugPrint, _HEAP_UNCOMMMTTED_RANGE::Next, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, _HEAP_ENTRY::PreviousSize, RTL_PAGED_CODE, RtlpDestroyUnCommittedRange(), _HEAP_ENTRY::SegmentIndex, _HEAP_ENTRY::Size, Size, _HEAP_UNCOMMMTTED_RANGE::Size, Status, and USHORT.

Referenced by RtlpExtendHeap(), and RtlpGrowBlockInPlace().

04431 : 04432 04433 This function searches the supplied segment for an uncommitted range that 04434 satisfies the specified size. It commits the range and returns a heap entry 04435 for the range. 04436 04437 Arguments: 04438 04439 Heap - Supplies the heap being maniuplated 04440 04441 Segment - Supplies the segment being searched 04442 04443 Size - Supplies the size of what we need to look for, on return it contains 04444 the size of what we're just found and committed. 04445 04446 AddressWanted - Optionally gives an address where we would like the pages 04447 based. If supplied the entry must start at this address 04448 04449 Return Value: 04450 04451 PHEAP_FREE_ENTRY - Returns a pointer to the newly committed range that 04452 satisfies the given size requirement, or NULL if we could not find 04453 something large enough and/or based at the address wanted. 04454 04455 --*/ 04456 04457 { 04458 NTSTATUS Status; 04459 PHEAP_ENTRY FirstEntry, LastEntry, PreviousLastEntry; 04460 PHEAP_UNCOMMMTTED_RANGE PreviousUnCommittedRange, UnCommittedRange, *pp; 04461 ULONG_PTR Address; 04462 SIZE_T Length; 04463 04464 RTL_PAGED_CODE(); 04465 04466 // 04467 // What the outer loop does is cycle through the uncommited ranges 04468 // stored in in the specified segment 04469 // 04470 04471 PreviousUnCommittedRange = NULL; 04472 pp = &Segment->UnCommittedRanges; 04473 04474 while (UnCommittedRange = *pp) { 04475 04476 // 04477 // Check for the best of worlds, where the size of this current 04478 // uncommitted range satisfies our size request and either the user 04479 // didn't specify an address or the address match 04480 // 04481 04482 if ((UnCommittedRange->Size >= *Size) && 04483 (!ARGUMENT_PRESENT( AddressWanted ) || (UnCommittedRange->Address == (ULONG_PTR)AddressWanted ))) { 04484 04485 // 04486 // Calculate an address 04487 // 04488 04489 Address = UnCommittedRange->Address; 04490 04491 // 04492 // Commit the memory. If the heap doesn't have a commit 04493 // routine then use the default mm supplied routine. 04494 // 04495 04496 if (Heap->CommitRoutine != NULL) { 04497 04498 Status = (Heap->CommitRoutine)( Heap, 04499 (PVOID *)&Address, 04500 Size ); 04501 04502 } else { 04503 04504 Status = ZwAllocateVirtualMemory( NtCurrentProcess(), 04505 (PVOID *)&Address, 04506 0, 04507 Size, 04508 MEM_COMMIT, 04509 PAGE_READWRITE ); 04510 04511 } 04512 04513 if (!NT_SUCCESS( Status )) { 04514 04515 return NULL; 04516 } 04517 04518 // 04519 // At this point we have some committed memory, with Address and Size 04520 // giving us the necessary details 04521 // 04522 // Update the number of uncommitted pages in the segment and if necessary 04523 // mark down the largest uncommitted range 04524 // 04525 04526 Segment->NumberOfUnCommittedPages -= (ULONG) (*Size / PAGE_SIZE); 04527 04528 if (Segment->LargestUnCommittedRange == UnCommittedRange->Size) { 04529 04530 Segment->LargestUnCommittedRange = 0; 04531 } 04532 04533 // 04534 // First entry is the start of the newly committed range 04535 // 04536 04537 FirstEntry = (PHEAP_ENTRY)Address; 04538 04539 // 04540 // We want last entry to point to the last real entry before 04541 // this newly committed spot. To do this we start by 04542 // setting last entry to either the first entry for the 04543 // segment or (if we can do better), to right after the last 04544 // uncommitted range we examined. Either way it points to 04545 // some committed range 04546 // 04547 04548 if ((Segment->LastEntryInSegment->Flags & HEAP_ENTRY_LAST_ENTRY) && 04549 (ULONG_PTR)(Segment->LastEntryInSegment + Segment->LastEntryInSegment->Size) == UnCommittedRange->Address) { 04550 04551 LastEntry = Segment->LastEntryInSegment; 04552 04553 } else { 04554 04555 if (PreviousUnCommittedRange == NULL) { 04556 04557 LastEntry = Segment->FirstEntry; 04558 04559 } else { 04560 04561 LastEntry = (PHEAP_ENTRY)(PreviousUnCommittedRange->Address + 04562 PreviousUnCommittedRange->Size); 04563 } 04564 04565 // 04566 // Now we zoom through the entries until we find the one 04567 // marked last 04568 // 04569 04570 while (!(LastEntry->Flags & HEAP_ENTRY_LAST_ENTRY)) { 04571 04572 PreviousLastEntry = LastEntry; 04573 LastEntry += LastEntry->Size; 04574 04575 if (((PCHAR)LastEntry >= (PCHAR)Segment->LastValidEntry) || (LastEntry->Size == 0)) { 04576 04577 // 04578 // Check for the situation where the last entry in the 04579 // segment isn't marked as a last entry but does put 04580 // us right where the have a new committed range 04581 // 04582 04583 if (LastEntry == (PHEAP_ENTRY)Address) { 04584 04585 LastEntry = PreviousLastEntry; 04586 04587 break; 04588 } 04589 04590 HeapDebugPrint(( "Heap missing last entry in committed range near %x\n", PreviousLastEntry )); 04591 HeapDebugBreak( PreviousLastEntry ); 04592 04593 return NULL; 04594 } 04595 } 04596 } 04597 04598 // 04599 // Turn off the last bit on this entry because what's following 04600 // is no longer uncommitted 04601 // 04602 04603 LastEntry->Flags &= ~HEAP_ENTRY_LAST_ENTRY; 04604 04605 // 04606 // Shrink the uncommited range by the size we've committed 04607 // 04608 04609 UnCommittedRange->Address += *Size; 04610 UnCommittedRange->Size -= *Size; 04611 04612 // 04613 // Now if the size is zero then we've committed everything that there 04614 // was in the range. Otherwise make sure the first entry of what 04615 // we've just committed knows that an uncommitted range follows. 04616 // 04617 04618 if (UnCommittedRange->Size == 0) { 04619 04620 // 04621 // This uncommitted range is about to vanish. Base on if the 04622 // range is the last one in the segemnt then we know how to 04623 // mark the committed range as being last or not. 04624 // 04625 04626 if (UnCommittedRange->Address == (ULONG_PTR)Segment->LastValidEntry) { 04627 04628 FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY; 04629 04630 Segment->LastEntryInSegment = FirstEntry; 04631 04632 } else { 04633 04634 FirstEntry->Flags = 0; 04635 04636 Segment->LastEntryInSegment = Segment->FirstEntry; 04637 } 04638 04639 // 04640 // Remove this zero sized range from the uncommitted range 04641 // list, and update the segment counters 04642 // 04643 04644 *pp = UnCommittedRange->Next; 04645 04646 RtlpDestroyUnCommittedRange( Segment, UnCommittedRange ); 04647 04648 Segment->NumberOfUnCommittedRanges -= 1; 04649 04650 } else { 04651 04652 // 04653 // Otherwise the range is not empty so we know what we committed 04654 // is immediately followed by an uncommitted range 04655 // 04656 04657 FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY; 04658 04659 Segment->LastEntryInSegment = FirstEntry; 04660 } 04661 04662 // 04663 // Update the fields in the first entry, and optional 04664 // following entry. 04665 // 04666 04667 FirstEntry->SegmentIndex = LastEntry->SegmentIndex; 04668 FirstEntry->Size = (USHORT)(*Size >> HEAP_GRANULARITY_SHIFT); 04669 FirstEntry->PreviousSize = LastEntry->Size; 04670 04671 if (!(FirstEntry->Flags & HEAP_ENTRY_LAST_ENTRY)) { 04672 04673 (FirstEntry + FirstEntry->Size)->PreviousSize = FirstEntry->Size; 04674 } 04675 04676 // 04677 // Now if we adjusted the largest uncommitted range to zero then 04678 // we need to go back and find the largest uncommitted range 04679 // To do that we simply zoom down the uncommitted range list 04680 // remembering the largest one 04681 // 04682 04683 if (Segment->LargestUnCommittedRange == 0) { 04684 04685 UnCommittedRange = Segment->UnCommittedRanges; 04686 04687 while (UnCommittedRange != NULL) { 04688 04689 if (UnCommittedRange->Size >= Segment->LargestUnCommittedRange) { 04690 04691 Segment->LargestUnCommittedRange = UnCommittedRange->Size; 04692 } 04693 04694 UnCommittedRange = UnCommittedRange->Next; 04695 } 04696 } 04697 04698 // 04699 // And return the heap entry to our caller 04700 // 04701 04702 return (PHEAP_FREE_ENTRY)FirstEntry; 04703 04704 } else { 04705 04706 // 04707 // Otherwise the current uncommited range is too small or 04708 // doesn't have the right address so go to the next uncommitted 04709 // range entry 04710 // 04711 04712 PreviousUnCommittedRange = UnCommittedRange; 04713 pp = &UnCommittedRange->Next; 04714 } 04715 } 04716 04717 // 04718 // At this point we did not find an uncommitted range entry that satisfied 04719 // our requirements either because of size and/or address. So return null 04720 // to tell the user we didn't find anything. 04721 // 04722 04723 return NULL; 04724 }

NTKERNELAPI BOOLEAN RtlpFreeToHeapLookaside IN PHEAP_LOOKASIDE  Lookaside,
IN PVOID  Entry
 

Definition at line 288 of file rtl/lookasid.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, RtlpInterlockedPushEntrySList(), RtlpQueryDepthSList, and TRUE.

Referenced by RtlFreeHeap().

00295 : 00296 00297 This function inserts (pushes) the specified entry into the specified 00298 paged lookaside list. 00299 00300 Arguments: 00301 00302 Lookaside - Supplies a pointer to a paged lookaside list structure. 00303 00304 Entry - Supples a pointer to the entry that is inserted in the 00305 lookaside list. 00306 00307 Return Value: 00308 00309 BOOLEAN - TRUE if the entry was put on the lookaside list and FALSE 00310 otherwise. 00311 00312 --*/ 00313 00314 { 00315 Lookaside->TotalFrees += 1; 00316 00317 #if defined(_X86_) 00318 00319 if (USER_SHARED_DATA->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE]) { 00320 00321 #endif // defined(_X86_) 00322 00323 if (RtlpQueryDepthSList(&Lookaside->ListHead) < Lookaside->Depth) { 00324 00325 // 00326 // We need to protect ourselves from a second thread that can 00327 // cause us to fault on the push. If we do fault then we'll 00328 // just do a regular free operation 00329 // 00330 00331 try { 00332 00333 RtlpInterlockedPushEntrySList(&Lookaside->ListHead, 00334 (PSINGLE_LIST_ENTRY)Entry); 00335 00336 } except (EXCEPTION_EXECUTE_HANDLER) { 00337 00338 Lookaside->FreeMisses += 1; 00339 00340 return FALSE; 00341 } 00342 00343 return TRUE; 00344 } 00345 00346 #if defined(_X86_) 00347 00348 } 00349 00350 #endif // defined(_X86_) 00351 00352 Lookaside->FreeMisses += 1; 00353 00354 return FALSE; 00355 }

PHEAP_ENTRY_EXTRA RtlpGetExtraStuffPointer PHEAP_ENTRY  BusyBlock  ) 
 

Definition at line 6008 of file rtl/heap.c.

References _HEAP_VIRTUAL_ALLOC_ENTRY::ExtraStuff, _HEAP_ENTRY::Flags, HEAP_ENTRY_VIRTUAL_ALLOC, and _HEAP_ENTRY::Size.

Referenced by RtlAllocateHeapSlowly(), RtlDebugAllocateHeap(), RtlDebugFreeHeap(), RtlDebugReAllocateHeap(), RtlGetUserInfoHeap(), RtlpValidateHeapSegment(), RtlReAllocateHeap(), RtlSetUserValueHeap(), RtlUsageHeap(), and RtlWalkHeap().

06014 : 06015 06016 This routine calculates where the extra stuff record will be given 06017 the busy block and returns a pointer to it. The caller must have 06018 already checked that the entry extry field is present 06019 06020 Arguments: 06021 06022 BusyBlock - Supplies the busy block whose extra stuff we are seeking 06023 06024 Return Value: 06025 06026 PHEAP_ENTRY_EXTRA - returns a pointer to the extra stuff record. 06027 06028 --*/ 06029 06030 { 06031 ULONG AllocationIndex; 06032 06033 // 06034 // On big blocks the extra stuff is automatically part of the 06035 // block 06036 // 06037 06038 if (BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) { 06039 06040 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock; 06041 06042 VirtualAllocBlock = CONTAINING_RECORD( BusyBlock, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock ); 06043 06044 return &VirtualAllocBlock->ExtraStuff; 06045 06046 } else { 06047 06048 // 06049 // On non big blocks the extra stuff follows immediately after 06050 // the allocation itself. 06051 // 06052 // **** What a hack 06053 // **** We do some funny math here because the busy block 06054 // **** stride is 8 bytes we know we can stride it by its 06055 // **** index minus one to get to the end of the allocation 06056 // 06057 06058 AllocationIndex = BusyBlock->Size; 06059 06060 return (PHEAP_ENTRY_EXTRA)(BusyBlock + AllocationIndex - 1); 06061 } 06062 }

SIZE_T RtlpGetSizeOfBigBlock IN PHEAP_ENTRY  BusyBlock  ) 
 

Definition at line 6070 of file rtl/heap.c.

References _HEAP_VIRTUAL_ALLOC_ENTRY::CommitSize, and RTL_PAGED_CODE.

Referenced by RtlpCheckBusyBlockTail(), RtlReAllocateHeap(), RtlSizeHeap(), and RtlWalkHeap().

06076 : 06077 06078 This routine returns the size, in bytes, of the big allocation block 06079 06080 Arguments: 06081 06082 BusyBlock - Supplies a pointer to the block being queried 06083 06084 Return Value: 06085 06086 SIZE_T - Returns the size, in bytes, that was allocated to the big 06087 block 06088 06089 --*/ 06090 06091 { 06092 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock; 06093 06094 RTL_PAGED_CODE(); 06095 06096 // 06097 // Get a pointer to the block header itself 06098 // 06099 06100 VirtualAllocBlock = CONTAINING_RECORD( BusyBlock, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock ); 06101 06102 // 06103 // The size allocated to the block is actually the difference between the 06104 // commit size stored in the virtual alloc block and the size stored in 06105 // in the block. 06106 // 06107 06108 return VirtualAllocBlock->CommitSize - BusyBlock->Size; 06109 }

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 }

NTKERNELAPI VOID RtlpInitializeHeapLookaside IN PHEAP_LOOKASIDE  Lookaside,
IN USHORT  Depth
 

Definition at line 45 of file rtl/lookasid.c.

References MINIMUM_LOOKASIDE_DEPTH, and RtlpInitializeSListHead.

Referenced by RtlCreateHeap().

00052 : 00053 00054 This function initializes a heap lookaside list structure 00055 00056 Arguments: 00057 00058 Lookaside - Supplies a pointer to a heap lookaside list structure. 00059 00060 Allocate - Supplies a pointer to an allocate function. 00061 00062 Free - Supplies a pointer to a free function. 00063 00064 HeapHandle - Supplies a pointer to the heap that backs this lookaside list 00065 00066 Flags - Supplies a set of heap flags. 00067 00068 Size - Supplies the size for the lookaside list entries. 00069 00070 Depth - Supplies the maximum depth of the lookaside list. 00071 00072 Return Value: 00073 00074 None. 00075 00076 --*/ 00077 00078 { 00079 00080 // 00081 // Initialize the lookaside list structure. 00082 // 00083 00084 RtlpInitializeSListHead(&Lookaside->ListHead); 00085 00086 Lookaside->Depth = MINIMUM_LOOKASIDE_DEPTH; 00087 Lookaside->MaximumDepth = 256; //Depth; 00088 Lookaside->TotalAllocates = 0; 00089 Lookaside->AllocateMisses = 0; 00090 Lookaside->TotalFrees = 0; 00091 Lookaside->FreeMisses = 0; 00092 00093 Lookaside->LastTotalAllocates = 0; 00094 Lookaside->LastAllocateMisses = 0; 00095 00096 return; 00097 }

BOOLEAN RtlpInitializeHeapSegment IN PHEAP  Heap,
IN PHEAP_SEGMENT  Segment,
IN UCHAR  SegmentIndex,
IN ULONG  Flags,
IN PVOID  BaseAddress,
IN PVOID  UnCommittedAddress,
IN PVOID  CommitLimitAddress
 

Definition at line 4732 of file rtl/heap.c.

References FALSE, _HEAP_ENTRY::Flags, HEAP_ENTRY_BUSY, HEAP_ENTRY_LAST_ENTRY, HEAP_GRANULARITY, HEAP_GRANULARITY_SHIFT, HEAP_SEGMENT_SIGNATURE, NT_SUCCESS, NtGlobalFlag, NTSTATUS(), PAGE_SIZE, _HEAP_ENTRY::PreviousSize, ROUND_UP_TO_POWER2, RTL_PAGED_CODE, RtlGetNtGlobalFlags(), RtlpInsertFreeBlock(), RtlpInsertUnCommittedPages(), _HEAP_ENTRY::SegmentIndex, Size, Status, TRUE, and USHORT.

Referenced by RtlCreateHeap(), RtlExtendHeap(), and RtlpExtendHeap().

04744 : 04745 04746 This routines initializes the internal structures for a heap segment. 04747 The caller supplies the heap and the memory for the segment being 04748 initialized 04749 04750 Arguments: 04751 04752 Heap - Supplies the address of the heap owning this segment 04753 04754 Segment - Supplies a pointer to the segment being initialized 04755 04756 SegmentIndex - Supplies the segement index within the heap that this 04757 new segment is being assigned 04758 04759 Flags - Supplies flags controlling the initialization of the segment 04760 Valid flags are: 04761 04762 HEAP_SEGMENT_USER_ALLOCATED 04763 04764 BaseAddress - Supplies the base address for the segment 04765 04766 UnCommittedAddress - Supplies the address where the uncommited range starts 04767 04768 CommitLimitAddress - Supplies the top address available to the segment 04769 04770 Return Value: 04771 04772 BOOLEAN - TRUE if the initialization is successful and FALSE otherwise 04773 04774 --*/ 04775 04776 { 04777 NTSTATUS Status; 04778 PHEAP_ENTRY FirstEntry; 04779 USHORT PreviousSize, Size; 04780 ULONG NumberOfPages; 04781 ULONG NumberOfCommittedPages; 04782 ULONG NumberOfUnCommittedPages; 04783 SIZE_T CommitSize; 04784 ULONG NtGlobalFlag = RtlGetNtGlobalFlags(); 04785 04786 RTL_PAGED_CODE(); 04787 04788 // 04789 // Compute the total number of pages possible in this segment 04790 // 04791 04792 NumberOfPages = (ULONG) (((PCHAR)CommitLimitAddress - (PCHAR)BaseAddress) / PAGE_SIZE); 04793 04794 // 04795 // First entry points to the first possible segment entry after 04796 // the segment header 04797 // 04798 04799 FirstEntry = (PHEAP_ENTRY)ROUND_UP_TO_POWER2( Segment + 1, 04800 HEAP_GRANULARITY ); 04801 04802 // 04803 // Now if the heap is equal to the base address for the segment which 04804 // it the case for the segment zero then the previous size is the 04805 // heap header. Otherwise there isn't a previous entry 04806 // 04807 04808 if ((PVOID)Heap == BaseAddress) { 04809 04810 PreviousSize = Heap->Entry.Size; 04811 04812 } else { 04813 04814 PreviousSize = 0; 04815 } 04816 04817 // 04818 // Compute the index size of the segement header 04819 // 04820 04821 Size = (USHORT)(((PCHAR)FirstEntry - (PCHAR)Segment) >> HEAP_GRANULARITY_SHIFT); 04822 04823 // 04824 // If the first available heap entry is not committed and 04825 // it is beyond the heap limit then we cannot initialize 04826 // 04827 04828 if ((PCHAR)(FirstEntry + 1) >= (PCHAR)UnCommittedAddress) { 04829 04830 if ((PCHAR)(FirstEntry + 1) >= (PCHAR)CommitLimitAddress) { 04831 04832 return FALSE; 04833 } 04834 04835 // 04836 // Enough of the segment has not been committed so we 04837 // will commit enough now to handle the first entry 04838 // 04839 04840 CommitSize = (PCHAR)(FirstEntry + 1) - (PCHAR)UnCommittedAddress; 04841 04842 Status = ZwAllocateVirtualMemory( NtCurrentProcess(), 04843 (PVOID *)&UnCommittedAddress, 04844 0, 04845 &CommitSize, 04846 MEM_COMMIT, 04847 PAGE_READWRITE ); 04848 04849 if (!NT_SUCCESS( Status )) { 04850 04851 return FALSE; 04852 } 04853 04854 // 04855 // Because we had to commit some memory we need to adjust 04856 // the uncommited address 04857 // 04858 04859 UnCommittedAddress = (PVOID)((PCHAR)UnCommittedAddress + CommitSize); 04860 } 04861 04862 // 04863 // At this point we know there is enough memory committed to handle the 04864 // segment header and one heap entry 04865 // 04866 // Now compute the number of uncommited pages and the number of committed 04867 // pages 04868 // 04869 04870 NumberOfUnCommittedPages = (ULONG)(((PCHAR)CommitLimitAddress - (PCHAR)UnCommittedAddress) / PAGE_SIZE); 04871 NumberOfCommittedPages = NumberOfPages - NumberOfUnCommittedPages; 04872 04873 // 04874 // Initialize the heap segment heap entry. We 04875 // calculated earlier if there was a previous entry 04876 // 04877 04878 Segment->Entry.PreviousSize = PreviousSize; 04879 Segment->Entry.Size = Size; 04880 Segment->Entry.Flags = HEAP_ENTRY_BUSY; 04881 Segment->Entry.SegmentIndex = SegmentIndex; 04882 04883 #if i386 && !NTOS_KERNEL_RUNTIME 04884 04885 // 04886 // In the non kernel x86 case see if we need to capture the callers stack 04887 // backtrace 04888 // 04889 04890 if (NtGlobalFlag & FLG_USER_STACK_TRACE_DB) { 04891 04892 Segment->AllocatorBackTraceIndex = (USHORT)RtlLogStackBackTrace(); 04893 } 04894 04895 #endif // i386 && !NTOS_KERNEL_RUNTIME 04896 04897 // 04898 // Now initializes the heap segment 04899 // 04900 04901 Segment->Signature = HEAP_SEGMENT_SIGNATURE; 04902 Segment->Flags = Flags; 04903 Segment->Heap = Heap; 04904 Segment->BaseAddress = BaseAddress; 04905 Segment->FirstEntry = FirstEntry; 04906 Segment->LastValidEntry = (PHEAP_ENTRY)((PCHAR)BaseAddress + (NumberOfPages * PAGE_SIZE)); 04907 Segment->NumberOfPages = NumberOfPages; 04908 Segment->NumberOfUnCommittedPages = NumberOfUnCommittedPages; 04909 04910 // 04911 // If there are uncommitted pages then we need to insert them 04912 // into the uncommitted ranges list 04913 // 04914 04915 if (NumberOfUnCommittedPages) { 04916 04917 RtlpInsertUnCommittedPages( Segment, 04918 (ULONG_PTR)UnCommittedAddress, 04919 NumberOfUnCommittedPages * PAGE_SIZE ); 04920 } 04921 04922 // 04923 // Have the containing heap point to this segment via the specified index 04924 // 04925 04926 Heap->Segments[ SegmentIndex ] = Segment; 04927 04928 // 04929 // Initialize the first free heap entry after the heap segment header and 04930 // put it in the free list. This first entry will be for whatever is left 04931 // of the committed range 04932 // 04933 04934 PreviousSize = Segment->Entry.Size; 04935 FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY; 04936 04937 Segment->LastEntryInSegment = FirstEntry; 04938 04939 FirstEntry->PreviousSize = PreviousSize; 04940 FirstEntry->SegmentIndex = SegmentIndex; 04941 04942 RtlpInsertFreeBlock( Heap, 04943 (PHEAP_FREE_ENTRY)FirstEntry, 04944 (PHEAP_ENTRY)UnCommittedAddress - FirstEntry); 04945 04946 // 04947 // And return to our caller 04948 // 04949 04950 return TRUE; 04951 }

VOID RtlpInsertFreeBlock IN PHEAP  Heap,
IN PHEAP_FREE_ENTRY  FreeBlock,
IN SIZE_T  FreeSize
 

Definition at line 5849 of file rtl/heap.c.

References _HEAP_SEGMENT::Flags, HEAP_ENTRY_LAST_ENTRY, HEAP_MAXIMUM_BLOCK_SIZE, _HEAP_SEGMENT::LastValidEntry, RTL_PAGED_CODE, RtlpInsertFreeBlockDirect, Size, and USHORT.

Referenced by RtlAllocateHeap(), RtlAllocateHeapSlowly(), RtlFreeHeap(), RtlFreeHeapSlowly(), RtlpCoalesceHeap(), RtlpDeCommitFreeBlock(), RtlpExtendHeap(), RtlpGrowBlockInPlace(), RtlpInitializeHeapSegment(), and RtlReAllocateHeap().

05857 : 05858 05859 This routines take a piece of committed memory and adds to the 05860 the appropriate free lists for the heap. If necessary this 05861 routine will divide up the free block to sizes that fit 05862 on the free list 05863 05864 05865 Arguments: 05866 05867 Heap - Supplies a pointer to the owning heap 05868 05869 FreeBlock - Supplies a pointer to the block being freed 05870 05871 FreeSize - Supplies the size, in bytes, of the block being freed 05872 05873 Return Value: 05874 05875 None. 05876 05877 --*/ 05878 05879 { 05880 USHORT PreviousSize, Size; 05881 UCHAR Flags; 05882 UCHAR SegmentIndex; 05883 PHEAP_SEGMENT Segment; 05884 05885 RTL_PAGED_CODE(); 05886 05887 // 05888 // Get the size of the previous block, the index of the segment 05889 // containing this block, and the flags specific to the block 05890 // 05891 05892 PreviousSize = FreeBlock->PreviousSize; 05893 05894 SegmentIndex = FreeBlock->SegmentIndex; 05895 Segment = Heap->Segments[ SegmentIndex ]; 05896 05897 Flags = FreeBlock->Flags; 05898 05899 // 05900 // Adjust the total amount free in the heap 05901 // 05902 05903 Heap->TotalFreeSize += FreeSize; 05904 05905 // 05906 // Now, while there is still something left to add to the free list 05907 // we'll process the information 05908 // 05909 05910 while (FreeSize != 0) { 05911 05912 // 05913 // If the size is too big for our free lists then we'll 05914 // chop it down. 05915 // 05916 05917 if (FreeSize > (ULONG)HEAP_MAXIMUM_BLOCK_SIZE) { 05918 05919 Size = HEAP_MAXIMUM_BLOCK_SIZE; 05920 05921 // 05922 // This little adjustment is so that we don't have a remainder 05923 // that is too small to be useful on the next iteration 05924 // through the loop 05925 // 05926 05927 if (FreeSize == ((ULONG)HEAP_MAXIMUM_BLOCK_SIZE + 1)) { 05928 05929 Size -= 16; 05930 } 05931 05932 // 05933 // Guarantee that Last entry does not get set in this 05934 // block. 05935 // 05936 05937 FreeBlock->Flags = 0; 05938 05939 } else { 05940 05941 Size = (USHORT)FreeSize; 05942 05943 // 05944 // This could propagate the last entry flag 05945 // 05946 05947 FreeBlock->Flags = Flags; 05948 } 05949 05950 // 05951 // Update the block sizes and then insert this 05952 // block into a free list 05953 // 05954 05955 FreeBlock->PreviousSize = PreviousSize; 05956 FreeBlock->SegmentIndex = SegmentIndex; 05957 FreeBlock->Size = Size; 05958 05959 RtlpInsertFreeBlockDirect( Heap, FreeBlock, Size ); 05960 05961 // 05962 // Note the size of what we just freed, and then update 05963 // our state information for the next time through the 05964 // loop 05965 // 05966 05967 PreviousSize = Size; 05968 05969 FreeSize -= Size; 05970 FreeBlock = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeBlock + Size); 05971 05972 // 05973 // Check if we're done with the free block based on the 05974 // segment information, otherwise go back up and check size 05975 // Note that is means that we can get called with a very 05976 // large size and still work. 05977 // 05978 05979 if ((PHEAP_ENTRY)FreeBlock >= Segment->LastValidEntry) { 05980 05981 return; 05982 } 05983 } 05984 05985 // 05986 // If the block we're freeing did not think it was the last entry 05987 // then tell the next block our real size. 05988 // 05989 05990 if (!(Flags & HEAP_ENTRY_LAST_ENTRY)) { 05991 05992 FreeBlock->PreviousSize = PreviousSize; 05993 } 05994 05995 // 05996 // And return to our caller 05997 // 05998 05999 return; 06000 }

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_PSEUDO_TAG_ENTRY::Allocs, _HEAP_TAG_ENTRY::Allocs, _HEAP_PSEUDO_TAG_ENTRY::Frees, _HEAP_TAG_ENTRY::Frees, HEAP_NUMBER_OF_PSEUDO_TAG, _HEAP::NextAvailableTagIndex, NULL, _HEAP::PseudoTagEntries, _HEAP_PSEUDO_TAG_ENTRY::Size, _HEAP_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 RtlpUpdateHeapListIndex USHORT  OldIndex,
USHORT  NewIndex
 

Definition at line 76 of file heapdbg.c.

References _HEAP_STOP_ON_VALUES::AllocTag, _HEAP_STOP_ON_VALUES::FreeTag, _HEAP_STOP_ON_TAG::HeapIndex, _HEAP_STOP_ON_VALUES::ReAllocTag, and RtlpHeapStopOn.

Referenced by RtlpRemoveHeapFromProcessList().

00083 : 00084 00085 Arguments: 00086 00087 Return Value: 00088 00089 --*/ 00090 00091 { 00092 if (RtlpHeapStopOn.AllocTag.HeapIndex == OldIndex) { 00093 00094 RtlpHeapStopOn.AllocTag.HeapIndex = NewIndex; 00095 } 00096 00097 if (RtlpHeapStopOn.ReAllocTag.HeapIndex == OldIndex) { 00098 00099 RtlpHeapStopOn.ReAllocTag.HeapIndex = NewIndex; 00100 } 00101 00102 if (RtlpHeapStopOn.FreeTag.HeapIndex == OldIndex) { 00103 00104 RtlpHeapStopOn.FreeTag.HeapIndex = NewIndex; 00105 } 00106 00107 return; 00108 }

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 }

BOOLEAN RtlpValidateHeap IN PHEAP  Heap,
IN BOOLEAN  AlwaysValidate
 

Definition at line 2025 of file heapdbg.c.

References _HEAP_VIRTUAL_ALLOC_ENTRY::BusyBlock, _HEAP_VIRTUAL_ALLOC_ENTRY::CommitSize, exit, _HEAP_VIRTUAL_ALLOC_ENTRY::ExtraStuff, FALSE, _HEAP_ENTRY::Flags, HEAP_ENTRY_BUSY, HEAP_ENTRY_FILL_PATTERN, HEAP_GRANULARITY_SHIFT, HEAP_MAXIMUM_FREELISTS, HEAP_MAXIMUM_SEGMENTS, HEAP_NUMBER_OF_PSEUDO_TAG, HEAP_VALIDATE_ALL_ENABLED, HeapDebugBreak, HeapDebugPrint, NT_SUCCESS, NtAllocateVirtualMemory(), NtFreeVirtualMemory(), NTSTATUS(), NULL, RTL_PAGED_CODE, RtlpCheckBusyBlockTail(), RtlpValidateHeapHeaders(), RtlpValidateHeapSegment(), RtlpValidateHeapTagsEnable, _HEAP_TAG_ENTRY::Size, _HEAP_PSEUDO_TAG_ENTRY::Size, Size, Status, _HEAP_ENTRY_EXTRA::TagIndex, _HEAP_TAG_ENTRY::TagName, TRUE, and USHORT.

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

02032 : 02033 02034 Arguments: 02035 02036 Return Value: 02037 02038 --*/ 02039 02040 { 02041 NTSTATUS Status; 02042 PHEAP_SEGMENT Segment; 02043 PLIST_ENTRY Head, Next; 02044 PHEAP_FREE_ENTRY FreeBlock; 02045 BOOLEAN EmptyFreeList; 02046 ULONG NumberOfFreeListEntries; 02047 ULONG CountOfFreeBlocks; 02048 SIZE_T TotalFreeSize; 02049 SIZE_T Size; 02050 USHORT PreviousSize; 02051 UCHAR SegmentIndex; 02052 PVOID BadAddress; 02053 PSIZE_T ComputedTagEntries = NULL; 02054 PSIZE_T ComputedPseudoTagEntries = NULL; 02055 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock; 02056 USHORT TagIndex; 02057 02058 RTL_PAGED_CODE(); 02059 02060 BadAddress = Heap; 02061 02062 if (!RtlpValidateHeapHeaders( Heap, FALSE )) { 02063 02064 goto errorExit; 02065 } 02066 02067 if (!AlwaysValidate && !(Heap->Flags & HEAP_VALIDATE_ALL_ENABLED)) { 02068 02069 goto exit; 02070 } 02071 02072 NumberOfFreeListEntries = 0; 02073 Head = &Heap->FreeLists[ 0 ]; 02074 02075 for (Size = 0; Size < HEAP_MAXIMUM_FREELISTS; Size++) { 02076 02077 if (Size != 0) { 02078 02079 EmptyFreeList = (BOOLEAN)(IsListEmpty( Head )); 02080 BadAddress = &Heap->u.FreeListsInUseBytes[ Size / 8 ]; 02081 02082 if (Heap->u.FreeListsInUseBytes[ Size / 8 ] & (1 << (Size & 7)) ) { 02083 02084 if (EmptyFreeList) { 02085 02086 HeapDebugPrint(( "dedicated (%04x) free list empty but marked as non-empty\n", 02087 Size )); 02088 02089 goto errorExit; 02090 } 02091 02092 } else { 02093 02094 if (!EmptyFreeList) { 02095 02096 HeapDebugPrint(( "dedicated (%04x) free list non-empty but marked as empty\n", 02097 Size )); 02098 02099 goto errorExit; 02100 } 02101 } 02102 } 02103 02104 Next = Head->Flink; 02105 PreviousSize = 0; 02106 02107 while (Head != Next) { 02108 02109 FreeBlock = CONTAINING_RECORD( Next, HEAP_FREE_ENTRY, FreeList ); 02110 Next = Next->Flink; 02111 02112 BadAddress = FreeBlock; 02113 02114 if (FreeBlock->Flags & HEAP_ENTRY_BUSY) { 02115 02116 HeapDebugPrint(( "dedicated (%04x) free list element %lx is marked busy\n", 02117 Size, 02118 FreeBlock )); 02119 02120 goto errorExit; 02121 } 02122 02123 if ((Size != 0) && (FreeBlock->Size != Size)) { 02124 02125 HeapDebugPrint(( "Dedicated (%04x) free list element %lx is wrong size (%04x)\n", 02126 Size, 02127 FreeBlock, 02128 FreeBlock->Size )); 02129 02130 goto errorExit; 02131 02132 } else if ((Size == 0) && (FreeBlock->Size < HEAP_MAXIMUM_FREELISTS)) { 02133 02134 HeapDebugPrint(( "Non-Dedicated free list element %lx with too small size (%04x)\n", 02135 FreeBlock, 02136 FreeBlock->Size )); 02137 02138 goto errorExit; 02139 02140 } else if ((Size == 0) && (FreeBlock->Size < PreviousSize)) { 02141 02142 HeapDebugPrint(( "Non-Dedicated free list element %lx is out of order\n", 02143 FreeBlock )); 02144 02145 goto errorExit; 02146 02147 } else { 02148 02149 PreviousSize = FreeBlock->Size; 02150 } 02151 02152 NumberOfFreeListEntries++; 02153 } 02154 02155 Head++; 02156 } 02157 02158 Size = (HEAP_NUMBER_OF_PSEUDO_TAG + Heap->NextAvailableTagIndex + 1) * sizeof( SIZE_T ); 02159 02160 if ((RtlpValidateHeapTagsEnable) && (Heap->PseudoTagEntries != NULL)) { 02161 02162 Status = NtAllocateVirtualMemory( NtCurrentProcess(), 02163 &ComputedPseudoTagEntries, 02164 0, 02165 &Size, 02166 MEM_COMMIT, 02167 PAGE_READWRITE ); 02168 02169 if (NT_SUCCESS( Status )) { 02170 02171 ComputedTagEntries = ComputedPseudoTagEntries + HEAP_NUMBER_OF_PSEUDO_TAG; 02172 } 02173 } 02174 02175 Head = &Heap->VirtualAllocdBlocks; 02176 Next = Head->Flink; 02177 02178 while (Head != Next) { 02179 02180 VirtualAllocBlock = CONTAINING_RECORD( Next, HEAP_VIRTUAL_ALLOC_ENTRY, Entry ); 02181 02182 if (ComputedTagEntries != NULL) { 02183 02184 TagIndex = VirtualAllocBlock->ExtraStuff.TagIndex; 02185 02186 if (TagIndex != 0) { 02187 02188 if (TagIndex & HEAP_PSEUDO_TAG_FLAG) { 02189 02190 TagIndex &= ~HEAP_PSEUDO_TAG_FLAG; 02191 02192 if (TagIndex < HEAP_NUMBER_OF_PSEUDO_TAG) { 02193 02194 ComputedPseudoTagEntries[ TagIndex ] += 02195 VirtualAllocBlock->CommitSize >> HEAP_GRANULARITY_SHIFT; 02196 } 02197 02198 } else if (TagIndex & HEAP_GLOBAL_TAG) { 02199 02200 // 02201 // Ignore these since they are global across more than 02202 // one heap. 02203 // 02204 02205 } else if (TagIndex < Heap->NextAvailableTagIndex) { 02206 02207 ComputedTagEntries[ TagIndex ] += 02208 VirtualAllocBlock->CommitSize >> HEAP_GRANULARITY_SHIFT; 02209 } 02210 } 02211 } 02212 02213 if (VirtualAllocBlock->BusyBlock.Flags & HEAP_ENTRY_FILL_PATTERN) { 02214 02215 if (!RtlpCheckBusyBlockTail( &VirtualAllocBlock->BusyBlock )) { 02216 02217 return FALSE; 02218 } 02219 } 02220 02221 Next = Next->Flink; 02222 } 02223 02224 CountOfFreeBlocks = 0; 02225 TotalFreeSize = 0; 02226 02227 for (SegmentIndex=0; SegmentIndex<HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) { 02228 02229 Segment = Heap->Segments[ SegmentIndex ]; 02230 02231 if (Segment) { 02232 02233 if (!RtlpValidateHeapSegment( Heap, 02234 Segment, 02235 SegmentIndex, 02236 &CountOfFreeBlocks, 02237 &TotalFreeSize, 02238 &BadAddress, 02239 ComputedTagEntries, 02240 ComputedPseudoTagEntries )) { 02241 02242 goto errorExit; 02243 } 02244 } 02245 } 02246 02247 BadAddress = Heap; 02248 02249 if (NumberOfFreeListEntries != CountOfFreeBlocks) { 02250 02251 HeapDebugPrint(( "Number of free blocks in arena (%ld) does not match number in the free lists (%ld)\n", 02252 CountOfFreeBlocks, 02253 NumberOfFreeListEntries )); 02254 02255 goto errorExit; 02256 } 02257 02258 if (Heap->TotalFreeSize != TotalFreeSize) { 02259 02260 HeapDebugPrint(( "Total size of free blocks in arena (%ld) does not match number total in heap header (%ld)\n", 02261 TotalFreeSize, 02262 Heap->TotalFreeSize )); 02263 02264 goto errorExit; 02265 } 02266 02267 if (ComputedPseudoTagEntries != NULL) { 02268 02269 PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries; 02270 PHEAP_TAG_ENTRY TagEntries; 02271 USHORT TagIndex; 02272 02273 PseudoTagEntries = Heap->PseudoTagEntries; 02274 02275 if (PseudoTagEntries != NULL) { 02276 02277 for (TagIndex=1; TagIndex<HEAP_NUMBER_OF_PSEUDO_TAG; TagIndex++) { 02278 02279 PseudoTagEntries += 1; 02280 02281 if (ComputedPseudoTagEntries[ TagIndex ] != PseudoTagEntries->Size) { 02282 02283 HeapDebugPrint(( "Pseudo Tag %04x size incorrect (%x != %x) %x\n", 02284 TagIndex, 02285 PseudoTagEntries->Size, 02286 ComputedPseudoTagEntries[ TagIndex ] 02287 &ComputedPseudoTagEntries[ TagIndex ] )); 02288 02289 goto errorExit; 02290 } 02291 } 02292 } 02293 02294 TagEntries = Heap->TagEntries; 02295 02296 if (TagEntries != NULL) { 02297 02298 for (TagIndex=1; TagIndex<Heap->NextAvailableTagIndex; TagIndex++) { 02299 02300 TagEntries += 1; 02301 02302 if (ComputedTagEntries[ TagIndex ] != TagEntries->Size) { 02303 02304 HeapDebugPrint(( "Tag %04x (%ws) size incorrect (%x != %x) %x\n", 02305 TagIndex, 02306 TagEntries->TagName, 02307 TagEntries->Size, 02308 ComputedTagEntries[ TagIndex ], 02309 &ComputedTagEntries[ TagIndex ] )); 02310 02311 goto errorExit; 02312 } 02313 } 02314 } 02315 02316 Size = 0; 02317 02318 NtFreeVirtualMemory( NtCurrentProcess(), 02319 &ComputedPseudoTagEntries, 02320 &Size, 02321 MEM_RELEASE ); 02322 } 02323 02324 exit: 02325 02326 return TRUE; 02327 02328 errorExit: 02329 02330 HeapDebugBreak( BadAddress ); 02331 02332 if (ComputedPseudoTagEntries != NULL) { 02333 02334 Size = 0; 02335 02336 NtFreeVirtualMemory( NtCurrentProcess(), 02337 &ComputedPseudoTagEntries, 02338 &Size, 02339 MEM_RELEASE ); 02340 } 02341 02342 return FALSE; 02343 02344 }

BOOLEAN RtlpValidateHeapEntry IN PHEAP  Heap,
IN PHEAP_ENTRY  BusyBlock,
IN PCHAR  Reason
 

Definition at line 1696 of file heapdbg.c.

References FALSE, _HEAP_SEGMENT::FirstEntry, HEAP_ENTRY_BUSY, HEAP_ENTRY_FILL_PATTERN, HEAP_ENTRY_VIRTUAL_ALLOC, HEAP_GRANULARITY, HEAP_MAXIMUM_SEGMENTS, HeapDebugBreak, HeapDebugPrint, _HEAP_SEGMENT::LastValidEntry, NULL, PAGE_SIZE, RtlpCheckBusyBlockTail(), and TRUE.

Referenced by RtlDebugFreeHeap(), RtlDebugGetUserInfoHeap(), RtlDebugReAllocateHeap(), RtlDebugSetUserFlagsHeap(), RtlDebugSetUserValueHeap(), RtlDebugSizeHeap(), and RtlValidateHeap().

01704 : 01705 01706 Arguments: 01707 01708 Return Value: 01709 01710 --*/ 01711 01712 { 01713 PHEAP_SEGMENT Segment; 01714 UCHAR SegmentIndex; 01715 BOOLEAN Result; 01716 01717 if ((BusyBlock == NULL) 01718 01719 || 01720 01721 ((ULONG_PTR)BusyBlock & (HEAP_GRANULARITY-1)) 01722 01723 || 01724 01725 ((BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) && 01726 ((ULONG_PTR)BusyBlock & (PAGE_SIZE-1)) != FIELD_OFFSET( HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock )) 01727 01728 || 01729 01730 (!(BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) && 01731 ((BusyBlock->SegmentIndex >= HEAP_MAXIMUM_SEGMENTS) || 01732 !(Segment = Heap->Segments[ BusyBlock->SegmentIndex ]) || 01733 (BusyBlock < Segment->FirstEntry) || 01734 (BusyBlock >= Segment->LastValidEntry))) 01735 01736 || 01737 01738 !(BusyBlock->Flags & HEAP_ENTRY_BUSY) 01739 01740 || 01741 01742 ((BusyBlock->Flags & HEAP_ENTRY_FILL_PATTERN) && !RtlpCheckBusyBlockTail( BusyBlock ))) { 01743 01744 InvalidBlock: 01745 01746 HeapDebugPrint(( "Invalid Address specified to %s( %lx, %lx )\n", 01747 Reason, 01748 Heap, 01749 BusyBlock + 1 )); 01750 01751 HeapDebugBreak( BusyBlock ); 01752 01753 return FALSE; 01754 01755 } else { 01756 01757 if (BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) { 01758 01759 Result = TRUE; 01760 01761 } else { 01762 01763 for (SegmentIndex=0; SegmentIndex<HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) { 01764 01765 Segment = Heap->Segments[ SegmentIndex ]; 01766 01767 if (Segment) { 01768 01769 if ((BusyBlock >= Segment->FirstEntry) && 01770 (BusyBlock < Segment->LastValidEntry)) { 01771 01772 Result = TRUE; 01773 break; 01774 } 01775 } 01776 } 01777 } 01778 01779 if (!Result) { 01780 01781 goto InvalidBlock; 01782 } 01783 01784 return TRUE; 01785 } 01786 }

BOOLEAN RtlpValidateHeapHeaders IN PHEAP  Heap,
IN BOOLEAN  Recompute
 

Definition at line 112 of file heapdbg.c.

References DbgPrint, Description, FALSE, HeapDebugPrint, n, NT_SUCCESS, NtAllocateVirtualMemory(), NTSTATUS(), NULL, RtlpHeapHeaderFieldOffsets, RtlpValidateHeapHdrsEnable, Status, and TRUE.

Referenced by RtlDebugAllocateHeap(), RtlDebugCompactHeap(), RtlDebugCreateHeap(), RtlDebugCreateTagHeap(), RtlDebugFreeHeap(), RtlDebugReAllocateHeap(), RtlpGrowBlockInPlace(), RtlpSerializeHeap(), and RtlpValidateHeap().

00119 : 00120 00121 Arguments: 00122 00123 Return Value: 00124 00125 --*/ 00126 00127 { 00128 ULONG i; 00129 SIZE_T n; 00130 SIZE_T nEqual; 00131 NTSTATUS Status; 00132 00133 if (!RtlpValidateHeapHdrsEnable) { 00134 00135 return TRUE; 00136 } 00137 00138 if (Heap->HeaderValidateCopy == NULL) { 00139 00140 n = Heap->HeaderValidateLength; 00141 00142 Status = NtAllocateVirtualMemory( NtCurrentProcess(), 00143 &Heap->HeaderValidateCopy, 00144 0, 00145 &n, 00146 MEM_COMMIT, 00147 PAGE_READWRITE ); 00148 00149 if (!NT_SUCCESS( Status )) { 00150 00151 return TRUE; 00152 } 00153 00154 Recompute = TRUE; 00155 } 00156 00157 n = Heap->HeaderValidateLength; 00158 00159 if (!Recompute) { 00160 00161 nEqual = RtlCompareMemory( Heap, 00162 Heap->HeaderValidateCopy, 00163 n ); 00164 00165 } else { 00166 00167 RtlMoveMemory( Heap->HeaderValidateCopy, 00168 Heap, 00169 n ); 00170 00171 nEqual = n; 00172 } 00173 00174 if (n != nEqual) { 00175 00176 HeapDebugPrint(( "Heap %x - headers modified (%x is %x instead of %x)\n", 00177 Heap, 00178 (PCHAR)Heap + nEqual, 00179 *(PULONG)((PCHAR)Heap + nEqual), 00180 *(PULONG)((PCHAR)Heap->HeaderValidateCopy + nEqual))); 00181 00182 for (i=0; RtlpHeapHeaderFieldOffsets[ i ].Description != NULL; i++) { 00183 00184 if ((nEqual >= RtlpHeapHeaderFieldOffsets[ i ].Offset) && 00185 (nEqual < RtlpHeapHeaderFieldOffsets[ i+1 ].Offset)) { 00186 00187 DbgPrint( " This is located in the %s field of the heap header.\n", 00188 RtlpHeapHeaderFieldOffsets[ i ].Description ); 00189 00190 break; 00191 } 00192 } 00193 00194 return FALSE; 00195 00196 } else { 00197 00198 return TRUE; 00199 } 00200 }


Variable Documentation

UCHAR CheckHeapFillPattern[CHECK_HEAP_TAIL_SIZE]
 

Definition at line 46 of file heappriv.h.


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