ReactOS  0.4.15-dev-1070-ge1a01de
heap.c File Reference
#include <rtl.h>
#include <heap.h>
#include <debug.h>
Include dependency graph for heap.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

FORCEINLINE UCHAR RtlpFindLeastSetBit (ULONG Bits)
 
NTSTATUS NTAPI RtlpInitializeHeap (OUT PHEAP Heap, IN ULONG Flags, IN PHEAP_LOCK Lock OPTIONAL, IN PRTL_HEAP_PARAMETERS Parameters)
 
FORCEINLINE VOID RtlpSetFreeListsBit (PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry)
 
FORCEINLINE VOID RtlpClearFreeListsBit (PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry)
 
VOID NTAPI RtlpInsertFreeBlockHelper (PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
 
VOID NTAPI RtlpInsertFreeBlock (PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
 
VOID NTAPI RtlpRemoveFreeBlock (PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN Dedicated, BOOLEAN NoFill)
 
SIZE_T NTAPI RtlpGetSizeOfBigBlock (PHEAP_ENTRY HeapEntry)
 
PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange (PHEAP_SEGMENT Segment)
 
VOID NTAPI RtlpDestroyUnCommittedRange (PHEAP_SEGMENT Segment, PHEAP_UCR_DESCRIPTOR UcrDescriptor)
 
VOID NTAPI RtlpInsertUnCommittedPages (PHEAP_SEGMENT Segment, ULONG_PTR Address, SIZE_T Size)
 
PHEAP_FREE_ENTRY NTAPI RtlpFindAndCommitPages (PHEAP Heap, PHEAP_SEGMENT Segment, PSIZE_T Size, PVOID AddressRequested)
 
VOID NTAPI RtlpDeCommitFreeBlock (PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T Size)
 
NTSTATUS NTAPI RtlpInitializeHeapSegment (IN OUT PHEAP Heap, OUT PHEAP_SEGMENT Segment, IN UCHAR SegmentIndex, IN ULONG SegmentFlags, IN SIZE_T SegmentReserve, IN SIZE_T SegmentCommit)
 
VOID NTAPI RtlpDestroyHeapSegment (PHEAP_SEGMENT Segment)
 
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceHeap (PHEAP Heap)
 
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceFreeBlocks (PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, PSIZE_T FreeSize, BOOLEAN Remove)
 
PHEAP_FREE_ENTRY NTAPI RtlpExtendHeap (PHEAP Heap, SIZE_T Size)
 
HANDLE NTAPI RtlCreateHeap (ULONG Flags, PVOID Addr, SIZE_T TotalSize, SIZE_T CommitSize, PVOID Lock, PRTL_HEAP_PARAMETERS Parameters)
 
HANDLE NTAPI RtlDestroyHeap (HANDLE HeapPtr)
 
PHEAP_ENTRY NTAPI RtlpSplitEntry (PHEAP Heap, ULONG Flags, PHEAP_FREE_ENTRY FreeBlock, SIZE_T AllocationSize, SIZE_T Index, SIZE_T Size)
 
PVOID NTAPI RtlpAllocateNonDedicated (PHEAP Heap, ULONG Flags, SIZE_T Size, SIZE_T AllocationSize, SIZE_T Index, BOOLEAN HeapLocked)
 
PVOID NTAPI RtlAllocateHeap (IN PVOID HeapPtr, IN ULONG Flags, IN SIZE_T Size)
 
BOOLEAN NTAPI RtlFreeHeap (HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
 
BOOLEAN NTAPI RtlpGrowBlockInPlace (IN PHEAP Heap, IN ULONG Flags, IN PHEAP_ENTRY InUseEntry, IN SIZE_T Size, IN SIZE_T Index)
 
PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer (PHEAP_ENTRY HeapEntry)
 
PVOID NTAPI RtlReAllocateHeap (HANDLE HeapPtr, ULONG Flags, PVOID Ptr, SIZE_T Size)
 
ULONG NTAPI RtlCompactHeap (HANDLE Heap, ULONG Flags)
 
BOOLEAN NTAPI RtlLockHeap (IN HANDLE HeapPtr)
 
BOOLEAN NTAPI RtlUnlockHeap (HANDLE HeapPtr)
 
SIZE_T NTAPI RtlSizeHeap (HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
 
BOOLEAN NTAPI RtlpCheckInUsePattern (PHEAP_ENTRY HeapEntry)
 
BOOLEAN NTAPI RtlpValidateHeapHeaders (PHEAP Heap, BOOLEAN Recalculate)
 
BOOLEAN NTAPI RtlpValidateHeapEntry (PHEAP Heap, PHEAP_ENTRY HeapEntry)
 
BOOLEAN NTAPI RtlpValidateHeapSegment (PHEAP Heap, PHEAP_SEGMENT Segment, UCHAR SegmentOffset, PULONG FreeEntriesCount, PSIZE_T TotalFreeSize, PSIZE_T TagEntries, PSIZE_T PseudoTagEntries)
 
BOOLEAN NTAPI RtlpValidateHeap (PHEAP Heap, BOOLEAN ForceValidation)
 
BOOLEAN NTAPI RtlValidateHeap (HANDLE HeapPtr, ULONG Flags, PVOID Block)
 
NTSTATUS NTAPI RtlEnumProcessHeaps (PHEAP_ENUMERATION_ROUTINE HeapEnumerationRoutine, PVOID lParam)
 
ULONG NTAPI RtlGetProcessHeaps (ULONG count, HANDLE *heaps)
 
BOOLEAN NTAPI RtlValidateProcessHeaps (VOID)
 
BOOLEAN NTAPI RtlZeroHeap (IN PVOID HeapHandle, IN ULONG Flags)
 
BOOLEAN NTAPI RtlSetUserValueHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN PVOID UserValue)
 
BOOLEAN NTAPI RtlSetUserFlagsHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN ULONG UserFlagsReset, IN ULONG UserFlagsSet)
 
BOOLEAN NTAPI RtlGetUserInfoHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, OUT PVOID *UserValue, OUT PULONG UserFlags)
 
NTSTATUS NTAPI RtlUsageHeap (IN HANDLE Heap, IN ULONG Flags, OUT PRTL_HEAP_USAGE Usage)
 
PWSTR NTAPI RtlQueryTagHeap (IN PVOID HeapHandle, IN ULONG Flags, IN USHORT TagIndex, IN BOOLEAN ResetCounters, OUT PRTL_HEAP_TAG_INFO HeapTagInfo)
 
ULONG NTAPI RtlExtendHeap (IN HANDLE Heap, IN ULONG Flags, IN PVOID P, IN SIZE_T Size)
 
ULONG NTAPI RtlCreateTagHeap (IN HANDLE HeapHandle, IN ULONG Flags, IN PWSTR TagName, IN PWSTR TagSubName)
 
NTSTATUS NTAPI RtlWalkHeap (IN HANDLE HeapHandle, IN PVOID HeapEntry)
 
PVOID NTAPI RtlProtectHeap (IN PVOID HeapHandle, IN BOOLEAN ReadOnly)
 
NTSTATUS NTAPI RtlSetHeapInformation (IN HANDLE HeapHandle OPTIONAL, IN HEAP_INFORMATION_CLASS HeapInformationClass, IN PVOID HeapInformation, IN SIZE_T HeapInformationLength)
 
NTSTATUS NTAPI RtlQueryHeapInformation (HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass, PVOID HeapInformation, SIZE_T HeapInformationLength, PSIZE_T ReturnLength OPTIONAL)
 
ULONG NTAPI RtlMultipleAllocateHeap (IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size, IN ULONG Count, OUT PVOID *Array)
 
ULONG NTAPI RtlMultipleFreeHeap (IN PVOID HeapHandle, IN ULONG Flags, IN ULONG Count, OUT PVOID *Array)
 
NTSTATUS NTAPI RtlQueryProcessHeapInformation (IN struct _DEBUG_BUFFER *DebugBuffer)
 

Variables

UCHAR RtlpBitsClearLow []
 
UCHAR FillPattern [HEAP_ENTRY_SIZE]
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 25 of file heap.c.

Function Documentation

◆ RtlAllocateHeap()

PVOID NTAPI RtlAllocateHeap ( IN PVOID  HeapPtr,
IN ULONG  Flags,
IN SIZE_T  Size 
)

Definition at line 1954 of file heap.c.

1957 {
1958  PHEAP Heap = (PHEAP)HeapPtr;
1959  PULONG FreeListsInUse;
1960  ULONG FreeListsInUseUlong;
1962  SIZE_T Index, InUseIndex, i;
1963  PLIST_ENTRY FreeListHead;
1964  PHEAP_ENTRY InUseEntry;
1965  PHEAP_FREE_ENTRY FreeBlock;
1966  UCHAR FreeFlags, EntryFlags = HEAP_ENTRY_BUSY;
1967  EXCEPTION_RECORD ExceptionRecord;
1968  BOOLEAN HeapLocked = FALSE;
1969  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualBlock = NULL;
1970  PHEAP_ENTRY_EXTRA Extra;
1971  NTSTATUS Status;
1972 
1973  /* Force flags */
1974  Flags |= Heap->ForceFlags;
1975 
1976  /* Call special heap */
1977  if (RtlpHeapIsSpecial(Flags))
1978  return RtlDebugAllocateHeap(Heap, Flags, Size);
1979 
1980  /* Check for the maximum size */
1981  if (Size >= 0x80000000)
1982  {
1984  DPRINT1("HEAP: Allocation failed!\n");
1985  return NULL;
1986  }
1987 
1989  {
1990  DPRINT1("HEAP: RtlAllocateHeap is called with unsupported flags %x, ignoring\n", Flags);
1991  }
1992 
1993  //DPRINT("RtlAllocateHeap(%p %x %x)\n", Heap, Flags, Size);
1994 
1995  /* Calculate allocation size and index */
1996  if (Size)
1997  AllocationSize = Size;
1998  else
1999  AllocationSize = 1;
2000  AllocationSize = (AllocationSize + Heap->AlignRound) & Heap->AlignMask;
2001 
2002  /* Add extra flags in case of settable user value feature is requested,
2003  or there is a tag (small or normal) or there is a request to
2004  capture stack backtraces */
2006  Heap->PseudoTagEntries)
2007  {
2008  /* Add flag which means that the entry will have extra stuff attached */
2009  EntryFlags |= HEAP_ENTRY_EXTRA_PRESENT;
2010 
2011  /* Account for extra stuff size */
2012  AllocationSize += sizeof(HEAP_ENTRY_EXTRA);
2013  }
2014 
2015  /* Add settable user flags, if any */
2016  EntryFlags |= (Flags & HEAP_SETTABLE_USER_FLAGS) >> 4;
2017 
2019 
2020  /* Acquire the lock if necessary */
2021  if (!(Flags & HEAP_NO_SERIALIZE))
2022  {
2024  HeapLocked = TRUE;
2025  }
2026 
2027  /* Depending on the size, the allocation is going to be done from dedicated,
2028  non-dedicated lists or a virtual block of memory */
2029  if (Index < HEAP_FREELISTS)
2030  {
2031  FreeListHead = &Heap->FreeLists[Index];
2032 
2033  if (!IsListEmpty(FreeListHead))
2034  {
2035  /* There is a free entry in this list */
2036  FreeBlock = CONTAINING_RECORD(FreeListHead->Blink,
2038  FreeList);
2039 
2040  /* Save flags and remove the free entry */
2041  FreeFlags = FreeBlock->Flags;
2042  RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, FALSE);
2043 
2044  /* Update the total free size of the heap */
2045  Heap->TotalFreeSize -= Index;
2046 
2047  /* Initialize this block */
2048  InUseEntry = (PHEAP_ENTRY)FreeBlock;
2049  InUseEntry->Flags = EntryFlags | (FreeFlags & HEAP_ENTRY_LAST_ENTRY);
2050  InUseEntry->UnusedBytes = (UCHAR)(AllocationSize - Size);
2051  InUseEntry->SmallTagIndex = 0;
2052  }
2053  else
2054  {
2055  /* Find smallest free block which this request could fit in */
2056  InUseIndex = Index >> 5;
2057  FreeListsInUse = &Heap->u.FreeListsInUseUlong[InUseIndex];
2058 
2059  /* This bit magic disables all sizes which are less than the requested allocation size */
2060  FreeListsInUseUlong = *FreeListsInUse++ & ~((1 << ((ULONG)Index & 0x1f)) - 1);
2061 
2062  /* If size is definitily more than our lists - go directly to the non-dedicated one */
2063  if (InUseIndex > 3)
2064  return RtlpAllocateNonDedicated(Heap, Flags, Size, AllocationSize, Index, HeapLocked);
2065 
2066  /* Go through the list */
2067  for (i = InUseIndex; i < 4; i++)
2068  {
2069  if (FreeListsInUseUlong)
2070  {
2071  FreeListHead = &Heap->FreeLists[i * 32];
2072  break;
2073  }
2074 
2075  if (i < 3) FreeListsInUseUlong = *FreeListsInUse++;
2076  }
2077 
2078  /* Nothing found, search in the non-dedicated list */
2079  if (i == 4)
2080  return RtlpAllocateNonDedicated(Heap, Flags, Size, AllocationSize, Index, HeapLocked);
2081 
2082  /* That list is found, now calculate exact block */
2083  FreeListHead += RtlpFindLeastSetBit(FreeListsInUseUlong);
2084 
2085  /* Take this entry and remove it from the list of free blocks */
2086  FreeBlock = CONTAINING_RECORD(FreeListHead->Blink,
2088  FreeList);
2089  RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, FALSE);
2090 
2091  /* Split it */
2092  InUseEntry = RtlpSplitEntry(Heap, Flags, FreeBlock, AllocationSize, Index, Size);
2093  }
2094 
2095  /* Release the lock */
2096  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2097 
2098  /* Zero memory if that was requested */
2099  if (Flags & HEAP_ZERO_MEMORY)
2100  RtlZeroMemory(InUseEntry + 1, Size);
2101  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
2102  {
2103  /* Fill this block with a special pattern */
2104  RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
2105  }
2106 
2107  /* Fill tail of the block with a special pattern too if requested */
2108  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
2109  {
2110  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY), HEAP_TAIL_FILL);
2111  InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
2112  }
2113 
2114  /* Prepare extra if it's present */
2115  if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
2116  {
2117  Extra = RtlpGetExtraStuffPointer(InUseEntry);
2118  RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
2119 
2120  // TODO: Tagging
2121  }
2122 
2123  /* User data starts right after the entry's header */
2124  return InUseEntry + 1;
2125  }
2126  else if (Index <= Heap->VirtualMemoryThreshold)
2127  {
2128  /* The block is too large for dedicated lists, but fine for a non-dedicated one */
2129  return RtlpAllocateNonDedicated(Heap, Flags, Size, AllocationSize, Index, HeapLocked);
2130  }
2131  else if (Heap->Flags & HEAP_GROWABLE)
2132  {
2133  /* We've got a very big allocation request, satisfy it by directly allocating virtual memory */
2134  AllocationSize += sizeof(HEAP_VIRTUAL_ALLOC_ENTRY) - sizeof(HEAP_ENTRY);
2135 
2136  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
2137  (PVOID *)&VirtualBlock,
2138  0,
2139  &AllocationSize,
2140  MEM_COMMIT,
2141  PAGE_READWRITE);
2142 
2143  if (!NT_SUCCESS(Status))
2144  {
2145  // Set STATUS!
2146  /* Release the lock */
2147  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2148  DPRINT1("HEAP: Allocation failed!\n");
2149  return NULL;
2150  }
2151 
2152  /* Initialize the newly allocated block */
2153  VirtualBlock->BusyBlock.Size = (USHORT)(AllocationSize - Size);
2154  ASSERT(VirtualBlock->BusyBlock.Size >= sizeof(HEAP_VIRTUAL_ALLOC_ENTRY));
2155  VirtualBlock->BusyBlock.Flags = EntryFlags | HEAP_ENTRY_VIRTUAL_ALLOC | HEAP_ENTRY_EXTRA_PRESENT;
2156  VirtualBlock->CommitSize = AllocationSize;
2157  VirtualBlock->ReserveSize = AllocationSize;
2158 
2159  /* Insert it into the list of virtual allocations */
2160  InsertTailList(&Heap->VirtualAllocdBlocks, &VirtualBlock->Entry);
2161 
2162  /* Release the lock */
2163  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2164 
2165  /* Return pointer to user data */
2166  return VirtualBlock + 1;
2167  }
2168 
2169  /* Generate an exception */
2171  {
2172  ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY;
2173  ExceptionRecord.ExceptionRecord = NULL;
2174  ExceptionRecord.NumberParameters = 1;
2175  ExceptionRecord.ExceptionFlags = 0;
2176  ExceptionRecord.ExceptionInformation[0] = AllocationSize;
2177 
2178  RtlRaiseException(&ExceptionRecord);
2179  }
2180 
2182 
2183  /* Release the lock */
2184  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2185  DPRINT1("HEAP: Allocation failed!\n");
2186  return NULL;
2187 }
signed char * PCHAR
Definition: retypes.h:7
LIST_ENTRY Entry
Definition: heap.h:314
#define ARENA_INUSE_FILLER
Definition: oleaut.c:105
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
Definition: heap.h:312
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:44
SIZE_T TotalFreeSize
Definition: heap.h:240
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#define TRUE
Definition: types.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
LONG NTSTATUS
Definition: precomp.h:26
#define HEAP_EXTRA_FLAGS_MASK
Definition: heap.h:36
#define InsertTailList(ListHead, Entry)
NTSYSAPI VOID NTAPI RtlRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord)
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
#define MEM_COMMIT
Definition: nt_native.h:1313
PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer(PHEAP_ENTRY HeapEntry)
Definition: heap.c:2587
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
ULONG FreeListsInUseUlong[HEAP_FREELISTS/(sizeof(ULONG) *8)]
Definition: heap.h:264
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define HEAP_CREATE_ENABLE_TRACING
Definition: nt_native.h:1702
DWORD ExceptionCode
Definition: compat.h:208
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG_PTR AlignMask
Definition: heap.h:251
SIZE_T ReserveSize
Definition: heap.h:317
#define FALSE
Definition: types.h:117
Definition: heap.h:296
PHEAP_LOCK LockVariable
Definition: heap.h:267
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries
Definition: heap.h:259
Definition: heap.h:130
unsigned char BOOLEAN
struct _HEAP_ENTRY * PHEAP_ENTRY
smooth NULL
Definition: ftsmooth.c:416
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS NTAPI RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:133
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
SIZE_T CommitSize
Definition: heap.h:316
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:252
#define HEAP_GROWABLE
Definition: nt_native.h:1693
static const UCHAR Index[8]
Definition: usbohci.c:18
FORCEINLINE UCHAR RtlpFindLeastSetBit(ULONG Bits)
Definition: heap.c:53
struct _HEAP_VIRTUAL_ALLOC_ENTRY HEAP_VIRTUAL_ALLOC_ENTRY
#define HEAP_SETTABLE_USER_FLAGS
Definition: nt_native.h:1708
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID NTAPI RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN Dedicated, BOOLEAN NoFill)
Definition: heap.c:383
#define HEAP_FREELISTS
Definition: heap.h:15
unsigned char UCHAR
Definition: xmlstorage.h:181
MmuFreePage * FreeList
Definition: mmuobject.c:60
Status
Definition: gdiplustypes.h:24
union _HEAP::@4128 u
PHEAP_ENTRY NTAPI RtlpSplitEntry(PHEAP Heap, ULONG Flags, PHEAP_FREE_ENTRY FreeBlock, SIZE_T AllocationSize, SIZE_T Index, SIZE_T Size)
Definition: heap.c:1661
Definition: typedefs.h:119
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:319
ULONG_PTR SIZE_T
Definition: typedefs.h:80
ULONG_PTR AlignRound
Definition: heap.h:250
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
ULONG Flags
Definition: heap.h:227
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
struct _HEAP_ENTRY_EXTRA HEAP_ENTRY_EXTRA
unsigned int * PULONG
Definition: retypes.h:1
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45
#define DPRINT1
Definition: precomp.h:8
PVOID NTAPI RtlDebugAllocateHeap(PVOID HeapPtr, ULONG Flags, SIZE_T Size)
Definition: heapdbg.c:130
PVOID NTAPI RtlpAllocateNonDedicated(PHEAP Heap, ULONG Flags, SIZE_T Size, SIZE_T AllocationSize, SIZE_T Index, BOOLEAN HeapLocked)
Definition: heap.c:1801
#define HEAP_TAIL_FILL
Definition: heap.h:28
unsigned int ULONG
Definition: retypes.h:1
struct _HEAP * PHEAP
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
DWORD ExceptionFlags
Definition: compat.h:209
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
ULONG ForceFlags
Definition: heap.h:228
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42
HEAP_ENTRY BusyBlock
Definition: heap.h:318
DWORD NumberParameters
Definition: compat.h:212
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
LIST_ENTRY FreeLists[HEAP_FREELISTS]
Definition: heap.h:260
Definition: heap.c:51
#define PAGE_READWRITE
Definition: nt_native.h:1304
FORCEINLINE BOOLEAN RtlpHeapIsSpecial(ULONG Flags)
Definition: heap.h:60

◆ RtlCompactHeap()

ULONG NTAPI RtlCompactHeap ( HANDLE  Heap,
ULONG  Flags 
)

Definition at line 3040 of file heap.c.

3042 {
3043  UNIMPLEMENTED;
3044  return 0;
3045 }
#define UNIMPLEMENTED
Definition: debug.h:115

Referenced by GlobalCompact(), HeapCompact(), LocalCompact(), and LocalShrink().

◆ RtlCreateHeap()

HANDLE NTAPI RtlCreateHeap ( ULONG  Flags,
PVOID  Addr,
SIZE_T  TotalSize,
SIZE_T  CommitSize,
PVOID  Lock,
PRTL_HEAP_PARAMETERS  Parameters 
)

Definition at line 1254 of file heap.c.

1260 {
1261  PVOID CommittedAddress = NULL, UncommittedAddress = NULL;
1262  PHEAP Heap = NULL;
1263  RTL_HEAP_PARAMETERS SafeParams = {0};
1264  ULONG_PTR MaximumUserModeAddress;
1265  SYSTEM_BASIC_INFORMATION SystemInformation;
1266  MEMORY_BASIC_INFORMATION MemoryInfo;
1267  ULONG NtGlobalFlags = RtlGetNtGlobalFlags();
1268  ULONG HeapSegmentFlags = 0;
1269  NTSTATUS Status;
1270  ULONG MaxBlockSize;
1271 
1272  /* Check for a special heap */
1273  if (RtlpPageHeapEnabled && !Addr && !Lock)
1274  {
1275  Heap = RtlpPageHeapCreate(Flags, Addr, TotalSize, CommitSize, Lock, Parameters);
1276  if (Heap) return Heap;
1277 
1278  /* Reset a special Parameters == -1 hack */
1279  if ((ULONG_PTR)Parameters == (ULONG_PTR)-1)
1280  Parameters = NULL;
1281  else
1282  DPRINT1("Enabling page heap failed\n");
1283  }
1284 
1285  /* Check validation flags */
1287  {
1288  DPRINT1("Invalid flags 0x%08x, fixing...\n", Flags);
1290  }
1291 
1292  /* Capture parameters */
1293  if (Parameters)
1294  {
1295  _SEH2_TRY
1296  {
1297  /* If size of structure correct, then copy it */
1298  if (Parameters->Length == sizeof(RTL_HEAP_PARAMETERS))
1299  RtlCopyMemory(&SafeParams, Parameters, sizeof(RTL_HEAP_PARAMETERS));
1300  }
1302  {
1303  _SEH2_YIELD(return NULL);
1304  }
1305  _SEH2_END;
1306  }
1307 
1308  Parameters = &SafeParams;
1309 
1310  /* Check global flags */
1311  if (NtGlobalFlags & FLG_HEAP_DISABLE_COALESCING)
1313 
1314  if (NtGlobalFlags & FLG_HEAP_ENABLE_FREE_CHECK)
1316 
1317  if (NtGlobalFlags & FLG_HEAP_ENABLE_TAIL_CHECK)
1319 
1320  if (RtlpGetMode() == UserMode)
1321  {
1322  /* Also check these flags if in usermode */
1323  if (NtGlobalFlags & FLG_HEAP_VALIDATE_ALL)
1325 
1326  if (NtGlobalFlags & FLG_HEAP_VALIDATE_PARAMETERS)
1328 
1329  if (NtGlobalFlags & FLG_USER_STACK_TRACE_DB)
1331  }
1332 
1333  /* Set tunable parameters */
1335 
1336  /* Get the max um address */
1338  &SystemInformation,
1339  sizeof(SystemInformation),
1340  NULL);
1341 
1342  if (!NT_SUCCESS(Status))
1343  {
1344  DPRINT1("Getting max usermode address failed with status 0x%08x\n", Status);
1345  return NULL;
1346  }
1347 
1348  MaximumUserModeAddress = SystemInformation.MaximumUserModeAddress;
1349 
1350  /* Calculate max alloc size */
1351  if (!Parameters->MaximumAllocationSize)
1352  Parameters->MaximumAllocationSize = MaximumUserModeAddress - (ULONG_PTR)0x10000 - PAGE_SIZE;
1353 
1354  MaxBlockSize = 0x80000 - PAGE_SIZE;
1355 
1356  if (!Parameters->VirtualMemoryThreshold ||
1357  Parameters->VirtualMemoryThreshold > MaxBlockSize)
1358  {
1359  Parameters->VirtualMemoryThreshold = MaxBlockSize;
1360  }
1361 
1362  /* Check reserve/commit sizes and set default values */
1363  if (!CommitSize)
1364  {
1366  if (TotalSize)
1367  TotalSize = ROUND_UP(TotalSize, PAGE_SIZE);
1368  else
1369  TotalSize = 64 * PAGE_SIZE;
1370  }
1371  else
1372  {
1373  /* Round up the commit size to be at least the page size */
1375 
1376  if (TotalSize)
1377  TotalSize = ROUND_UP(TotalSize, PAGE_SIZE);
1378  else
1379  TotalSize = ROUND_UP(CommitSize, 16 * PAGE_SIZE);
1380  }
1381 
1382  /* Call special heap */
1383  if (RtlpHeapIsSpecial(Flags))
1384  return RtlDebugCreateHeap(Flags, Addr, TotalSize, CommitSize, Lock, Parameters);
1385 
1386  /* Without serialization, a lock makes no sense */
1387  if ((Flags & HEAP_NO_SERIALIZE) && (Lock != NULL))
1388  return NULL;
1389 
1390  /* See if we are already provided with an address for the heap */
1391  if (Addr)
1392  {
1393  if (Parameters->CommitRoutine)
1394  {
1395  /* There is a commit routine, so no problem here, check params */
1396  if ((Flags & HEAP_GROWABLE) ||
1397  !Parameters->InitialCommit ||
1398  !Parameters->InitialReserve ||
1399  (Parameters->InitialCommit > Parameters->InitialReserve))
1400  {
1401  /* Fail */
1402  return NULL;
1403  }
1404 
1405  /* Calculate committed and uncommitted addresses */
1406  CommittedAddress = Addr;
1407  UncommittedAddress = (PCHAR)Addr + Parameters->InitialCommit;
1408  TotalSize = Parameters->InitialReserve;
1409 
1410  /* Zero the initial page ourselves */
1411  RtlZeroMemory(CommittedAddress, PAGE_SIZE);
1412  }
1413  else
1414  {
1415  /* Commit routine is absent, so query how much memory caller reserved */
1417  Addr,
1419  &MemoryInfo,
1420  sizeof(MemoryInfo),
1421  NULL);
1422 
1423  if (!NT_SUCCESS(Status))
1424  {
1425  DPRINT1("Querying amount of user supplied memory failed with status 0x%08X\n", Status);
1426  return NULL;
1427  }
1428 
1429  /* Validate it */
1430  if (MemoryInfo.BaseAddress != Addr ||
1431  MemoryInfo.State == MEM_FREE)
1432  {
1433  return NULL;
1434  }
1435 
1436  /* Validation checks passed, set committed/uncommitted addresses */
1437  CommittedAddress = Addr;
1438 
1439  /* Check if it's committed or not */
1440  if (MemoryInfo.State == MEM_COMMIT)
1441  {
1442  /* Zero it out because it's already committed */
1443  RtlZeroMemory(CommittedAddress, PAGE_SIZE);
1444 
1445  /* Calculate uncommitted address value */
1446  CommitSize = MemoryInfo.RegionSize;
1447  TotalSize = CommitSize;
1448  UncommittedAddress = (PCHAR)Addr + CommitSize;
1449 
1450  /* Check if uncommitted address is reserved */
1452  UncommittedAddress,
1454  &MemoryInfo,
1455  sizeof(MemoryInfo),
1456  NULL);
1457 
1458  if (NT_SUCCESS(Status) &&
1459  MemoryInfo.State == MEM_RESERVE)
1460  {
1461  /* It is, so add it up to the reserve size */
1462  TotalSize += MemoryInfo.RegionSize;
1463  }
1464  }
1465  else
1466  {
1467  /* It's not committed, inform following code that a commit is necessary */
1469  UncommittedAddress = Addr;
1470  }
1471  }
1472 
1473  /* Mark this as a user-committed mem */
1474  HeapSegmentFlags = HEAP_USER_ALLOCATED;
1475  Heap = (PHEAP)Addr;
1476  }
1477  else
1478  {
1479  /* Check commit routine */
1480  if (Parameters->CommitRoutine) return NULL;
1481 
1482  /* Reserve memory */
1483  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1484  (PVOID *)&Heap,
1485  0,
1486  &TotalSize,
1487  MEM_RESERVE,
1488  PAGE_READWRITE);
1489 
1490  if (!NT_SUCCESS(Status))
1491  {
1492  DPRINT1("Failed to reserve memory with status 0x%08x\n", Status);
1493  return NULL;
1494  }
1495 
1496  /* Set base addresses */
1497  CommittedAddress = Heap;
1498  UncommittedAddress = Heap;
1499  }
1500 
1501  /* Check if we need to commit something */
1502  if (CommittedAddress == UncommittedAddress)
1503  {
1504  /* Commit the required size */
1505  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1506  &CommittedAddress,
1507  0,
1508  &CommitSize,
1509  MEM_COMMIT,
1510  PAGE_READWRITE);
1511 
1512  DPRINT("Committed %Iu bytes at base %p\n", CommitSize, CommittedAddress);
1513 
1514  if (!NT_SUCCESS(Status))
1515  {
1516  DPRINT1("Failure, Status 0x%08X\n", Status);
1517 
1518  /* Release memory if it was reserved */
1519  if (!Addr) ZwFreeVirtualMemory(NtCurrentProcess(),
1520  (PVOID *)&Heap,
1521  &TotalSize,
1522  MEM_RELEASE);
1523 
1524  return NULL;
1525  }
1526 
1527  /* Calculate new uncommitted address */
1528  UncommittedAddress = (PCHAR)UncommittedAddress + CommitSize;
1529  }
1530 
1531  /* Initialize the heap */
1533  if (!NT_SUCCESS(Status))
1534  {
1535  DPRINT1("Failed to initialize heap (%x)\n", Status);
1536  return NULL;
1537  }
1538 
1539  /* Initialize heap's first segment */
1540  Status = RtlpInitializeHeapSegment(Heap, (PHEAP_SEGMENT) (Heap), 0, HeapSegmentFlags, TotalSize, CommitSize);
1541  if (!NT_SUCCESS(Status))
1542  {
1543  DPRINT1("Failed to initialize heap segment (%x)\n", Status);
1544  return NULL;
1545  }
1546 
1547  DPRINT("Created heap %p, CommitSize %x, ReserveSize %x\n", Heap, CommitSize, TotalSize);
1548 
1549  /* Add heap to process list in case of usermode heap */
1550  if (RtlpGetMode() == UserMode)
1551  {
1553 
1554  // FIXME: What about lookasides?
1555  }
1556 
1557  return Heap;
1558 }
#define FLG_HEAP_DISABLE_COALESCING
Definition: pstypes.h:80
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
#define FLG_HEAP_ENABLE_TAIL_CHECK
Definition: pstypes.h:60
LONG NTSTATUS
Definition: precomp.h:26
#define HEAP_DISABLE_COALESCE_ON_FREE
Definition: nt_native.h:1699
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
#define MEM_COMMIT
Definition: nt_native.h:1313
BOOLEAN RtlpPageHeapEnabled
Definition: heappage.c:106
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define HEAP_SKIP_VALIDATION_CHECKS
Definition: rtltypes.h:165
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
VOID NTAPI RtlpSetHeapParameters(IN PRTL_HEAP_PARAMETERS Parameters)
Definition: libsupp.c:174
#define MEM_RESERVE
Definition: nt_native.h:1314
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
VOID NTAPI RtlpAddHeapToProcessList(struct _HEAP *Heap)
Definition: libsupp.c:230
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define HEAP_VALIDATE_PARAMETERS_ENABLED
Definition: rtltypes.h:167
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define PCHAR
Definition: match.c:90
NTSYSAPI NTSTATUS NTAPI ZwQueryVirtualMemory(_In_ HANDLE ProcessHandle, _In_ PVOID Address, _In_ MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass, _Out_ PVOID VirtualMemoryInformation, _In_ SIZE_T Length, _Out_opt_ PSIZE_T ResultLength)
#define MEM_FREE
Definition: nt_native.h:1317
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define HEAP_VALIDATE_ALL_ENABLED
Definition: rtltypes.h:166
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:404
#define HEAP_CREATE_VALID_MASK
Definition: nt_native.h:1728
#define HEAP_GROWABLE
Definition: nt_native.h:1693
NTSTATUS NTAPI RtlpInitializeHeap(OUT PHEAP Heap, IN ULONG Flags, IN PHEAP_LOCK Lock OPTIONAL, IN PRTL_HEAP_PARAMETERS Parameters)
Definition: heap.c:87
Status
Definition: gdiplustypes.h:24
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:887
#define HEAP_USER_ALLOCATED
Definition: heap.h:56
#define FLG_HEAP_ENABLE_FREE_CHECK
Definition: pstypes.h:61
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock
Definition: CrNtStubs.h:75
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI RtlpInitializeHeapSegment(IN OUT PHEAP Heap, OUT PHEAP_SEGMENT Segment, IN UCHAR SegmentIndex, IN ULONG SegmentFlags, IN SIZE_T SegmentReserve, IN SIZE_T SegmentCommit)
Definition: heap.c:892
#define DPRINT1
Definition: precomp.h:8
#define FLG_HEAP_VALIDATE_ALL
Definition: pstypes.h:63
#define MEM_RELEASE
Definition: nt_native.h:1316
unsigned int ULONG
Definition: retypes.h:1
struct _HEAP * PHEAP
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define FLG_USER_STACK_TRACE_DB
Definition: pstypes.h:67
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define HEAP_CAPTURE_STACK_BACKTRACES
Definition: rtltypes.h:164
HANDLE NTAPI RtlDebugCreateHeap(ULONG Flags, PVOID Addr, SIZE_T TotalSize, SIZE_T CommitSize, PVOID Lock, PRTL_HEAP_PARAMETERS Parameters)
Definition: heapdbg.c:20
ULONG NTAPI RtlGetNtGlobalFlags(VOID)
Definition: libsupp.c:93
HANDLE NTAPI RtlpPageHeapCreate(ULONG Flags, PVOID Addr, SIZE_T TotalSize, SIZE_T CommitSize, PVOID Lock, PRTL_HEAP_PARAMETERS Parameters)
Definition: heappage.c:1472
Definition: heap.c:51
#define PAGE_READWRITE
Definition: nt_native.h:1304
FORCEINLINE BOOLEAN RtlpHeapIsSpecial(ULONG Flags)
Definition: heap.h:60
#define FLG_HEAP_VALIDATE_PARAMETERS
Definition: pstypes.h:62

◆ RtlCreateTagHeap()

ULONG NTAPI RtlCreateTagHeap ( IN HANDLE  HeapHandle,
IN ULONG  Flags,
IN PWSTR  TagName,
IN PWSTR  TagSubName 
)

Definition at line 3956 of file heap.c.

3960 {
3961  /* TODO */
3962  UNIMPLEMENTED;
3963  return 0;
3964 }
#define UNIMPLEMENTED
Definition: debug.h:115

Referenced by HeapCreateTagsW(), and SmpInit().

◆ RtlDestroyHeap()

HANDLE NTAPI RtlDestroyHeap ( HANDLE  HeapPtr)

Definition at line 1573 of file heap.c.

1574 {
1575  PHEAP Heap = (PHEAP)HeapPtr;
1576  PLIST_ENTRY Current;
1577  PHEAP_UCR_SEGMENT UcrSegment;
1578  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
1580  SIZE_T Size;
1581  LONG i;
1583 
1584  if (!HeapPtr) return NULL;
1585 
1586  /* Call page heap routine if required */
1587  if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS) return RtlpPageHeapDestroy(HeapPtr);
1588 
1589  /* Call special heap */
1590  if (RtlpHeapIsSpecial(Heap->Flags))
1591  {
1592  if (!RtlDebugDestroyHeap(Heap)) return HeapPtr;
1593  }
1594 
1595  /* Check for a process heap */
1596  if (RtlpGetMode() == UserMode &&
1597  HeapPtr == NtCurrentPeb()->ProcessHeap) return HeapPtr;
1598 
1599  /* Free up all big allocations */
1600  Current = Heap->VirtualAllocdBlocks.Flink;
1601  while (Current != &Heap->VirtualAllocdBlocks)
1602  {
1603  VirtualEntry = CONTAINING_RECORD(Current, HEAP_VIRTUAL_ALLOC_ENTRY, Entry);
1604  BaseAddress = (PVOID)VirtualEntry;
1605  Current = Current->Flink;
1606  Size = 0;
1607  ZwFreeVirtualMemory(NtCurrentProcess(),
1608  &BaseAddress,
1609  &Size,
1610  MEM_RELEASE);
1611  }
1612 
1613  /* Delete tags and remove heap from the process heaps list in user mode */
1614  if (RtlpGetMode() == UserMode)
1615  {
1616  // FIXME DestroyTags
1618  }
1619 
1620  /* Delete the heap lock */
1621  if (!(Heap->Flags & HEAP_NO_SERIALIZE))
1622  {
1623  /* Delete it if it wasn't user allocated */
1624  if (!(Heap->Flags & HEAP_LOCK_USER_ALLOCATED))
1626 
1627  /* Clear out the lock variable */
1628  Heap->LockVariable = NULL;
1629  }
1630 
1631  /* Free UCR segments if any were created */
1632  Current = Heap->UCRSegments.Flink;
1633  while (Current != &Heap->UCRSegments)
1634  {
1635  UcrSegment = CONTAINING_RECORD(Current, HEAP_UCR_SEGMENT, ListEntry);
1636 
1637  /* Advance to the next descriptor */
1638  Current = Current->Flink;
1639 
1640  BaseAddress = (PVOID)UcrSegment;
1641  Size = 0;
1642 
1643  /* Release that memory */
1644  ZwFreeVirtualMemory(NtCurrentProcess(),
1645  &BaseAddress,
1646  &Size,
1647  MEM_RELEASE);
1648  }
1649 
1650  /* Go through segments and destroy them */
1651  for (i = HEAP_SEGMENTS - 1; i >= 0; i--)
1652  {
1653  Segment = Heap->Segments[i];
1655  }
1656 
1657  return NULL;
1658 }
Definition: heap.h:312
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
#define HEAP_SEGMENTS
Definition: heap.h:16
static PVOID
Definition: heap.c:41
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:254
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
long LONG
Definition: pedump.c:60
PHEAP_LOCK LockVariable
Definition: heap.h:267
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI RtlpRemoveHeapFromProcessList(struct _HEAP *Heap)
Definition: libsupp.c:237
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PVOID NTAPI RtlpPageHeapDestroy(HANDLE HeapPtr)
Definition: heappage.c:1613
BOOLEAN NTAPI RtlDebugDestroyHeap(HANDLE HeapPtr)
Definition: heapdbg.c:95
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
LIST_ENTRY UCRSegments
Definition: heap.h:249
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:252
#define HEAP_LOCK_USER_ALLOCATED
Definition: rtltypes.h:168
Definition: typedefs.h:119
#define HEAP_FLAG_PAGE_ALLOCS
Definition: rtltypes.h:160
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
HANDLE ProcessHeap
Definition: servman.c:15
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define NtCurrentPeb()
Definition: FLS.c:20
ULONG Flags
Definition: heap.h:227
#define MEM_RELEASE
Definition: nt_native.h:1316
struct _HEAP * PHEAP
NTSTATUS NTAPI RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:101
ULONG ForceFlags
Definition: heap.h:228
VOID NTAPI RtlpDestroyHeapSegment(PHEAP_SEGMENT Segment)
Definition: heap.c:968
base of all file and directory entries
Definition: entries.h:82
Definition: heap.c:51
FORCEINLINE BOOLEAN RtlpHeapIsSpecial(ULONG Flags)
Definition: heap.h:60

◆ RtlEnumProcessHeaps()

NTSTATUS NTAPI RtlEnumProcessHeaps ( PHEAP_ENUMERATION_ROUTINE  HeapEnumerationRoutine,
PVOID  lParam 
)

Definition at line 3687 of file heap.c.

3689 {
3690  UNIMPLEMENTED;
3691  return STATUS_NOT_IMPLEMENTED;
3692 }
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define UNIMPLEMENTED
Definition: debug.h:115

◆ RtlExtendHeap()

ULONG NTAPI RtlExtendHeap ( IN HANDLE  Heap,
IN ULONG  Flags,
IN PVOID  P,
IN SIZE_T  Size 
)

Definition at line 3944 of file heap.c.

3948 {
3949  /* TODO */
3950  UNIMPLEMENTED;
3951  return 0;
3952 }
#define UNIMPLEMENTED
Definition: debug.h:115

◆ RtlFreeHeap()

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

Definition at line 2198 of file heap.c.

2203 {
2204  PHEAP Heap;
2205  PHEAP_ENTRY HeapEntry;
2206  USHORT TagIndex = 0;
2207  SIZE_T BlockSize;
2208  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
2209  BOOLEAN Locked = FALSE;
2210  NTSTATUS Status;
2211 
2212  /* Freeing NULL pointer is a legal operation */
2213  if (!Ptr) return TRUE;
2214 
2215  /* Get pointer to the heap and force flags */
2216  Heap = (PHEAP)HeapPtr;
2217  Flags |= Heap->ForceFlags;
2218 
2219  /* Call special heap */
2220  if (RtlpHeapIsSpecial(Flags))
2221  return RtlDebugFreeHeap(Heap, Flags, Ptr);
2222 
2223  /* Get pointer to the heap entry */
2224  HeapEntry = (PHEAP_ENTRY)Ptr - 1;
2225 
2226  /* Protect with SEH in case the pointer is not valid */
2227  _SEH2_TRY
2228  {
2229  /* Check this entry, fail if it's invalid */
2230  if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY) ||
2231  (((ULONG_PTR)Ptr & 0x7) != 0) ||
2232  (HeapEntry->SegmentOffset >= HEAP_SEGMENTS))
2233  {
2234  /* This is an invalid block */
2235  DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
2237  _SEH2_YIELD(return FALSE);
2238  }
2239  }
2241  {
2242  /* The pointer was invalid */
2243  DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
2245  _SEH2_YIELD(return FALSE);
2246  }
2247  _SEH2_END;
2248 
2249  /* Lock if necessary */
2250  if (!(Flags & HEAP_NO_SERIALIZE))
2251  {
2253  Locked = TRUE;
2254  }
2255 
2256  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
2257  {
2258  /* Big allocation */
2259  VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
2260 
2261  /* Remove it from the list */
2262  RemoveEntryList(&VirtualEntry->Entry);
2263 
2264  // TODO: Tagging
2265 
2266  BlockSize = 0;
2267  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
2268  (PVOID *)&VirtualEntry,
2269  &BlockSize,
2270  MEM_RELEASE);
2271 
2272  if (!NT_SUCCESS(Status))
2273  {
2274  DPRINT1("HEAP: Failed releasing memory with Status 0x%08X. Heap %p, ptr %p, base address %p\n",
2275  Status, Heap, Ptr, VirtualEntry);
2277  }
2278  }
2279  else
2280  {
2281  /* Normal allocation */
2282  BlockSize = HeapEntry->Size;
2283 
2284  // TODO: Tagging
2285 
2286  /* Coalesce in kernel mode, and in usermode if it's not disabled */
2287  if (RtlpGetMode() == KernelMode ||
2289  {
2290  HeapEntry = (PHEAP_ENTRY)RtlpCoalesceFreeBlocks(Heap,
2291  (PHEAP_FREE_ENTRY)HeapEntry,
2292  &BlockSize,
2293  FALSE);
2294  }
2295 
2296  /* If there is no need to decommit the block - put it into a free list */
2297  if (BlockSize < Heap->DeCommitFreeBlockThreshold ||
2298  (Heap->TotalFreeSize + BlockSize < Heap->DeCommitTotalFreeThreshold))
2299  {
2300  /* Check if it needs to go to a 0 list */
2301  if (BlockSize > HEAP_MAX_BLOCK_SIZE)
2302  {
2303  /* General-purpose 0 list */
2304  RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY)HeapEntry, BlockSize);
2305  }
2306  else
2307  {
2308  /* Usual free list */
2309  RtlpInsertFreeBlockHelper(Heap, (PHEAP_FREE_ENTRY)HeapEntry, BlockSize, FALSE);
2310 
2311  /* Assert sizes are consistent */
2312  if (!(HeapEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
2313  {
2314  ASSERT((HeapEntry + BlockSize)->PreviousSize == BlockSize);
2315  }
2316 
2317  /* Increase the free size */
2318  Heap->TotalFreeSize += BlockSize;
2319  }
2320 
2321 
2322  if (RtlpGetMode() == UserMode &&
2323  TagIndex != 0)
2324  {
2325  // FIXME: Tagging
2326  UNIMPLEMENTED;
2327  }
2328  }
2329  else
2330  {
2331  /* Decommit this block */
2332  RtlpDeCommitFreeBlock(Heap, (PHEAP_FREE_ENTRY)HeapEntry, BlockSize);
2333  }
2334  }
2335 
2336  /* Release the heap lock */
2337  if (Locked) RtlLeaveHeapLock(Heap->LockVariable);
2338 
2339  return TRUE;
2340 }
LIST_ENTRY Entry
Definition: heap.h:314
Definition: heap.h:312
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:44
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:251
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
SIZE_T TotalFreeSize
Definition: heap.h:240
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceFreeBlocks(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, PSIZE_T FreeSize, BOOLEAN Remove)
Definition: heap.c:1000
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
#define HEAP_SEGMENTS
Definition: heap.h:16
VOID NTAPI RtlpDeCommitFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T Size)
Definition: heap.c:746
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
LONG NTSTATUS
Definition: precomp.h:26
#define HEAP_DISABLE_COALESCE_ON_FREE
Definition: nt_native.h:1699
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:24
_SEH2_TRY
Definition: create.c:4226
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FALSE
Definition: types.h:117
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:260
PHEAP_LOCK LockVariable
Definition: heap.h:267
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:319
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
Definition: heap.h:130
unsigned char BOOLEAN
struct _HEAP_ENTRY * PHEAP_ENTRY
BOOLEAN NTAPI RtlDebugFreeHeap(HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
Definition: heapdbg.c:267
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS NTAPI RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:133
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_SEH2_END
Definition: create.c:4400
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
ULONG Flags
Definition: heap.h:227
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45
#define DPRINT1
Definition: precomp.h:8
#define MEM_RELEASE
Definition: nt_native.h:1316
struct _HEAP * PHEAP
#define UNIMPLEMENTED
Definition: debug.h:115
#define ULONG_PTR
Definition: config.h:101
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
ULONG ForceFlags
Definition: heap.h:228
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
Definition: heap.c:51
FORCEINLINE BOOLEAN RtlpHeapIsSpecial(ULONG Flags)
Definition: heap.h:60

◆ RtlGetProcessHeaps()

ULONG NTAPI RtlGetProcessHeaps ( ULONG  count,
HANDLE heaps 
)

Definition at line 3699 of file heap.c.

3701 {
3702  UNIMPLEMENTED;
3703  return 0;
3704 }
#define UNIMPLEMENTED
Definition: debug.h:115

Referenced by GetProcessHeaps().

◆ RtlGetUserInfoHeap()

BOOLEAN NTAPI RtlGetUserInfoHeap ( IN PVOID  HeapHandle,
IN ULONG  Flags,
IN PVOID  BaseAddress,
OUT PVOID UserValue,
OUT PULONG  UserFlags 
)

Definition at line 3853 of file heap.c.

3858 {
3859  PHEAP Heap = (PHEAP)HeapHandle;
3860  PHEAP_ENTRY HeapEntry;
3861  PHEAP_ENTRY_EXTRA Extra;
3862  BOOLEAN HeapLocked = FALSE;
3863 
3864  /* Force flags */
3865  Flags |= Heap->Flags;
3866 
3867  /* Call special heap */
3868  if (RtlpHeapIsSpecial(Flags))
3869  return RtlDebugGetUserInfoHeap(Heap, Flags, BaseAddress, UserValue, UserFlags);
3870 
3871  /* Lock if it's lockable */
3872  if (!(Heap->Flags & HEAP_NO_SERIALIZE))
3873  {
3875  HeapLocked = TRUE;
3876  }
3877 
3878  /* Get a pointer to the entry */
3879  HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
3880 
3881  /* If it's a free entry - return error */
3882  if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
3883  {
3885 
3886  /* Release the heap lock if it was acquired */
3887  if (HeapLocked)
3889 
3890  return FALSE;
3891  }
3892 
3893  /* Check if this entry has an extra stuff associated with it */
3894  if (HeapEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
3895  {
3896  /* Get pointer to extra data */
3897  Extra = RtlpGetExtraStuffPointer(HeapEntry);
3898 
3899  /* Pass user value */
3900  if (UserValue)
3901  *UserValue = (PVOID)Extra->Settable;
3902  }
3903 
3904  /* Decode and return user flags */
3905  if (UserFlags)
3906  *UserFlags = (HeapEntry->Flags & HEAP_ENTRY_SETTABLE_FLAGS) << 4;
3907 
3908  /* Release the heap lock if it was acquired */
3909  if (HeapLocked)
3911 
3912  return TRUE;
3913 }
ULONG_PTR Settable
Definition: heap.h:304
#define HEAP_ENTRY_SETTABLE_FLAGS
Definition: heap.h:49
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
static PVOID
Definition: heap.c:41
PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer(PHEAP_ENTRY HeapEntry)
Definition: heap.c:2587
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FALSE
Definition: types.h:117
Definition: heap.h:296
PHEAP_LOCK LockVariable
Definition: heap.h:267
unsigned char BOOLEAN
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
NTSTATUS NTAPI RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:133
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
BOOLEAN NTAPI RtlDebugGetUserInfoHeap(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID *UserValue, PULONG UserFlags)
Definition: heapdbg.c:322
Definition: heap.h:136
ULONG Flags
Definition: heap.h:227
struct _HEAP * PHEAP
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42
Definition: heap.c:51
FORCEINLINE BOOLEAN RtlpHeapIsSpecial(ULONG Flags)
Definition: heap.h:60

Referenced by GlobalFlags(), GlobalHandle(), GlobalReAlloc(), GlobalSize(), LocalFlags(), RtlDebugGetUserInfoHeap(), and START_TEST().

◆ RtlLockHeap()

BOOLEAN NTAPI RtlLockHeap ( IN HANDLE  HeapPtr)

Definition at line 3062 of file heap.c.

3063 {
3064  PHEAP Heap = (PHEAP)HeapPtr;
3065 
3066  /* Check for page heap */
3067  if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
3068  {
3069  return RtlpPageHeapLock(Heap);
3070  }
3071 
3072  /* Check if it's really a heap */
3073  if (Heap->Signature != HEAP_SIGNATURE) return FALSE;
3074 
3075  /* Lock if it's lockable */
3076  if (!(Heap->Flags & HEAP_NO_SERIALIZE))
3077  {
3079  }
3080 
3081  return TRUE;
3082 }
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#define TRUE
Definition: types.h:120
ULONG Signature
Definition: heap.h:235
BOOLEAN NTAPI RtlpPageHeapLock(HANDLE HeapPtr)
Definition: heappage.c:2354
#define FALSE
Definition: types.h:117
PHEAP_LOCK LockVariable
Definition: heap.h:267
#define HEAP_FLAG_PAGE_ALLOCS
Definition: rtltypes.h:160
ULONG Flags
Definition: heap.h:227
#define HEAP_SIGNATURE
Definition: heap.h:52
struct _HEAP * PHEAP
ULONG ForceFlags
Definition: heap.h:228
Definition: heap.c:51

◆ RtlMultipleAllocateHeap()

ULONG NTAPI RtlMultipleAllocateHeap ( IN PVOID  HeapHandle,
IN ULONG  Flags,
IN SIZE_T  Size,
IN ULONG  Count,
OUT PVOID Array 
)

Definition at line 4050 of file heap.c.

4055 {
4056  ULONG Index;
4057  EXCEPTION_RECORD ExceptionRecord;
4058 
4059  for (Index = 0; Index < Count; ++Index)
4060  {
4061  Array[Index] = RtlAllocateHeap(HeapHandle, Flags, Size);
4062  if (Array[Index] == NULL)
4063  {
4064  /* ERROR_NOT_ENOUGH_MEMORY */
4066 
4068  {
4069  ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY;
4070  ExceptionRecord.ExceptionRecord = NULL;
4071  ExceptionRecord.NumberParameters = 0;
4072  ExceptionRecord.ExceptionFlags = 0;
4073 
4074  RtlRaiseException(&ExceptionRecord);
4075  }
4076  break;
4077  }
4078  }
4079 
4080  return Index;
4081 }
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1223
NTSYSAPI VOID NTAPI RtlRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord)
DWORD ExceptionCode
Definition: compat.h:208
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
smooth NULL
Definition: ftsmooth.c:416
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
static const UCHAR Index[8]
Definition: usbohci.c:18
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
unsigned int ULONG
Definition: retypes.h:1
DWORD ExceptionFlags
Definition: compat.h:209
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
DWORD NumberParameters
Definition: compat.h:212
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694

◆ RtlMultipleFreeHeap()

ULONG NTAPI RtlMultipleFreeHeap ( IN PVOID  HeapHandle,
IN ULONG  Flags,
IN ULONG  Count,
OUT PVOID Array 
)

Definition at line 4086 of file heap.c.

4090 {
4091  ULONG Index;
4092 
4093  for (Index = 0; Index < Count; ++Index)
4094  {
4095  if (Array[Index] == NULL)
4096  continue;
4097 
4098  _SEH2_TRY
4099  {
4100  if (!RtlFreeHeap(HeapHandle, Flags, Array[Index]))
4101  {
4102  /* ERROR_INVALID_PARAMETER */
4104  break;
4105  }
4106  }
4108  {
4109  /* ERROR_INVALID_PARAMETER */
4111  break;
4112  }
4113  _SEH2_END;
4114  }
4115 
4116  return Index;
4117 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1223
_SEH2_TRY
Definition: create.c:4226
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
static const UCHAR Index[8]
Definition: usbohci.c:18
_SEH2_END
Definition: create.c:4400
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6

◆ RtlpAllocateNonDedicated()

PVOID NTAPI RtlpAllocateNonDedicated ( PHEAP  Heap,
ULONG  Flags,
SIZE_T  Size,
SIZE_T  AllocationSize,
SIZE_T  Index,
BOOLEAN  HeapLocked 
)

Definition at line 1801 of file heap.c.

1807 {
1808  PLIST_ENTRY FreeListHead, Next;
1809  PHEAP_FREE_ENTRY FreeBlock;
1810  PHEAP_ENTRY InUseEntry;
1811  PHEAP_ENTRY_EXTRA Extra;
1812  EXCEPTION_RECORD ExceptionRecord;
1813 
1814  /* Go through the zero list to find a place where to insert the new entry */
1815  FreeListHead = &Heap->FreeLists[0];
1816 
1817  /* Start from the largest block to reduce time */
1818  Next = FreeListHead->Blink;
1819  if (FreeListHead != Next)
1820  {
1821  FreeBlock = CONTAINING_RECORD(Next, HEAP_FREE_ENTRY, FreeList);
1822 
1823  if (FreeBlock->Size >= Index)
1824  {
1825  /* Our request is smaller than the largest entry in the zero list */
1826 
1827  /* Go through the list to find insertion place */
1828  Next = FreeListHead->Flink;
1829  while (FreeListHead != Next)
1830  {
1831  FreeBlock = CONTAINING_RECORD(Next, HEAP_FREE_ENTRY, FreeList);
1832 
1833  if (FreeBlock->Size >= Index)
1834  {
1835  /* Found minimally fitting entry. Proceed to either using it as it is
1836  or splitting it to two entries */
1837  RemoveEntryList(&FreeBlock->FreeList);
1838 
1839  /* Split it */
1840  InUseEntry = RtlpSplitEntry(Heap, Flags, FreeBlock, AllocationSize, Index, Size);
1841 
1842  /* Release the lock */
1843  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
1844 
1845  /* Zero memory if that was requested */
1846  if (Flags & HEAP_ZERO_MEMORY)
1847  RtlZeroMemory(InUseEntry + 1, Size);
1848  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
1849  {
1850  /* Fill this block with a special pattern */
1851  RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
1852  }
1853 
1854  /* Fill tail of the block with a special pattern too if requested */
1855  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
1856  {
1857  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY), HEAP_TAIL_FILL);
1858  InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
1859  }
1860 
1861  /* Prepare extra if it's present */
1862  if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
1863  {
1864  Extra = RtlpGetExtraStuffPointer(InUseEntry);
1865  RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
1866 
1867  // TODO: Tagging
1868  }
1869 
1870  /* Return pointer to the */
1871  return InUseEntry + 1;
1872  }
1873 
1874  /* Advance to the next entry */
1875  Next = Next->Flink;
1876  }
1877  }
1878  }
1879 
1880  /* Extend the heap, 0 list didn't have anything suitable */
1881  FreeBlock = RtlpExtendHeap(Heap, AllocationSize);
1882 
1883  /* Use the new biggest entry we've got */
1884  if (FreeBlock)
1885  {
1886  RemoveEntryList(&FreeBlock->FreeList);
1887 
1888  /* Split it */
1889  InUseEntry = RtlpSplitEntry(Heap, Flags, FreeBlock, AllocationSize, Index, Size);
1890 
1891  /* Release the lock */
1892  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
1893 
1894  /* Zero memory if that was requested */
1895  if (Flags & HEAP_ZERO_MEMORY)
1896  RtlZeroMemory(InUseEntry + 1, Size);
1897  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
1898  {
1899  /* Fill this block with a special pattern */
1900  RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
1901  }
1902 
1903  /* Fill tail of the block with a special pattern too if requested */
1904  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
1905  {
1906  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY), HEAP_TAIL_FILL);
1907  InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
1908  }
1909 
1910  /* Prepare extra if it's present */
1911  if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
1912  {
1913  Extra = RtlpGetExtraStuffPointer(InUseEntry);
1914  RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
1915 
1916  // TODO: Tagging
1917  }
1918 
1919  /* Return pointer to the */
1920  return InUseEntry + 1;
1921  }
1922 
1923  /* Really unfortunate, out of memory condition */
1925 
1926  /* Generate an exception */
1928  {
1929  ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY;
1930  ExceptionRecord.ExceptionRecord = NULL;
1931  ExceptionRecord.NumberParameters = 1;
1932  ExceptionRecord.ExceptionFlags = 0;
1933  ExceptionRecord.ExceptionInformation[0] = AllocationSize;
1934 
1935  RtlRaiseException(&ExceptionRecord);
1936  }
1937 
1938  /* Release the lock */
1939  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
1940  DPRINT1("HEAP: Allocation failed!\n");
1941  DPRINT1("Flags %x\n", Heap->Flags);
1942  return NULL;
1943 }
signed char * PCHAR
Definition: retypes.h:7
#define ARENA_INUSE_FILLER
Definition: oleaut.c:105
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
LIST_ENTRY FreeList
Definition: heap.h:132
NTSYSAPI VOID NTAPI RtlRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord)
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer(PHEAP_ENTRY HeapEntry)
Definition: heap.c:2587
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
DWORD ExceptionCode
Definition: compat.h:208
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
Definition: heap.h:296
PHEAP_LOCK LockVariable
Definition: heap.h:267
Definition: heap.h:130
smooth NULL
Definition: ftsmooth.c:416
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS NTAPI RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:133
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
static const UCHAR Index[8]
Definition: usbohci.c:18
MmuFreePage * FreeList
Definition: mmuobject.c:60
PHEAP_ENTRY NTAPI RtlpSplitEntry(PHEAP Heap, ULONG Flags, PHEAP_FREE_ENTRY FreeBlock, SIZE_T AllocationSize, SIZE_T Index, SIZE_T Size)
Definition: heap.c:1661
Definition: typedefs.h:119
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:319
Definition: heap.h:136
ULONG Flags
Definition: heap.h:227
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define DPRINT1
Definition: precomp.h:8
#define HEAP_TAIL_FILL
Definition: heap.h:28
PHEAP_FREE_ENTRY NTAPI RtlpExtendHeap(PHEAP Heap, SIZE_T Size)
Definition: heap.c:1098
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
DWORD ExceptionFlags
Definition: compat.h:209
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42
DWORD NumberParameters
Definition: compat.h:212
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
LIST_ENTRY FreeLists[HEAP_FREELISTS]
Definition: heap.h:260

Referenced by RtlAllocateHeap().

◆ RtlpCheckInUsePattern()

BOOLEAN NTAPI RtlpCheckInUsePattern ( PHEAP_ENTRY  HeapEntry)

Definition at line 3186 of file heap.c.

3187 {
3188  SIZE_T Size, Result;
3189  PCHAR TailPart;
3190 
3191  /* Calculate size */
3192  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
3193  Size = RtlpGetSizeOfBigBlock(HeapEntry);
3194  else
3195  Size = (HeapEntry->Size << HEAP_ENTRY_SHIFT) - HeapEntry->UnusedBytes;
3196 
3197  /* Calculate pointer to the tail part of the block */
3198  TailPart = (PCHAR)(HeapEntry + 1) + Size;
3199 
3200  /* Compare tail pattern */
3201  Result = RtlCompareMemory(TailPart,
3202  FillPattern,
3203  HEAP_ENTRY_SIZE);
3204 
3205  if (Result != HEAP_ENTRY_SIZE)
3206  {
3207  DPRINT1("HEAP: Heap entry (size %x) %p tail is modified at %p\n", Size, HeapEntry, TailPart + Result);
3208  return FALSE;
3209  }
3210 
3211  /* All is fine */
3212  return TRUE;
3213 }
SIZE_T NTAPI RtlpGetSizeOfBigBlock(PHEAP_ENTRY HeapEntry)
Definition: heap.c:425
signed char * PCHAR
Definition: retypes.h:7
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:44
#define TRUE
Definition: types.h:120
UCHAR FillPattern[HEAP_ENTRY_SIZE]
Definition: heap.c:72
#define FALSE
Definition: types.h:117
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
#define HEAP_ENTRY_SIZE
Definition: heap.h:18
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define DPRINT1
Definition: precomp.h:8
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465

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

◆ RtlpClearFreeListsBit()

FORCEINLINE VOID RtlpClearFreeListsBit ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry 
)

Definition at line 231 of file heap.c.

233 {
234  ULONG Index, Bit;
235 
236  ASSERT(FreeEntry->Size < HEAP_FREELISTS);
237 
238  /* Calculate offset in the free list bitmap */
239  Index = FreeEntry->Size >> 3; /* = FreeEntry->Size / (sizeof(UCHAR) * 8)*/
240  Bit = 1 << (FreeEntry->Size & 7);
241 
242  /* Assure it was set and the corresponding free list is empty */
243  ASSERT(Heap->u.FreeListsInUseBytes[Index] & Bit);
244  ASSERT(IsListEmpty(&Heap->FreeLists[FreeEntry->Size]));
245 
246  /* Clear it */
247  Heap->u.FreeListsInUseBytes[Index] ^= Bit;
248 }
UCHAR FreeListsInUseBytes[HEAP_FREELISTS/(sizeof(UCHAR) *8)]
Definition: heap.h:265
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static const UCHAR Index[8]
Definition: usbohci.c:18
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define HEAP_FREELISTS
Definition: heap.h:15
union _HEAP::@4128 u
unsigned int ULONG
Definition: retypes.h:1
LIST_ENTRY FreeLists[HEAP_FREELISTS]
Definition: heap.h:260

Referenced by RtlpRemoveFreeBlock().

◆ RtlpCoalesceFreeBlocks()

PHEAP_FREE_ENTRY NTAPI RtlpCoalesceFreeBlocks ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry,
PSIZE_T  FreeSize,
BOOLEAN  Remove 
)

Definition at line 1000 of file heap.c.

1004 {
1005  PHEAP_FREE_ENTRY CurrentEntry, NextEntry;
1006  UCHAR SegmentOffset;
1007 
1008  /* Get the previous entry */
1009  CurrentEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry - FreeEntry->PreviousSize);
1010 
1011  /* Check it */
1012  if (CurrentEntry != FreeEntry &&
1013  !(CurrentEntry->Flags & HEAP_ENTRY_BUSY) &&
1014  (*FreeSize + CurrentEntry->Size) <= HEAP_MAX_BLOCK_SIZE)
1015  {
1016  ASSERT(FreeEntry->PreviousSize == CurrentEntry->Size);
1017 
1018  /* Remove it if asked for */
1019  if (Remove)
1020  {
1021  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE, FALSE);
1022  Heap->TotalFreeSize -= FreeEntry->Size;
1023 
1024  /* Remove it only once! */
1025  Remove = FALSE;
1026  }
1027 
1028  /* Remove previous entry too */
1029  RtlpRemoveFreeBlock(Heap, CurrentEntry, FALSE, FALSE);
1030 
1031  /* Copy flags */
1032  CurrentEntry->Flags = FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY;
1033 
1034  /* Advance FreeEntry and update sizes */
1035  FreeEntry = CurrentEntry;
1036  *FreeSize = *FreeSize + CurrentEntry->Size;
1037  Heap->TotalFreeSize -= CurrentEntry->Size;
1038  FreeEntry->Size = (USHORT)(*FreeSize);
1039 
1040  /* Also update previous size if needed */
1041  if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1042  {
1043  ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
1044  }
1045  else
1046  {
1047  SegmentOffset = FreeEntry->SegmentOffset;
1048  ASSERT(SegmentOffset < HEAP_SEGMENTS);
1049  Heap->Segments[SegmentOffset]->LastEntryInSegment = FreeEntry;
1050  }
1051  }
1052 
1053  /* Check the next block if it exists */
1054  if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1055  {
1056  NextEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + *FreeSize);
1057 
1058  if (!(NextEntry->Flags & HEAP_ENTRY_BUSY) &&
1059  NextEntry->Size + *FreeSize <= HEAP_MAX_BLOCK_SIZE)
1060  {
1061  ASSERT(*FreeSize == NextEntry->PreviousSize);
1062 
1063  /* Remove it if asked for */
1064  if (Remove)
1065  {
1066  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE, FALSE);
1067  Heap->TotalFreeSize -= FreeEntry->Size;
1068  }
1069 
1070  /* Copy flags */
1071  FreeEntry->Flags = NextEntry->Flags & HEAP_ENTRY_LAST_ENTRY;
1072 
1073  /* Remove next entry now */
1074  RtlpRemoveFreeBlock(Heap, NextEntry, FALSE, FALSE);
1075 
1076  /* Update sizes */
1077  *FreeSize = *FreeSize + NextEntry->Size;
1078  Heap->TotalFreeSize -= NextEntry->Size;
1079  FreeEntry->Size = (USHORT)(*FreeSize);
1080 
1081  /* Also update previous size if needed */
1082  if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1083  {
1084  ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
1085  }
1086  else
1087  {
1088  SegmentOffset = FreeEntry->SegmentOffset;
1089  ASSERT(SegmentOffset < HEAP_SEGMENTS);
1090  Heap->Segments[SegmentOffset]->LastEntryInSegment = FreeEntry;
1091  }
1092  }
1093  }
1094  return FreeEntry;
1095 }
SIZE_T TotalFreeSize
Definition: heap.h:240
#define HEAP_SEGMENTS
Definition: heap.h:16
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:24
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:254
#define FALSE
Definition: types.h:117
Definition: heap.h:130
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
_In_ BOOLEAN Remove
Definition: psfuncs.h:110
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID NTAPI RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN Dedicated, BOOLEAN NoFill)
Definition: heap.c:383
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45

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

◆ RtlpCoalesceHeap()

PHEAP_FREE_ENTRY NTAPI RtlpCoalesceHeap ( PHEAP  Heap)

Definition at line 993 of file heap.c.

994 {
996  return NULL;
997 }
smooth NULL
Definition: ftsmooth.c:416
#define UNIMPLEMENTED
Definition: debug.h:115

Referenced by RtlpExtendHeap().

◆ RtlpCreateUnCommittedRange()

PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange ( PHEAP_SEGMENT  Segment)

Definition at line 438 of file heap.c.

439 {
441  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
442  PHEAP_UCR_SEGMENT UcrSegment;
443  PHEAP Heap = Segment->Heap;
447 
448  DPRINT("RtlpCreateUnCommittedRange(%p)\n", Segment);
449 
450  /* Check if we have unused UCRs */
451  if (IsListEmpty(&Heap->UCRList))
452  {
453  /* Get a pointer to the first UCR segment */
454  UcrSegment = CONTAINING_RECORD(Heap->UCRSegments.Flink, HEAP_UCR_SEGMENT, ListEntry);
455 
456  /* Check the list of UCR segments */
457  if (IsListEmpty(&Heap->UCRSegments) ||
458  UcrSegment->ReservedSize == UcrSegment->CommittedSize)
459  {
460  /* We need to create a new one. Reserve 16 pages for it */
461  UcrSegment = NULL;
462  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
463  (PVOID *)&UcrSegment,
464  0,
465  &ReserveSize,
466  MEM_RESERVE,
468 
469  if (!NT_SUCCESS(Status)) return NULL;
470 
471  /* Commit one page */
472  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
473  (PVOID *)&UcrSegment,
474  0,
475  &CommitSize,
476  MEM_COMMIT,
478 
479  if (!NT_SUCCESS(Status))
480  {
481  /* Release reserved memory */
482  ZwFreeVirtualMemory(NtCurrentProcess(),
483  (PVOID *)&UcrSegment,
484  &ReserveSize,
485  MEM_RELEASE);
486  return NULL;
487  }
488 
489  /* Set it's data */
490  UcrSegment->ReservedSize = ReserveSize;
491  UcrSegment->CommittedSize = CommitSize;
492 
493  /* Add it to the head of the list */
494  InsertHeadList(&Heap->UCRSegments, &UcrSegment->ListEntry);
495 
496  /* Get a pointer to the first available UCR descriptor */
497  UcrDescriptor = (PHEAP_UCR_DESCRIPTOR)(UcrSegment + 1);
498  }
499  else
500  {
501  /* It's possible to use existing UCR segment. Commit one more page */
502  UcrDescriptor = (PHEAP_UCR_DESCRIPTOR)((PCHAR)UcrSegment + UcrSegment->CommittedSize);
503  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
504  (PVOID *)&UcrDescriptor,
505  0,
506  &CommitSize,
507  MEM_COMMIT,
509 
510  if (!NT_SUCCESS(Status)) return NULL;
511 
512  /* Update sizes */
513  UcrSegment->CommittedSize += CommitSize;
514  }
515 
516  /* There is a whole bunch of new UCR descriptors. Put them into the unused list */
517  while ((PCHAR)(UcrDescriptor + 1) <= (PCHAR)UcrSegment + UcrSegment->CommittedSize)
518  {
519  InsertTailList(&Heap->UCRList, &UcrDescriptor->ListEntry);
520  UcrDescriptor++;
521  }
522  }
523 
524  /* There are unused UCRs, just get the first one */
525  Entry = RemoveHeadList(&Heap->UCRList);
526  UcrDescriptor = CONTAINING_RECORD(Entry, HEAP_UCR_DESCRIPTOR, ListEntry);
527  return UcrDescriptor;
528 }
signed char * PCHAR
Definition: retypes.h:7
struct _Entry Entry
Definition: kefuncs.h:627
struct _HEAP_UCR_DESCRIPTOR * PHEAP_UCR_DESCRIPTOR
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LONG NTSTATUS
Definition: precomp.h:26
#define InsertTailList(ListHead, Entry)
#define MEM_COMMIT
Definition: nt_native.h:1313
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
SIZE_T ReservedSize
Definition: heap.h:292
#define MEM_RESERVE
Definition: nt_native.h:1314
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
void DPRINT(...)
Definition: polytest.cpp:61
SIZE_T CommittedSize
Definition: heap.h:293
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY UCRSegments
Definition: heap.h:249
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:404
Status
Definition: gdiplustypes.h:24
LIST_ENTRY UCRList
Definition: heap.h:248
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
LIST_ENTRY ListEntry
Definition: heap.h:283
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_In_opt_ PVOID _In_opt_ SIZE_T ReserveSize
Definition: rtlfuncs.h:2169
#define MEM_RELEASE
Definition: nt_native.h:1316
LIST_ENTRY ListEntry
Definition: heap.h:291
base of all file and directory entries
Definition: entries.h:82
Definition: heap.c:51
#define PAGE_READWRITE
Definition: nt_native.h:1304

Referenced by RtlpDeCommitFreeBlock(), and RtlpInsertUnCommittedPages().

◆ RtlpDeCommitFreeBlock()

VOID NTAPI RtlpDeCommitFreeBlock ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry,
SIZE_T  Size 
)

Definition at line 746 of file heap.c.

749 {
751  PHEAP_ENTRY PrecedingInUseEntry = NULL, NextInUseEntry = NULL;
752  PHEAP_FREE_ENTRY NextFreeEntry;
753  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
754  SIZE_T PrecedingSize, NextSize, DecommitSize;
755  ULONG_PTR DecommitBase;
757 
758  DPRINT("Decommitting %p %p %x\n", Heap, FreeEntry, Size);
759 
760  /* We can't decommit if there is a commit routine! */
761  if (Heap->CommitRoutine)
762  {
763  /* Just add it back the usual way */
764  RtlpInsertFreeBlock(Heap, FreeEntry, Size);
765  return;
766  }
767 
768  /* Get the segment */
769  Segment = Heap->Segments[FreeEntry->SegmentOffset];
770 
771  /* Get the preceding entry */
772  DecommitBase = ROUND_UP(FreeEntry, PAGE_SIZE);
773  PrecedingSize = (PHEAP_ENTRY)DecommitBase - (PHEAP_ENTRY)FreeEntry;
774 
775  if (PrecedingSize == 1)
776  {
777  /* Just 1 heap entry, increase the base/size */
778  DecommitBase += PAGE_SIZE;
779  PrecedingSize += PAGE_SIZE >> HEAP_ENTRY_SHIFT;
780  }
781  else if (FreeEntry->PreviousSize &&
782  (DecommitBase == (ULONG_PTR)FreeEntry))
783  {
784  PrecedingInUseEntry = (PHEAP_ENTRY)FreeEntry - FreeEntry->PreviousSize;
785  }
786 
787  /* Get the next entry */
788  NextFreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + Size);
789  DecommitSize = ROUND_DOWN(NextFreeEntry, PAGE_SIZE);
790  NextSize = (PHEAP_ENTRY)NextFreeEntry - (PHEAP_ENTRY)DecommitSize;
791 
792  if (NextSize == 1)
793  {
794  /* Just 1 heap entry, increase the size */
795  DecommitSize -= PAGE_SIZE;
796  NextSize += PAGE_SIZE >> HEAP_ENTRY_SHIFT;
797  }
798  else if (NextSize == 0 &&
799  !(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
800  {
801  NextInUseEntry = (PHEAP_ENTRY)NextFreeEntry;
802  }
803 
804  NextFreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)NextFreeEntry - NextSize);
805 
806  /* Calculate real decommit size */
807  if (DecommitSize > DecommitBase)
808  {
809  DecommitSize -= DecommitBase;
810  }
811  else
812  {
813  /* Nothing to decommit */
814  RtlpInsertFreeBlock(Heap, FreeEntry, Size);
815  return;
816  }
817 
818  /* A decommit is necessary. Create a UCR descriptor */
819  UcrDescriptor = RtlpCreateUnCommittedRange(Segment);
820  if (!UcrDescriptor)
821  {
822  DPRINT1("HEAP: Failed to create UCR descriptor\n");
823  RtlpInsertFreeBlock(Heap, FreeEntry, PrecedingSize);
824  return;
825  }
826 
827  /* Decommit the memory */
828  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
829  (PVOID *)&DecommitBase,
830  &DecommitSize,
831  MEM_DECOMMIT);
832 
833  /* Delete that UCR. This is needed to assure there is an unused UCR entry in the list */
834  RtlpDestroyUnCommittedRange(Segment, UcrDescriptor);
835 
836  if (!NT_SUCCESS(Status))
837  {
838  RtlpInsertFreeBlock(Heap, FreeEntry, Size);
839  return;
840  }
841 
842  /* Insert uncommitted pages */
843  RtlpInsertUnCommittedPages(Segment, DecommitBase, DecommitSize);
844  Segment->NumberOfUnCommittedPages += (ULONG)(DecommitSize / PAGE_SIZE);
845 
846  if (PrecedingSize)
847  {
848  /* Adjust size of this free entry and insert it */
849  FreeEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
850  FreeEntry->Size = (USHORT)PrecedingSize;
851  Heap->TotalFreeSize += PrecedingSize;
852  Segment->LastEntryInSegment = FreeEntry;
853 
854  /* Insert it into the free list */
855  RtlpInsertFreeBlockHelper(Heap, FreeEntry, PrecedingSize, FALSE);
856  }
857  else if (PrecedingInUseEntry)
858  {
859  /* Adjust preceding in use entry */
860  PrecedingInUseEntry->Flags |= HEAP_ENTRY_LAST_ENTRY;
861  Segment->LastEntryInSegment = PrecedingInUseEntry;
862  }
863  else if ((ULONG_PTR)Segment->LastEntryInSegment >= DecommitBase &&
864  (ULONG_PTR)Segment->LastEntryInSegment < DecommitBase + DecommitSize)
865  {
866  /* Invalidate last entry */
867  Segment->LastEntryInSegment = Segment->FirstEntry;
868  }
869 
870  /* Now the next one */
871  if (NextSize)
872  {
873  /* Adjust size of this free entry and insert it */
874  NextFreeEntry->Flags = 0;
875  NextFreeEntry->PreviousSize = 0;
876  NextFreeEntry->SegmentOffset = Segment->Entry.SegmentOffset;
877  NextFreeEntry->Size = (USHORT)NextSize;
878 
879  ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)NextFreeEntry + NextSize))->PreviousSize = (USHORT)NextSize;
880 
881  Heap->TotalFreeSize += NextSize;
882  RtlpInsertFreeBlockHelper(Heap, NextFreeEntry, NextSize, FALSE);
883  }
884  else if (NextInUseEntry)
885  {
886  NextInUseEntry->PreviousSize = 0;
887  }
888 }
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine
Definition: heap.h:268
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:251
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
SIZE_T TotalFreeSize
Definition: heap.h:240
LONG NTSTATUS
Definition: precomp.h:26
uint32_t ULONG_PTR
Definition: typedefs.h:65
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:254
#define MEM_DECOMMIT
Definition: nt_native.h:1315
#define FALSE
Definition: types.h:117
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:319
Definition: heap.h:130
struct _HEAP_ENTRY * PHEAP_ENTRY
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI RtlpDestroyUnCommittedRange(PHEAP_SEGMENT Segment, PHEAP_UCR_DESCRIPTOR UcrDescriptor)
Definition: heap.c:531
Status
Definition: gdiplustypes.h:24
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange(PHEAP_SEGMENT Segment)
Definition: heap.c:438
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
ULONG_PTR SIZE_T
Definition: typedefs.h:80
VOID NTAPI RtlpInsertUnCommittedPages(PHEAP_SEGMENT Segment, ULONG_PTR Address, SIZE_T Size)
Definition: heap.c:543
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45
#define DPRINT1
Definition: precomp.h:8

Referenced by RtlFreeHeap().

◆ RtlpDestroyHeapSegment()

VOID NTAPI RtlpDestroyHeapSegment ( PHEAP_SEGMENT  Segment)

Definition at line 968 of file heap.c.

969 {
972  SIZE_T Size = 0;
973 
974  /* Make sure it's not user allocated */
975  if (Segment->SegmentFlags & HEAP_USER_ALLOCATED) return;
976 
977  BaseAddress = Segment->BaseAddress;
978  DPRINT("Destroying segment %p, BA %p\n", Segment, BaseAddress);
979 
980  /* Release virtual memory */
981  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
982  &BaseAddress,
983  &Size,
984  MEM_RELEASE);
985 
986  if (!NT_SUCCESS(Status))
987  {
988  DPRINT1("HEAP: Failed to release segment's memory with status 0x%08X\n", Status);
989  }
990 }
LONG NTSTATUS
Definition: precomp.h:26
void DPRINT(...)
Definition: polytest.cpp:61
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:24
#define HEAP_USER_ALLOCATED
Definition: heap.h:56
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define DPRINT1
Definition: precomp.h:8
#define MEM_RELEASE
Definition: nt_native.h:1316

Referenced by RtlDestroyHeap().

◆ RtlpDestroyUnCommittedRange()

VOID NTAPI RtlpDestroyUnCommittedRange ( PHEAP_SEGMENT  Segment,
PHEAP_UCR_DESCRIPTOR  UcrDescriptor 
)

Definition at line 531 of file heap.c.

533 {
534  /* Zero it out */
535  UcrDescriptor->Address = NULL;
536  UcrDescriptor->Size = 0;
537 
538  /* Put it into the heap's list of unused UCRs */
539  InsertHeadList(&Segment->Heap->UCRList, &UcrDescriptor->ListEntry);
540 }
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
smooth NULL
Definition: ftsmooth.c:416
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
LIST_ENTRY ListEntry
Definition: heap.h:283

Referenced by RtlpDeCommitFreeBlock(), RtlpFindAndCommitPages(), and RtlpInsertUnCommittedPages().

◆ RtlpExtendHeap()

PHEAP_FREE_ENTRY NTAPI RtlpExtendHeap ( PHEAP  Heap,
SIZE_T  Size 
)

Definition at line 1098 of file heap.c.

1100 {
1101  ULONG Pages;
1102  UCHAR Index, EmptyIndex;
1103  SIZE_T FreeSize, CommitSize, ReserveSize;
1105  PHEAP_FREE_ENTRY FreeEntry;
1106  NTSTATUS Status;
1107 
1108  DPRINT("RtlpExtendHeap(%p %x)\n", Heap, Size);
1109 
1110  /* Calculate amount in pages */
1111  Pages = (ULONG)((Size + PAGE_SIZE - 1) / PAGE_SIZE);
1112  FreeSize = Pages * PAGE_SIZE;
1113  DPRINT("Pages %x, FreeSize %x. Going through segments...\n", Pages, FreeSize);
1114 
1115  /* Find an empty segment */
1116  EmptyIndex = HEAP_SEGMENTS;
1117  for (Index = 0; Index < HEAP_SEGMENTS; Index++)
1118  {
1119  Segment = Heap->Segments[Index];
1120 
1121  if (Segment) DPRINT("Segment[%u] %p with NOUCP %x\n", Index, Segment, Segment->NumberOfUnCommittedPages);
1122 
1123  /* Check if its size suits us */
1124  if (Segment &&
1125  Pages <= Segment->NumberOfUnCommittedPages)
1126  {
1127  DPRINT("This segment is suitable\n");
1128 
1129  /* Commit needed amount */
1130  FreeEntry = RtlpFindAndCommitPages(Heap, Segment, &FreeSize, NULL);
1131 
1132  /* Coalesce it with adjacent entries */
1133  if (FreeEntry)
1134  {
1135  FreeSize = FreeSize >> HEAP_ENTRY_SHIFT;
1136  FreeEntry = RtlpCoalesceFreeBlocks(Heap, FreeEntry, &FreeSize, FALSE);
1137  RtlpInsertFreeBlock(Heap, FreeEntry, FreeSize);
1138  return FreeEntry;
1139  }
1140  }
1141  else if (!Segment &&
1142  EmptyIndex == HEAP_SEGMENTS)
1143  {
1144  /* Remember the first unused segment index */
1145  EmptyIndex = Index;
1146  }
1147  }
1148 
1149  /* No luck, need to grow the heap */
1150  if ((Heap->Flags & HEAP_GROWABLE) &&
1151  (EmptyIndex != HEAP_SEGMENTS))
1152  {
1153  Segment = NULL;
1154 
1155  /* Reserve the memory */
1156  if ((Size + PAGE_SIZE) <= Heap->SegmentReserve)
1157  ReserveSize = Heap->SegmentReserve;
1158  else
1160 
1161  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1162  (PVOID)&Segment,
1163  0,
1164  &ReserveSize,
1165  MEM_RESERVE,
1166  PAGE_READWRITE);
1167 
1168  /* If it failed, retry again with a half division algorithm */
1169  while (!NT_SUCCESS(Status) &&
1170  ReserveSize != Size + PAGE_SIZE)
1171  {
1172  ReserveSize /= 2;
1173 
1174  if (ReserveSize < (Size + PAGE_SIZE))
1176 
1177  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1178  (PVOID)&Segment,
1179  0,
1180  &ReserveSize,
1181  MEM_RESERVE,
1182  PAGE_READWRITE);
1183  }
1184 
1185  /* Proceed only if it's success */
1186  if (NT_SUCCESS(Status))
1187  {
1188  Heap->SegmentReserve += ReserveSize;
1189 
1190  /* Now commit the memory */
1191  if ((Size + PAGE_SIZE) <= Heap->SegmentCommit)
1192  CommitSize = Heap->SegmentCommit;
1193  else
1195 
1196  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1197  (PVOID)&Segment,
1198  0,
1199  &CommitSize,
1200  MEM_COMMIT,
1201  PAGE_READWRITE);
1202 
1203  DPRINT("Committed %lu bytes at base %p\n", CommitSize, Segment);
1204 
1205  /* Initialize heap segment if commit was successful */
1206  if (NT_SUCCESS(Status))
1208 
1209  /* If everything worked - cool */
1210  if (NT_SUCCESS(Status)) return (PHEAP_FREE_ENTRY)Segment->FirstEntry;
1211 
1212  DPRINT1("Committing failed with status 0x%08X\n", Status);
1213 
1214  /* Nope, we failed. Free memory */
1215  ZwFreeVirtualMemory(NtCurrentProcess(),
1216  (PVOID)&Segment,
1217  &ReserveSize,
1218  MEM_RELEASE);
1219  }
1220  else
1221  {
1222  DPRINT1("Reserving failed with status 0x%08X\n", Status);
1223  }
1224  }
1225 
1226  if (RtlpGetMode() == UserMode)
1227  {
1228  /* If coalescing on free is disabled in usermode, then do it here */
1230  {
1231  FreeEntry = RtlpCoalesceHeap(Heap);
1232 
1233  /* If it's a suitable one - return it */
1234  if (FreeEntry &&
1235  FreeEntry->Size >= Size)
1236  {
1237  return FreeEntry;
1238  }
1239  }
1240  }
1241 
1242  return NULL;
1243 }
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceFreeBlocks(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, PSIZE_T FreeSize, BOOLEAN Remove)
Definition: heap.c:1000
#define HEAP_SEGMENTS
Definition: heap.h:16
LONG NTSTATUS
Definition: precomp.h:26
#define HEAP_DISABLE_COALESCE_ON_FREE
Definition: nt_native.h:1699
#define MEM_COMMIT
Definition: nt_native.h:1313
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceHeap(PHEAP Heap)
Definition: heap.c:993
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:254
#define FALSE
Definition: types.h:117
#define MEM_RESERVE
Definition: nt_native.h:1314
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:319
Definition: heap.h:130
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
PHEAP_FREE_ENTRY NTAPI RtlpFindAndCommitPages(PHEAP Heap, PHEAP_SEGMENT Segment, PSIZE_T Size, PVOID AddressRequested)
Definition: heap.c:612
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:404
#define HEAP_GROWABLE
Definition: nt_native.h:1693
static const UCHAR Index[8]
Definition: usbohci.c:18
unsigned char UCHAR
Definition: xmlstorage.h:181
Status
Definition: gdiplustypes.h:24
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
ULONG_PTR SIZE_T
Definition: typedefs.h:80
SIZE_T SegmentReserve
Definition: heap.h:236
ULONG Flags
Definition: heap.h:227
SIZE_T SegmentCommit
Definition: heap.h:237
NTSTATUS NTAPI RtlpInitializeHeapSegment(IN OUT PHEAP Heap, OUT PHEAP_SEGMENT Segment, IN UCHAR SegmentIndex, IN ULONG SegmentFlags, IN SIZE_T SegmentReserve, IN SIZE_T SegmentCommit)
Definition: heap.c:892
_In_opt_ PVOID _In_opt_ SIZE_T ReserveSize
Definition: rtlfuncs.h:2169
#define DPRINT1
Definition: precomp.h:8
#define MEM_RELEASE
Definition: nt_native.h:1316
unsigned int ULONG
Definition: retypes.h:1
#define PAGE_READWRITE
Definition: nt_native.h:1304

Referenced by RtlpAllocateNonDedicated().

◆ RtlpFindAndCommitPages()

PHEAP_FREE_ENTRY NTAPI RtlpFindAndCommitPages ( PHEAP  Heap,
PHEAP_SEGMENT  Segment,
PSIZE_T  Size,
PVOID  AddressRequested 
)

Definition at line 612 of file heap.c.

616 {
617  PLIST_ENTRY Current;
618  ULONG_PTR Address = 0;
619  PHEAP_UCR_DESCRIPTOR UcrDescriptor, PreviousUcr = NULL;
620  PHEAP_ENTRY FirstEntry, LastEntry;
622 
623  DPRINT("RtlpFindAndCommitPages(%p %p %Ix %08Ix)\n", Heap, Segment, *Size, Address);
624 
625  /* Go through UCRs in a segment */
626  Current = Segment->UCRSegmentList.Flink;
627  while (Current != &Segment->UCRSegmentList)
628  {
629  UcrDescriptor = CONTAINING_RECORD(Current, HEAP_UCR_DESCRIPTOR, SegmentEntry);
630 
631  /* Check if we can use that one right away */
632  if (UcrDescriptor->Size >= *Size &&
633  (UcrDescriptor->Address == AddressRequested || !AddressRequested))
634  {
635  /* Get the address */
636  Address = (ULONG_PTR)UcrDescriptor->Address;
637 
638  /* Commit it */
639  if (Heap->CommitRoutine)
640  {
641  Status = Heap->CommitRoutine(Heap, (PVOID *)&Address, Size);
642  }
643  else
644  {
645  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
646  (PVOID *)&Address,
647  0,
648  Size,
649  MEM_COMMIT,
651  }
652 
653  DPRINT("Committed %Iu bytes at base %08Ix, UCR size is %lu\n", *Size, Address, UcrDescriptor->Size);
654 
655  /* Fail in unsuccessful case */
656  if (!NT_SUCCESS(Status))
657  {
658  DPRINT1("Committing page failed with status 0x%08X\n", Status);
659  return NULL;
660  }
661 
662  /* Update tracking numbers */
663  Segment->NumberOfUnCommittedPages -= (ULONG)(*Size / PAGE_SIZE);
664 
665  /* Calculate first and last entries */
666  FirstEntry = (PHEAP_ENTRY)Address;
667 
668  LastEntry = Segment->LastEntryInSegment;
669  if (!(LastEntry->Flags & HEAP_ENTRY_LAST_ENTRY) ||
670  LastEntry + LastEntry->Size != FirstEntry)
671  {
672  /* Go through the entries to find the last one */
673  if (PreviousUcr)
674  LastEntry = (PHEAP_ENTRY)((ULONG_PTR)PreviousUcr->Address + PreviousUcr->Size);
675  else
676  LastEntry = &Segment->Entry;
677 
678  while (!(LastEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
679  {
680  ASSERT(LastEntry->Size != 0);
681  LastEntry += LastEntry->Size;
682  }
683  }
684  ASSERT((LastEntry + LastEntry->Size) == FirstEntry);
685 
686  /* Unmark it as a last entry */
687  LastEntry->Flags &= ~HEAP_ENTRY_LAST_ENTRY;
688 
689  /* Update UCR descriptor */
690  UcrDescriptor->Address = (PVOID)((ULONG_PTR)UcrDescriptor->Address + *Size);
691  UcrDescriptor->Size -= *Size;
692 
693  DPRINT("Updating UcrDescriptor %p, new Address %p, size %lu\n",
694  UcrDescriptor, UcrDescriptor->Address, UcrDescriptor->Size);
695 
696  /* Set various first entry fields */
697  FirstEntry->SegmentOffset = LastEntry->SegmentOffset;
698  FirstEntry->Size = (USHORT)(*Size >> HEAP_ENTRY_SHIFT);
699  FirstEntry->PreviousSize = LastEntry->Size;
700 
701  /* Check if anything left in this UCR */
702  if (UcrDescriptor->Size == 0)
703  {
704  /* It's fully exhausted */
705 
706  /* Check if this is the end of the segment */
707  if(UcrDescriptor->Address == Segment->LastValidEntry)
708  {
709  FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
710  Segment->LastEntryInSegment = FirstEntry;
711  }
712  else
713  {
714  FirstEntry->Flags = 0;
715  Segment->LastEntryInSegment = Segment->FirstEntry;
716  /* Update field of next entry */
717  ASSERT((FirstEntry + FirstEntry->Size)->PreviousSize == 0);
718  (FirstEntry + FirstEntry->Size)->PreviousSize = FirstEntry->Size;
719  }
720 
721  /* This UCR needs to be removed because it became useless */
722  RemoveEntryList(&UcrDescriptor->SegmentEntry);
723 
724  RtlpDestroyUnCommittedRange(Segment, UcrDescriptor);
725  Segment->NumberOfUnCommittedRanges--;
726  }
727  else
728  {
729  FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
730  Segment->LastEntryInSegment = FirstEntry;
731  }
732 
733  /* We're done */
734  return (PHEAP_FREE_ENTRY)FirstEntry;
735  }
736 
737  /* Advance to the next descriptor */
738  PreviousUcr = UcrDescriptor;
739  Current = Current->Flink;
740  }
741 
742  return NULL;
743 }
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine
Definition: heap.h:268
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
LONG NTSTATUS
Definition: precomp.h:26
static PVOID
Definition: heap.c:41
#define MEM_COMMIT
Definition: nt_native.h:1313
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
Definition: heap.h:130
struct _HEAP_ENTRY * PHEAP_ENTRY
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
void DPRINT(...)
Definition: polytest.cpp:61
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI RtlpDestroyUnCommittedRange(PHEAP_SEGMENT Segment, PHEAP_UCR_DESCRIPTOR UcrDescriptor)
Definition: heap.c:531
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LIST_ENTRY SegmentEntry
Definition: heap.h:284
Status
Definition: gdiplustypes.h:24
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45
#define DPRINT1
Definition: precomp.h:8
#define ULONG_PTR
Definition: config.h:101
#define PAGE_READWRITE
Definition: nt_native.h:1304

Referenced by RtlpExtendHeap(), and RtlpGrowBlockInPlace().

◆ RtlpFindLeastSetBit()

FORCEINLINE UCHAR RtlpFindLeastSetBit ( ULONG  Bits)

Definition at line 53 of file heap.c.

54 {
55  if (Bits & 0xFFFF)
56  {
57  if (Bits & 0xFF)
58  return RtlpBitsClearLow[Bits & 0xFF]; /* Lowest byte */
59  else
60  return RtlpBitsClearLow[(Bits >> 8) & 0xFF] + 8; /* 2nd byte */
61  }
62  else
63  {
64  if ((Bits >> 16) & 0xFF)
65  return RtlpBitsClearLow[(Bits >> 16) & 0xFF] + 16; /* 3rd byte */
66  else
67  return RtlpBitsClearLow[(Bits >> 24) & 0xFF] + 24; /* Highest byte */
68  }
69 }
UCHAR RtlpBitsClearLow[]
Definition: heap.c:31

Referenced by RtlAllocateHeap().

◆ RtlpGetExtraStuffPointer()

PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer ( PHEAP_ENTRY  HeapEntry)

Definition at line 2587 of file heap.c.

2588 {
2589  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
2590 
2591  /* Check if it's a big block */
2592  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
2593  {
2594  VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
2595 
2596  /* Return a pointer to the extra stuff*/
2597  return &VirtualEntry->ExtraStuff;
2598  }
2599  else
2600  {
2601  /* This is a usual entry, which means extra stuff follows this block */
2602  return (PHEAP_ENTRY_EXTRA)(HeapEntry + HeapEntry->Size - 1);
2603  }
2604 }
Definition: heap.h:312
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:44
Definition: heap.h:296
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
HEAP_ENTRY_EXTRA ExtraStuff
Definition: heap.h:315

Referenced by RtlAllocateHeap(), RtlGetUserInfoHeap(), RtlpAllocateNonDedicated(), RtlReAllocateHeap(), and RtlSetUserValueHeap().

◆ RtlpGetSizeOfBigBlock()

SIZE_T NTAPI RtlpGetSizeOfBigBlock ( PHEAP_ENTRY  HeapEntry)

Definition at line 425 of file heap.c.

426 {
427  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
428 
429  /* Get pointer to the containing record */
430  VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
431  ASSERT(VirtualEntry->BusyBlock.Size >= sizeof(HEAP_VIRTUAL_ALLOC_ENTRY));
432 
433  /* Restore the real size */
434  return VirtualEntry->CommitSize - HeapEntry->Size;
435 }
Definition: heap.h:312
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
SIZE_T CommitSize
Definition: heap.h:316
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
HEAP_ENTRY BusyBlock
Definition: heap.h:318

Referenced by RtlpCheckInUsePattern(), RtlReAllocateHeap(), and RtlSizeHeap().

◆ RtlpGrowBlockInPlace()

BOOLEAN NTAPI RtlpGrowBlockInPlace ( IN PHEAP  Heap,
IN ULONG  Flags,
IN PHEAP_ENTRY  InUseEntry,
IN SIZE_T  Size,
IN SIZE_T  Index 
)

Definition at line 2343 of file heap.c.

2348 {
2349  UCHAR EntryFlags, RememberFlags;
2350  PHEAP_FREE_ENTRY FreeEntry, UnusedEntry, FollowingEntry;
2351  SIZE_T FreeSize, PrevSize, TailPart, AddedSize = 0;
2352  PHEAP_ENTRY_EXTRA OldExtra, NewExtra;
2353  UCHAR SegmentOffset;
2354 
2355  /* We can't grow beyond specified threshold */
2356  if (Index > Heap->VirtualMemoryThreshold)
2357  return FALSE;
2358 
2359  /* Get entry flags */
2360  EntryFlags = InUseEntry->Flags;
2361 
2362  /* Get the next free entry */
2363  FreeEntry = (PHEAP_FREE_ENTRY)(InUseEntry + InUseEntry->Size);
2364 
2365  if (EntryFlags & HEAP_ENTRY_LAST_ENTRY)
2366  {
2367  /* There is no next block, just uncommitted space. Calculate how much is needed */
2368  FreeSize = (Index - InUseEntry->Size) << HEAP_ENTRY_SHIFT;
2369  FreeSize = ROUND_UP(FreeSize, PAGE_SIZE);
2370 
2371  /* Find and commit those pages */
2372  FreeEntry = RtlpFindAndCommitPages(Heap,
2373  Heap->Segments[InUseEntry->SegmentOffset],
2374  &FreeSize,
2375  FreeEntry);
2376 
2377  /* Fail if it failed... */
2378  if (!FreeEntry) return FALSE;
2379 
2380  /* It was successful, perform coalescing */
2381  FreeSize = FreeSize >> HEAP_ENTRY_SHIFT;
2382  FreeEntry = RtlpCoalesceFreeBlocks(Heap, FreeEntry, &FreeSize, FALSE);
2383 
2384  /* Check if it's enough */
2385  if (FreeSize + InUseEntry->Size < Index)
2386  {
2387  /* Still not enough */
2388  RtlpInsertFreeBlock(Heap, FreeEntry, FreeSize);
2389  Heap->TotalFreeSize += FreeSize;
2390  return FALSE;
2391  }
2392 
2393  /* Remember flags of this free entry */
2394  RememberFlags = FreeEntry->Flags;
2395 
2396  /* Sum up sizes */
2397  FreeSize += InUseEntry->Size;
2398  }
2399  else
2400  {
2401  /* The next block indeed exists. Check if it's free or in use */
2402  if (FreeEntry->Flags & HEAP_ENTRY_BUSY) return FALSE;
2403 
2404  /* Next entry is free, check if it can fit the block we need */
2405  FreeSize = InUseEntry->Size + FreeEntry->Size;
2406  if (FreeSize < Index) return FALSE;
2407 
2408  /* Remember flags of this free entry */
2409  RememberFlags = FreeEntry->Flags;
2410 
2411  /* Remove this block from the free list */
2412  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE, FALSE);
2413  Heap->TotalFreeSize -= FreeEntry->Size;
2414  }
2415 
2416  PrevSize = (InUseEntry->Size << HEAP_ENTRY_SHIFT) - InUseEntry->UnusedBytes;
2417  FreeSize -= Index;
2418 
2419  /* Don't produce too small blocks */
2420  if (FreeSize <= 2)
2421  {
2422  Index += FreeSize;
2423  FreeSize = 0;
2424  }
2425 
2426  /* Process extra stuff */
2427  if (EntryFlags & HEAP_ENTRY_EXTRA_PRESENT)
2428  {
2429  /* Calculate pointers */
2430  OldExtra = (PHEAP_ENTRY_EXTRA)(InUseEntry + InUseEntry->Size - 1);
2431  NewExtra = (PHEAP_ENTRY_EXTRA)(InUseEntry + Index - 1);
2432 
2433  /* Copy contents */
2434  *NewExtra = *OldExtra;
2435 
2436  // FIXME Tagging
2437  }
2438 
2439  /* Update sizes */
2440  InUseEntry->Size = (USHORT)Index;
2441  InUseEntry->UnusedBytes = (UCHAR)((Index << HEAP_ENTRY_SHIFT) - Size);
2442 
2443  /* Check if there is a free space remaining after merging those blocks */
2444  if (!FreeSize)
2445  {
2446  /* Update flags and sizes */
2447  InUseEntry->Flags |= RememberFlags & HEAP_ENTRY_LAST_ENTRY;
2448 
2449  /* Either update previous size of the next entry or mark it as a last
2450  entry in the segment */
2451  if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
2452  {
2453  (InUseEntry + InUseEntry->Size)->PreviousSize = InUseEntry->Size;
2454  }
2455  else
2456  {
2457  SegmentOffset = InUseEntry->SegmentOffset;
2458  ASSERT(SegmentOffset < HEAP_SEGMENTS);
2459  Heap->Segments[SegmentOffset]->LastEntryInSegment = InUseEntry;
2460  }
2461  }
2462  else
2463  {
2464  /* Complex case, we need to split the block to give unused free space
2465  back to the heap */
2466  UnusedEntry = (PHEAP_FREE_ENTRY)(InUseEntry + Index);
2467  UnusedEntry->PreviousSize = (USHORT)Index;
2468  UnusedEntry->SegmentOffset = InUseEntry->SegmentOffset;
2469 
2470  /* Update the following block or set the last entry in the segment */
2471  if (RememberFlags & HEAP_ENTRY_LAST_ENTRY)
2472  {
2473  SegmentOffset = UnusedEntry->SegmentOffset;
2474  ASSERT(SegmentOffset < HEAP_SEGMENTS);
2475  Heap->Segments[SegmentOffset]->LastEntryInSegment = UnusedEntry;
2476 
2477  /* Set flags and size */
2478  UnusedEntry->Flags = RememberFlags;
2479  UnusedEntry->Size = (USHORT)FreeSize;
2480 
2481  /* Insert it to the heap and update total size */
2482  RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
2483  Heap->TotalFreeSize += FreeSize;
2484  }
2485  else
2486  {
2487  /* There is a block after this one */
2488  FollowingEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)UnusedEntry + FreeSize);
2489 
2490  if (FollowingEntry->Flags & HEAP_ENTRY_BUSY)
2491  {
2492  /* Update flags and set size of the unused space entry */
2493  UnusedEntry->Flags = RememberFlags & (~HEAP_ENTRY_LAST_ENTRY);
2494  UnusedEntry->Size = (USHORT)FreeSize;
2495 
2496  /* Update previous size of the following entry */
2497  FollowingEntry->PreviousSize = (USHORT)FreeSize;
2498 
2499  /* Insert it to the heap and update total free size */
2500  RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
2501  Heap->TotalFreeSize += FreeSize;
2502  }
2503  else
2504  {
2505  /* That following entry is also free, what a fortune! */
2506  RememberFlags = FollowingEntry->Flags;
2507 
2508  /* Remove it */
2509  RtlpRemoveFreeBlock(Heap, FollowingEntry, FALSE, FALSE);
2510  Heap->TotalFreeSize -= FollowingEntry->Size;
2511 
2512  /* And make up a new combined block */
2513  FreeSize += FollowingEntry->Size;
2514  UnusedEntry->Flags = RememberFlags;
2515 
2516  /* Check where to put it */
2517  if (FreeSize <= HEAP_MAX_BLOCK_SIZE)
2518  {
2519  /* Fine for a dedicated list */
2520  UnusedEntry->Size = (USHORT)FreeSize;
2521 
2522  if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
2523  {
2524  ((PHEAP_ENTRY)UnusedEntry + FreeSize)->PreviousSize = (USHORT)FreeSize;
2525  }
2526  else
2527  {
2528  SegmentOffset = UnusedEntry->SegmentOffset;
2529  ASSERT(SegmentOffset < HEAP_SEGMENTS);
2530  Heap->Segments[SegmentOffset]->LastEntryInSegment = UnusedEntry;
2531  }
2532 
2533  /* Insert it back and update total size */
2534  RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
2535  Heap->TotalFreeSize += FreeSize;
2536  }
2537  else
2538  {
2539  /* The block is very large, leave all the hassle to the insertion routine */
2540  RtlpInsertFreeBlock(Heap, UnusedEntry, FreeSize);
2541  }
2542  }
2543  }
2544  }
2545 
2546  /* Properly "zero out" (and fill!) the space */
2547  if (Flags & HEAP_ZERO_MEMORY)
2548  {
2549  RtlZeroMemory((PCHAR)(InUseEntry + 1) + PrevSize, Size - PrevSize);
2550  }
2551  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
2552  {
2553  /* Calculate tail part which we need to fill */
2554  TailPart = PrevSize & (sizeof(ULONG) - 1);
2555 
2556  /* "Invert" it as usual */
2557  if (TailPart) TailPart = 4 - TailPart;
2558 
2559  if (Size > (PrevSize + TailPart))
2560  AddedSize = (Size - (PrevSize + TailPart)) & ~(sizeof(ULONG) - 1);
2561 
2562  if (AddedSize)
2563  {
2564  RtlFillMemoryUlong((PCHAR)(InUseEntry + 1) + PrevSize + TailPart,
2565  AddedSize,
2567  }
2568  }
2569 
2570  /* Fill the new tail */
2571  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
2572  {
2573  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size,
2575  HEAP_TAIL_FILL);
2576  }
2577 
2578  /* Copy user settable flags */
2579  InUseEntry->Flags &= ~HEAP_ENTRY_SETTABLE_FLAGS;
2580  InUseEntry->Flags |= ((Flags & HEAP_SETTABLE_USER_FLAGS) >> 4);
2581 
2582  /* Return success */
2583  return TRUE;
2584 }
signed char * PCHAR
Definition: retypes.h:7
#define HEAP_ENTRY_SETTABLE_FLAGS
Definition: heap.h:49
#define ARENA_INUSE_FILLER
Definition: oleaut.c:105
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:251
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceFreeBlocks(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, PSIZE_T FreeSize, BOOLEAN Remove)
Definition: heap.c:1000
#define HEAP_SEGMENTS
Definition: heap.h:16
#define TRUE
Definition: types.h:120
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:24
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FALSE
Definition: types.h:117
Definition: heap.h:296
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:319
Definition: heap.h:130
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
if(!(yy_init))
Definition: macro.lex.yy.c:714
PHEAP_FREE_ENTRY NTAPI RtlpFindAndCommitPages(PHEAP Heap, PHEAP_SEGMENT Segment, PSIZE_T Size, PVOID AddressRequested)
Definition: heap.c:612
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
static const UCHAR Index[8]
Definition: usbohci.c:18
#define HEAP_ENTRY_SIZE
Definition: heap.h:18
#define HEAP_SETTABLE_USER_FLAGS
Definition: nt_native.h:1708
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID NTAPI RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN Dedicated, BOOLEAN NoFill)
Definition: heap.c:383
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45
#define HEAP_TAIL_FILL
Definition: heap.h:28
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42
struct _HEAP_ENTRY_EXTRA * PHEAP_ENTRY_EXTRA

Referenced by RtlReAllocateHeap().

◆ RtlpInitializeHeap()

NTSTATUS NTAPI RtlpInitializeHeap ( OUT PHEAP  Heap,
IN ULONG  Flags,
IN PHEAP_LOCK Lock  OPTIONAL,
IN PRTL_HEAP_PARAMETERS  Parameters 
)

Definition at line 87 of file heap.c.

91 {
92  ULONG NumUCRs = 8;
93  ULONG Index;
94  SIZE_T HeaderSize;
96  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
97 
98  /* Preconditions */
99  ASSERT(Heap != NULL);
100  ASSERT(Parameters != NULL);
102  ASSERT(!(Flags & HEAP_NO_SERIALIZE) || (Lock == NULL)); /* HEAP_NO_SERIALIZE => no lock */
103 
104  /* Start out with the size of a plain Heap header */
105  HeaderSize = ROUND_UP(sizeof(HEAP), sizeof(HEAP_ENTRY));
106 
107  /* Check if space needs to be added for the Heap Lock */
108  if (!(Flags & HEAP_NO_SERIALIZE))
109  {
110  if (Lock != NULL)
111  /* The user manages the Heap Lock */
113  else
114  if (RtlpGetMode() == UserMode)
115  {
116  /* In user mode, the Heap Lock trails the Heap header */
117  Lock = (PHEAP_LOCK) ((ULONG_PTR) (Heap) + HeaderSize);
118  HeaderSize += ROUND_UP(sizeof(HEAP_LOCK), sizeof(HEAP_ENTRY));
119  }
120  }
121 
122  /* Add space for the initial Heap UnCommitted Range Descriptor list */
123  UcrDescriptor = (PHEAP_UCR_DESCRIPTOR) ((ULONG_PTR) (Heap) + HeaderSize);
124  HeaderSize += ROUND_UP(NumUCRs * sizeof(HEAP_UCR_DESCRIPTOR), sizeof(HEAP_ENTRY));
125 
126  /* Sanity check */
127  ASSERT(HeaderSize <= PAGE_SIZE);
128 
129  /* Initialise the Heap Entry header containing the Heap header */
130  Heap->Entry.Size = (USHORT)(HeaderSize >> HEAP_ENTRY_SHIFT);
131  Heap->Entry.Flags = HEAP_ENTRY_BUSY;
132  Heap->Entry.SmallTagIndex = LOBYTE(Heap->Entry.Size) ^ HIBYTE(Heap->Entry.Size) ^ Heap->Entry.Flags;
133  Heap->Entry.PreviousSize = 0;
134  Heap->Entry.SegmentOffset = 0;
135  Heap->Entry.UnusedBytes = 0;
136 
137  /* Initialise the Heap header */
138  Heap->Signature = HEAP_SIGNATURE;
139  Heap->Flags = Flags;
140  Heap->ForceFlags = (Flags & (HEAP_NO_SERIALIZE |
149 
150  /* Initialise the Heap parameters */
151  Heap->VirtualMemoryThreshold = ROUND_UP(Parameters->VirtualMemoryThreshold, sizeof(HEAP_ENTRY)) >> HEAP_ENTRY_SHIFT;
152  Heap->SegmentReserve = Parameters->SegmentReserve;
153  Heap->SegmentCommit = Parameters->SegmentCommit;
154  Heap->DeCommitFreeBlockThreshold = Parameters->DeCommitFreeBlockThreshold >> HEAP_ENTRY_SHIFT;
155  Heap->DeCommitTotalFreeThreshold = Parameters->DeCommitTotalFreeThreshold >> HEAP_ENTRY_SHIFT;
156  Heap->MaximumAllocationSize = Parameters->MaximumAllocationSize;
157  Heap->CommitRoutine = Parameters->CommitRoutine;
158 
159  /* Initialise the Heap validation info */
160  Heap->HeaderValidateCopy = NULL;
161  Heap->HeaderValidateLength = (USHORT)HeaderSize;
162 
163  /* Initialise the Heap Lock */
165  {
167  if (!NT_SUCCESS(Status))
168  return Status;
169  }
170  Heap->LockVariable = Lock;
171 
172  /* Initialise the Heap alignment info */
174  {
175  Heap->AlignMask = (ULONG) ~15;
176  Heap->AlignRound = 15 + sizeof(HEAP_ENTRY);
177  }
178  else
179  {
180  Heap->AlignMask = (ULONG) ~(sizeof(HEAP_ENTRY) - 1);
181  Heap->AlignRound = 2 * sizeof(HEAP_ENTRY) - 1;
182  }
183 
185  Heap->AlignRound += sizeof(HEAP_ENTRY);
186 
187  /* Initialise the Heap Segment list */
188  for (Index = 0; Index < HEAP_SEGMENTS; ++Index)
189  Heap->Segments[Index] = NULL;
190 
191  /* Initialise the Heap Free Heap Entry lists */
192  for (Index = 0; Index < HEAP_FREELISTS; ++Index)
193  InitializeListHead(&Heap->FreeLists[Index]);
194 
195  /* Initialise the Heap Virtual Allocated Blocks list */
196  InitializeListHead(&Heap->VirtualAllocdBlocks);
197 
198  /* Initialise the Heap UnCommitted Region lists */
199  InitializeListHead(&Heap->UCRSegments);
200  InitializeListHead(&Heap->UCRList);
201 
202  /* Register the initial Heap UnCommitted Region Descriptors */
203  for (Index = 0; Index < NumUCRs; ++Index)
204  InsertTailList(&Heap->UCRList, &UcrDescriptor[Index].ListEntry);
205 
206  return STATUS_SUCCESS;
207 }
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
#define HEAP_CREATE_ALIGN_16
Definition: nt_native.h:1701
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
#define HEAP_SEGMENTS
Definition: heap.h:16
struct _HEAP_UCR_DESCRIPTOR * PHEAP_UCR_DESCRIPTOR
LONG NTSTATUS
Definition: precomp.h:26
#define HIBYTE(W)
Definition: jmemdos.c:486
#define InsertTailList(ListHead, Entry)
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
struct _HEAP_LOCK * PHEAP_LOCK
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
smooth NULL
Definition: ftsmooth.c:416
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
#define HEAP_VALIDATE_PARAMETERS_ENABLED
Definition: rtltypes.h:167
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define HEAP_VALIDATE_ALL_ENABLED
Definition: rtltypes.h:166
static const UCHAR Index[8]
Definition: usbohci.c:18
#define for
Definition: utility.h:88
NTSTATUS NTAPI RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
Definition: libsupp.c:126
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define HEAP_FREELISTS
Definition: heap.h:15
#define HEAP_LOCK_USER_ALLOCATED
Definition: rtltypes.h:168
Status
Definition: gdiplustypes.h:24
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:887
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment IN PNDIS_RW_LOCK Lock
Definition: CrNtStubs.h:75
struct _HEAP_ENTRY HEAP_ENTRY
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define HEAP_SIGNATURE
Definition: heap.h:52
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
#define HEAP_REALLOC_IN_PLACE_ONLY
Definition: nt_native.h:1696
Definition: heap.c:51

Referenced by RtlCreateHeap().

◆ RtlpInitializeHeapSegment()

NTSTATUS NTAPI RtlpInitializeHeapSegment ( IN OUT PHEAP  Heap,
OUT PHEAP_SEGMENT  Segment,
IN UCHAR  SegmentIndex,
IN ULONG  SegmentFlags,
IN SIZE_T  SegmentReserve,
IN SIZE_T  SegmentCommit 
)

Definition at line 892 of file heap.c.

898 {
899  PHEAP_ENTRY HeapEntry;
900 
901  /* Preconditions */
902  ASSERT(Heap != NULL);
903  ASSERT(Segment != NULL);
904  ASSERT(SegmentCommit >= PAGE_SIZE);
905  ASSERT(ROUND_DOWN(SegmentCommit, PAGE_SIZE) == SegmentCommit);
906  ASSERT(SegmentReserve >= SegmentCommit);
907  ASSERT(ROUND_DOWN(SegmentReserve, PAGE_SIZE) == SegmentReserve);
908 
909  DPRINT("RtlpInitializeHeapSegment(%p %p %x %x %lx %lx)\n", Heap, Segment, SegmentIndex, SegmentFlags, SegmentReserve, SegmentCommit);
910 
911  /* Initialise the Heap Entry header if this is not the first Heap Segment */
912  if ((PHEAP_SEGMENT) (Heap) != Segment)
913  {
914  Segment->Entry.Size = ROUND_UP(sizeof(HEAP_SEGMENT), sizeof(HEAP_ENTRY)) >> HEAP_ENTRY_SHIFT;
915  Segment->Entry.Flags = HEAP_ENTRY_BUSY;
916  Segment->Entry.SmallTagIndex = LOBYTE(Segment->Entry.Size) ^ HIBYTE(Segment->Entry.Size) ^ Segment->Entry.Flags;
917  Segment->Entry.PreviousSize = 0;
918  Segment->Entry.SegmentOffset = SegmentIndex;
919  Segment->Entry.UnusedBytes = 0;
920  }
921 
922  /* Sanity check */
923  ASSERT((Segment->Entry.Size << HEAP_ENTRY_SHIFT) <= PAGE_SIZE);
924 
925  /* Initialise the Heap Segment header */
926  Segment->SegmentSignature = HEAP_SEGMENT_SIGNATURE;
927  Segment->SegmentFlags = SegmentFlags;
928  Segment->Heap = Heap;
929  Heap->Segments[SegmentIndex] = Segment;
930 
931  /* Initialise the Heap Segment location information */
932  Segment->BaseAddress = Segment;
933  Segment->NumberOfPages = (ULONG)(SegmentReserve >> PAGE_SHIFT);
934 
935  /* Initialise the Heap Entries contained within the Heap Segment */
936  Segment->FirstEntry = &Segment->Entry + Segment->Entry.Size;
937  Segment->LastValidEntry = (PHEAP_ENTRY)((ULONG_PTR)Segment + SegmentReserve);
938 
939  if (((SIZE_T)Segment->Entry.Size << HEAP_ENTRY_SHIFT) < SegmentCommit)
940  {
941  HeapEntry = Segment->FirstEntry;
942 
943  /* Prepare a Free Heap Entry header */
944  HeapEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
945  HeapEntry->PreviousSize = Segment->Entry.Size;
946  HeapEntry->SegmentOffset = SegmentIndex;
947 
948  /* Register the Free Heap Entry */
949  RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY) HeapEntry, (SegmentCommit >> HEAP_ENTRY_SHIFT) - Segment->Entry.Size);
950  }
951 
952  /* Always point to a valid entry */
953  Segment->LastEntryInSegment = Segment->FirstEntry;
954 
955  /* Initialise the Heap Segment UnCommitted Range information */
956  Segment->NumberOfUnCommittedPages = (ULONG)((SegmentReserve - SegmentCommit) >> PAGE_SHIFT);
957  Segment->NumberOfUnCommittedRanges = 0;
958  InitializeListHead(&Segment->UCRSegmentList);
959 
960  /* Register the UnCommitted Range of the Heap Segment */
961  if (Segment->NumberOfUnCommittedPages != 0)
962  RtlpInsertUnCommittedPages(Segment, (ULONG_PTR) (Segment) + SegmentCommit, SegmentReserve - SegmentCommit);
963 
964  return STATUS_SUCCESS;
965 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
uint32_t ULONG_PTR
Definition: typedefs.h:65
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:319
Definition: heap.h:130
struct _HEAP_ENTRY * PHEAP_ENTRY
smooth NULL
Definition: ftsmooth.c:416
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
void DPRINT(...)
Definition: polytest.cpp:61
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
#define HEAP_SEGMENT_SIGNATURE
Definition: heap.h:53
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
ULONG_PTR SIZE_T
Definition: typedefs.h:80
VOID NTAPI RtlpInsertUnCommittedPages(PHEAP_SEGMENT Segment, ULONG_PTR Address, SIZE_T Size)
Definition: heap.c:543
Definition: heap.h:136
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by RtlCreateHeap(), and RtlpExtendHeap().

◆ RtlpInsertFreeBlock()

VOID NTAPI RtlpInsertFreeBlock ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry,
SIZE_T  BlockSize 
)

Definition at line 319 of file heap.c.

322 {
323  USHORT Size, PreviousSize;
324  UCHAR SegmentOffset, Flags;
326 
327  DPRINT("RtlpInsertFreeBlock(%p %p %x)\n", Heap, FreeEntry, BlockSize);
328 
329  /* Increase the free size counter */
330  Heap->TotalFreeSize += BlockSize;
331 
332  /* Remember certain values */
333  Flags = FreeEntry->Flags;
334  PreviousSize = FreeEntry->PreviousSize;
335  SegmentOffset = FreeEntry->SegmentOffset;
336  Segment = Heap->Segments[SegmentOffset];
337 
338  /* Process it */
339  while (BlockSize)
340  {
341  /* Check for the max size */
342  if (BlockSize > HEAP_MAX_BLOCK_SIZE)
343  {
345 
346  /* Special compensation if it goes above limit just by 1 */
347  if (BlockSize == (HEAP_MAX_BLOCK_SIZE + 1))
348  Size -= 16;
349 
350  FreeEntry->Flags = 0;
351  }
352  else
353  {
354  Size = (USHORT)BlockSize;
355  FreeEntry->Flags = Flags;
356  }
357 
358  /* Change its size and insert it into a free list */
359  FreeEntry->Size = Size;
360  FreeEntry->PreviousSize = PreviousSize;
361  FreeEntry->SegmentOffset = SegmentOffset;
362 
363  /* Call a helper to actually insert the block */
364  RtlpInsertFreeBlockHelper(Heap, FreeEntry, Size, FALSE);
365 
366  /* Update sizes */
367  PreviousSize = Size;
368  BlockSize -= Size;
369 
370  /* Go to the next entry */
371  FreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + Size);
372 
373  /* Check if that's all */
374  if ((PHEAP_ENTRY)FreeEntry >= Segment->LastValidEntry) return;
375  }
376 
377  /* Update previous size if needed */
378  if (!(Flags & HEAP_ENTRY_LAST_ENTRY))
379  FreeEntry->PreviousSize = PreviousSize;
380 }
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:251
SIZE_T TotalFreeSize
Definition: heap.h:240
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:24
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:254
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FALSE
Definition: types.h:117
void DPRINT(...)
Definition: polytest.cpp:61
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45

Referenced by RtlFreeHeap(), RtlpDeCommitFreeBlock(), RtlpExtendHeap(), RtlpGrowBlockInPlace(), RtlpInitializeHeapSegment(), RtlpSplitEntry(), and RtlReAllocateHeap().

◆ RtlpInsertFreeBlockHelper()

VOID NTAPI RtlpInsertFreeBlockHelper ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry,
SIZE_T  BlockSize,
BOOLEAN  NoFill 
)

Definition at line 251 of file heap.c.

255 {
256  PLIST_ENTRY FreeListHead, Current;
257  PHEAP_FREE_ENTRY CurrentEntry;
258 
259  ASSERT(FreeEntry->Size == BlockSize);
260 
261  /* Fill if it's not denied */
262  if (!NoFill)
263  {
264  FreeEntry->Flags &= ~(HEAP_ENTRY_FILL_PATTERN |
267 
268  if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
269  {
270  RtlFillMemoryUlong((PCHAR)(FreeEntry + 1),
271  (BlockSize << HEAP_ENTRY_SHIFT) - sizeof(*FreeEntry),
273 
274  FreeEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
275  }
276  }
277  else
278  {
279  /* Clear out all flags except the last entry one */
280  FreeEntry->Flags &= HEAP_ENTRY_LAST_ENTRY;
281  }
282 
283  /* Insert it either into dedicated or non-dedicated list */
284  if (BlockSize < HEAP_FREELISTS)
285  {
286  /* Dedicated list */
287  FreeListHead = &Heap->FreeLists[BlockSize];
288 
289  if (IsListEmpty(FreeListHead))
290  {
291  RtlpSetFreeListsBit(Heap, FreeEntry);
292  }
293  }
294  else
295  {
296  /* Non-dedicated one */
297  FreeListHead = &Heap->FreeLists[0];
298  Current = FreeListHead->Flink;
299 
300  /* Find a position where to insert it to (the list must be sorted) */
301  while (FreeListHead != Current)
302  {
303  CurrentEntry = CONTAINING_RECORD(Current, HEAP_FREE_ENTRY, FreeList);
304 
305  if (BlockSize <= CurrentEntry->Size)
306  break;
307 
308  Current = Current->Flink;
309  }
310 
311  FreeListHead = Current;
312  }
313 
314  /* Actually insert it into the list */
315  InsertTailList(FreeListHead, &FreeEntry->FreeList);
316 }
signed char * PCHAR
Definition: retypes.h:7
#define ARENA_FREE_FILLER
Definition: jsutils.c:64
LIST_ENTRY FreeList
Definition: heap.h:132
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
Definition: heap.h:130
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define HEAP_FREELISTS
Definition: heap.h:15
MmuFreePage * FreeList
Definition: mmuobject.c:60
Definition: typedefs.h:119
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
ULONG Flags
Definition: heap.h:227
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42
FORCEINLINE VOID RtlpSetFreeListsBit(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry)
Definition: heap.c:211
LIST_ENTRY FreeLists[HEAP_FREELISTS]
Definition: heap.h:260

Referenced by RtlFreeHeap(), RtlpDeCommitFreeBlock(), RtlpGrowBlockInPlace(), RtlpInsertFreeBlock(), RtlpSplitEntry(), and RtlReAllocateHeap().

◆ RtlpInsertUnCommittedPages()

VOID NTAPI RtlpInsertUnCommittedPages ( PHEAP_SEGMENT  Segment,
ULONG_PTR  Address,
SIZE_T  Size 
)

Definition at line 543 of file heap.c.

546 {
547  PLIST_ENTRY Current;
548  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
549 
550  DPRINT("RtlpInsertUnCommittedPages(%p %08Ix %Ix)\n", Segment, Address, Size);
551 
552  /* Go through the list of UCR descriptors, they are sorted from lowest address
553  to the highest */
554  Current = Segment->UCRSegmentList.Flink;
555  while (Current != &Segment->UCRSegmentList)
556  {
557  UcrDescriptor = CONTAINING_RECORD(Current, HEAP_UCR_DESCRIPTOR, SegmentEntry);
558 
559  if ((ULONG_PTR)UcrDescriptor->Address > Address)
560  {
561  /* Check for a really lucky case */
562  if ((Address + Size) == (ULONG_PTR)UcrDescriptor->Address)
563  {
564  /* Exact match */
565  UcrDescriptor->Address = (PVOID)Address;
566  UcrDescriptor->Size += Size;
567  return;
568  }
569 
570  /* We found the block before which the new one should go */
571  break;
572  }
573  else if (((ULONG_PTR)UcrDescriptor->Address + UcrDescriptor->Size) == Address)
574  {
575  /* Modify this entry */
576  Address = (ULONG_PTR)UcrDescriptor->Address;
577  Size += UcrDescriptor->Size;
578 
579  /* Advance to the next descriptor */
580  Current = Current->Flink;
581 
582  /* Remove the current descriptor from the list and destroy it */
583  RemoveEntryList(&UcrDescriptor->SegmentEntry);
584  RtlpDestroyUnCommittedRange(Segment, UcrDescriptor);
585 
586  Segment->NumberOfUnCommittedRanges--;
587  }
588  else
589  {
590  /* Advance to the next descriptor */
591  Current = Current->Flink;
592  }
593  }
594 
595  /* Create a new UCR descriptor */
596  UcrDescriptor = RtlpCreateUnCommittedRange(Segment);
597  if (!UcrDescriptor) return;
598 
599  UcrDescriptor->Address = (PVOID)Address;
600  UcrDescriptor->Size = Size;
601 
602  /* "Current" is the descriptor before which our one should go */
603  InsertTailList(Current, &UcrDescriptor->SegmentEntry);
604 
605  DPRINT("Added segment UCR with base %08Ix, size 0x%x\n", Address, Size);
606 
607  /* Increase counters */
608  Segment->NumberOfUnCommittedRanges++;
609 }
static PVOID
Definition: heap.c:41
#define InsertTailList(ListHead, Entry)
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
static WCHAR Address[46]
Definition: ping.c:68
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
VOID NTAPI RtlpDestroyUnCommittedRange(PHEAP_SEGMENT Segment, PHEAP_UCR_DESCRIPTOR UcrDescriptor)
Definition: heap.c:531
LIST_ENTRY SegmentEntry
Definition: heap.h:284
Definition: typedefs.h:119
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange(PHEAP_SEGMENT Segment)
Definition: heap.c:438
#define ULONG_PTR
Definition: config.h:101

Referenced by RtlpDeCommitFreeBlock(), and RtlpInitializeHeapSegment().

◆ RtlpRemoveFreeBlock()

VOID NTAPI RtlpRemoveFreeBlock ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry,
BOOLEAN  Dedicated,
BOOLEAN  NoFill 
)

Definition at line 383 of file heap.c.

387 {
388  SIZE_T Result, RealSize;
389 
390  /* Remove the free block and update the freelists bitmap */
391  if (RemoveEntryList(&FreeEntry->FreeList) &&
392  (Dedicated || (!Dedicated && FreeEntry->Size < HEAP_FREELISTS)))
393  {
394  RtlpClearFreeListsBit(Heap, FreeEntry);
395  }
396 
397  /* Fill with pattern if necessary */
398  if (!NoFill &&
399  (FreeEntry->Flags & HEAP_ENTRY_FILL_PATTERN))
400  {
401  RealSize = (FreeEntry->Size << HEAP_ENTRY_SHIFT) - sizeof(*FreeEntry);
402 
403  /* Deduct extra stuff from block's real size */
404  if (FreeEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT &&
405  RealSize > sizeof(HEAP_FREE_ENTRY_EXTRA))
406  {
407  RealSize -= sizeof(HEAP_FREE_ENTRY_EXTRA);
408  }
409 
410  /* Check if the free filler is intact */
411  Result = RtlCompareMemoryUlong((PCHAR)(FreeEntry + 1),
412  RealSize,
414 
415  if (Result != RealSize)
416  {
417  DPRINT1("Free heap block %p modified at %p after it was freed\n",
418  FreeEntry,
419  (PCHAR)(FreeEntry + 1) + Result);
420  }
421  }
422 }
signed char * PCHAR
Definition: retypes.h:7
_Must_inspect_result_ NTSYSAPI SIZE_T NTAPI RtlCompareMemoryUlong(_In_reads_bytes_(Length) PVOID Source, _In_ SIZE_T Length, _In_ ULONG Pattern)
#define ARENA_FREE_FILLER
Definition: jsutils.c:64
LIST_ENTRY FreeList
Definition: heap.h:132
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
Definition: heap.h:296
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define HEAP_ENTRY_SHIFT
Definition: heap.h:22
#define HEAP_FREELISTS
Definition: heap.h:15
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define DPRINT1
Definition: precomp.h:8
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42
HEAP_ENTRY_EXTRA HEAP_FREE_ENTRY_EXTRA
Definition: heap.h:310
FORCEINLINE VOID RtlpClearFreeListsBit(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry)
Definition: heap.c:231

Referenced by RtlAllocateHeap(), RtlpCoalesceFreeBlocks(), RtlpGrowBlockInPlace(), RtlpSplitEntry(), and RtlReAllocateHeap().

◆ RtlProtectHeap()

PVOID NTAPI RtlProtectHeap ( IN PVOID  HeapHandle,
IN BOOLEAN  ReadOnly 
)

Definition at line 3977 of file heap.c.

3979 {
3980  UNIMPLEMENTED;
3981  return NULL;
3982 }
smooth NULL
Definition: ftsmooth.c:416
#define UNIMPLEMENTED
Definition: debug.h:115

◆ RtlpSetFreeListsBit()

FORCEINLINE VOID RtlpSetFreeListsBit ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry 
)

Definition at line 211 of file heap.c.

213 {
214  ULONG Index, Bit;
215 
216  ASSERT(FreeEntry->Size < HEAP_FREELISTS);
217 
218  /* Calculate offset in the free list bitmap */
219  Index = FreeEntry->Size >> 3; /* = FreeEntry->Size / (sizeof(UCHAR) * 8)*/
220  Bit = 1 << (FreeEntry->Size & 7);
221 
222  /* Assure it's not already set */
223  ASSERT((Heap->u.FreeListsInUseBytes[Index] & Bit) == 0);
224 
225  /* Set it */
226  Heap->u.FreeListsInUseBytes[Index] |= Bit;
227 }
UCHAR FreeListsInUseBytes[HEAP_FREELISTS/(sizeof(UCHAR) *8)]
Definition: heap.h:265
static const UCHAR Index[8]
Definition: usbohci.c:18
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define HEAP_FREELISTS
Definition: heap.h:15
union _HEAP::@4128 u
unsigned int ULONG
Definition: retypes.h:1

Referenced by RtlpInsertFreeBlockHelper().

◆ RtlpSplitEntry()

PHEAP_ENTRY NTAPI RtlpSplitEntry ( PHEAP  Heap,
ULONG  Flags,
PHEAP_FREE_ENTRY  FreeBlock,
SIZE_T  AllocationSize,
SIZE_T  Index,
SIZE_T  Size 
)

Definition at line 1661 of file heap.c.

1667 {
1668  PHEAP_FREE_ENTRY SplitBlock, SplitBlock2;
1669  UCHAR FreeFlags, EntryFlags = HEAP_ENTRY_BUSY;
1670  PHEAP_ENTRY InUseEntry;
1671  SIZE_T FreeSize;
1672  UCHAR SegmentOffset;
1673 
1674  /* Add extra flags in case of settable user value feature is requested,
1675  or there is a tag (small or normal) or there is a request to
1676  capture stack backtraces */
1677  if ((Flags & HEAP_EXTRA_FLAGS_MASK) ||
1678  Heap->PseudoTagEntries)
1679  {
1680  /* Add flag which means that the entry will have extra stuff attached */
1681  EntryFlags |= HEAP_ENTRY_EXTRA_PRESENT;
1682 
1683  /* NB! AllocationSize is already adjusted by RtlAllocateHeap */
1684  }
1685 
1686  /* Add settable user flags, if any */
1687  EntryFlags |= (Flags & HEAP_SETTABLE_USER_FLAGS) >> 4;
1688 
1689  /* Save flags, update total free size */
1690  FreeFlags = FreeBlock->Flags;
1691  Heap->TotalFreeSize -= FreeBlock->Size;
1692 
1693  /* Make this block an in-use one */
1694  InUseEntry = (PHEAP_ENTRY)FreeBlock;
1695  InUseEntry->Flags = EntryFlags;
1696  InUseEntry->SmallTagIndex = 0;
1697 
1698  /* Calculate the extra amount */
1699  FreeSize = InUseEntry->Size - Index;
1700 
1701  /* Update it's size fields (we don't need their data anymore) */
1702  InUseEntry->Size = (USHORT)Index;
1703  InUseEntry->UnusedBytes = (UCHAR)(AllocationSize - Size);
1704 
1705  /* If there is something to split - do the split */
1706  if (FreeSize != 0)
1707  {
1708  /* Don't split if resulting entry can't contain any payload data
1709  (i.e. being just HEAP_ENTRY_SIZE) */
1710  if (FreeSize == 1)
1711  {
1712  /* Increase sizes of the in-use entry */
1713  InUseEntry->Size++;
1714  InUseEntry->UnusedBytes += sizeof(HEAP_ENTRY);
1715  }
1716  else
1717  {
1718  /* Calculate a pointer to the new entry */
1719  SplitBlock = (PHEAP_FREE_ENTRY)(InUseEntry + Index);
1720 
1721  /* Initialize it */
1722  SplitBlock->Flags = FreeFlags;
1723  SplitBlock->SegmentOffset = InUseEntry->SegmentOffset;
1724  SplitBlock->Size = (USHORT)FreeSize;
1725  SplitBlock->PreviousSize = (USHORT)Index;
1726 
1727  /* Check if it's the last entry */
1728  if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
1729  {
1730  /* Insert it to the free list if it's the last entry */
1731  RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
1732  Heap->TotalFreeSize += FreeSize;
1733  }
1734  else
1735  {
1736  /* Not so easy - need to update next's previous size too */
1737  SplitBlock2 = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize);
1738 
1739  if (SplitBlock2->Flags & HEAP_ENTRY_BUSY)
1740  {
1741  SplitBlock2->PreviousSize = (USHORT)FreeSize;
1742  RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
1743  Heap->TotalFreeSize += FreeSize;
1744  }
1745  else
1746  {
1747  /* Even more complex - the next entry is free, so we can merge them into one! */
1748  SplitBlock->Flags = SplitBlock2->Flags;
1749 
1750  /* Remove that next entry */
1751  RtlpRemoveFreeBlock(Heap, SplitBlock2, FALSE, FALSE);
1752 
1753  /* Update sizes */
1754  FreeSize += SplitBlock2->Size;
1755  Heap->TotalFreeSize -= SplitBlock2->Size;
1756 
1757  if (FreeSize <= HEAP_MAX_BLOCK_SIZE)
1758  {
1759  /* Insert it back */
1760  SplitBlock->Size = (USHORT)FreeSize;
1761 
1762  /* Don't forget to update previous size of the next entry! */
1763  if (!(SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY))
1764  {
1765  ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize))->PreviousSize = (USHORT)FreeSize;
1766  }
1767 
1768  /* Actually insert it */
1769  RtlpInsertFreeBlockHelper(Heap, SplitBlock, (USHORT)FreeSize, FALSE);
1770 
1771  /* Update total size */
1772  Heap->TotalFreeSize += FreeSize;
1773  }
1774  else
1775  {
1776  /* Resulting block is quite big */
1777  RtlpInsertFreeBlock(Heap, SplitBlock, FreeSize);
1778  }
1779  }
1780  }
1781 
1782  /* Reset flags of the free entry */
1783  FreeFlags = 0;
1784  if (SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY)
1785  {
1786  SegmentOffset = SplitBlock->SegmentOffset;
1787  ASSERT(SegmentOffset < HEAP_SEGMENTS);
1788  Heap->Segments[SegmentOffset]->LastEntryInSegment = SplitBlock;
1789  }
1790  }
1791  }
1792 
1793  /* Set last entry flag */
1794  if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
1795  InUseEntry->Flags |= HEAP_ENTRY_LAST_ENTRY;
1796 
1797  return InUseEntry;
1798 }
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:251
SIZE_T TotalFreeSize
Definition: heap.h:240
#define HEAP_SEGMENTS
Definition: heap.h:16
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:24
#define HEAP_EXTRA_FLAGS_MASK
Definition: heap.h:36
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:254
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FALSE
Definition: types.h:117
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries
Definition: heap.h:259
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:319
Definition: heap.h:130
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
static const UCHAR Index[8]
Definition: usbohci.c:18
#define HEAP_SETTABLE_USER_FLAGS
Definition: nt_native.h:1708
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID NTAPI RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN Dedicated, BOOLEAN NoFill)
Definition: heap.c:383
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
struct _HEAP_ENTRY HEAP_ENTRY
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:319
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42

Referenced by RtlAllocateHeap(), and RtlpAllocateNonDedicated().

◆ RtlpValidateHeap()

BOOLEAN NTAPI RtlpValidateHeap ( PHEAP  Heap,
BOOLEAN  ForceValidation 
)

Definition at line 3469 of file heap.c.

3471 {
3473  BOOLEAN EmptyList;
3474  UCHAR SegmentOffset;
3475  SIZE_T Size, TotalFreeSize;
3476  ULONG PreviousSize;
3477  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock;
3478  PLIST_ENTRY ListHead, NextEntry;
3479  PHEAP_FREE_ENTRY FreeEntry;
3480  ULONG FreeBlocksCount, FreeListEntriesCount;
3481 
3482  /* Check headers */
3483  if (!RtlpValidateHeapHeaders(Heap, FALSE))
3484  return FALSE;
3485 
3486  /* Skip validation if it's not needed */
3487  if (!ForceValidation && !(Heap->Flags & HEAP_VALIDATE_ALL_ENABLED))
3488  return TRUE;
3489 
3490  /* Check free lists bitmaps */
3491  FreeListEntriesCount = 0;
3492  ListHead = &Heap->FreeLists[0];
3493 
3494  for (Size = 0; Size < HEAP_FREELISTS; Size++)
3495  {
3496  if (Size)
3497  {
3498  /* This is a dedicated list. Check if it's empty */
3499  EmptyList = IsListEmpty(ListHead);
3500 
3501  if (Heap->u.FreeListsInUseBytes[Size >> 3] & (1 << (Size & 7)))
3502  {
3503  if (EmptyList)
3504  {
3505  DPRINT1("HEAP: Empty %x-free list marked as non-empty\n", Size);
3506  return FALSE;
3507  }
3508  }
3509  else
3510  {
3511  if (!EmptyList)
3512  {
3513  DPRINT1("HEAP: Non-empty %x-free list marked as empty\n", Size);
3514  return FALSE;
3515  }
3516  }
3517  }
3518 
3519  /* Now check this list entries */
3520  NextEntry = ListHead->Flink;
3521  PreviousSize = 0;
3522 
3523  while (ListHead != NextEntry)
3524  {
3525  FreeEntry = CONTAINING_RECORD(NextEntry, HEAP_FREE_ENTRY, FreeList);
3526  NextEntry = NextEntry->Flink;
3527 
3528  /* If there is an in-use entry in a free list - that's quite a big problem */
3529  if (FreeEntry->Flags & HEAP_ENTRY_BUSY)
3530  {
3531  DPRINT1("HEAP: %Ix-dedicated list free element %p is marked in-use\n", Size, FreeEntry);
3532  return FALSE;
3533  }
3534 
3535  /* Check sizes according to that specific list's size */
3536  if ((Size == 0) && (FreeEntry->Size < HEAP_FREELISTS))
3537  {
3538  DPRINT1("HEAP: Non dedicated list free element %p has size %x which would fit a dedicated list\n", FreeEntry, FreeEntry->Size);
3539  return FALSE;
3540  }
3541  else if (Size && (FreeEntry->Size != Size))
3542  {
3543  DPRINT1("HEAP: %Ix-dedicated list free element %p has incorrect size %x\n", Size, FreeEntry, FreeEntry->Size);
3544  return FALSE;
3545  }
3546  else if ((Size == 0) && (FreeEntry->Size < PreviousSize))
3547  {
3548  DPRINT1("HEAP: Non dedicated list free element %p is not put in order\n", FreeEntry);
3549  return FALSE;
3550  }
3551 
3552  /* Remember previous size*/
3553  PreviousSize = FreeEntry->Size;
3554 
3555  /* Add up to the total amount of free entries */
3556  FreeListEntriesCount++;
3557  }
3558 
3559  /* Go to the head of the next free list */
3560  ListHead++;
3561  }
3562 
3563  /* Check big allocations */
3564  ListHead = &Heap->VirtualAllocdBlocks;
3565  NextEntry = ListHead->Flink;
3566 
3567  while (ListHead != NextEntry)
3568  {
3569  VirtualAllocBlock = CONTAINING_RECORD(NextEntry, HEAP_VIRTUAL_ALLOC_ENTRY, Entry);
3570 
3571  /* We can only check the fill pattern */
3572  if (VirtualAllocBlock->BusyBlock.Flags & HEAP_ENTRY_FILL_PATTERN)
3573  {
3574  if (!RtlpCheckInUsePattern(&VirtualAllocBlock->BusyBlock))
3575  return FALSE;
3576  }
3577 
3578  NextEntry = NextEntry->Flink;
3579  }
3580 
3581  /* Check all segments */
3582  FreeBlocksCount = 0;
3583  TotalFreeSize = 0;
3584 
3585  for (SegmentOffset = 0; SegmentOffset < HEAP_SEGMENTS; SegmentOffset++)
3586  {
3587  Segment = Heap->Segments[SegmentOffset];
3588 
3589  /* Go to the next one if there is no segment */
3590  if (!Segment) continue;
3591 
3592  if (!RtlpValidateHeapSegment(Heap,
3593  Segment,
3594  SegmentOffset,
3595  &FreeBlocksCount,
3596  &TotalFreeSize,
3597  NULL,
3598  NULL))
3599  {
3600  return FALSE;
3601  }
3602  }
3603 
3604  if (FreeListEntriesCount != FreeBlocksCount)
3605  {
3606  DPRINT1("HEAP: Free blocks count in arena (%lu) does not match free blocks number in the free lists (%lu)\n", FreeBlocksCount, FreeListEntriesCount);
3607  return FALSE;
3608  }
3609 
3610  if (Heap->TotalFreeSize != TotalFreeSize)
3611  {
3612  DPRINT1("HEAP: Total size of free blocks in arena (%Iu) does not equal to the one in heap header (%Iu)\n", TotalFreeSize, Heap->TotalFreeSize);
3613  return FALSE;
3614  }
3615 
3616  return TRUE;
3617 }
Definition: heap.h:312
UCHAR FreeListsInUseBytes[HEAP_FREELISTS/(sizeof(UCHAR) *8)]
Definition: heap.h:265
SIZE_T TotalFreeSize
Definition: heap.h:240
#define HEAP_SEGMENTS
Definition: heap.h:16
#define TRUE
Definition: types.h:120
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
BOOLEAN NTAPI RtlpValidateHeapHeaders(PHEAP Heap, BOOLEAN Recalculate)
Definition: heap.c:3216
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:254
#define FALSE
Definition: types.h:117
Definition: heap.h:130
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define HEAP_VALIDATE_ALL_ENABLED
Definition: rtltypes.h:166
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:252
#define HEAP_FREELISTS
Definition: heap.h:15
unsigned char UCHAR
Definition: xmlstorage.h:181
MmuFreePage * FreeList
Definition: mmuobject.c:60
union _HEAP::@4128 u
BOOLEAN NTAPI RtlpCheckInUsePattern(PHEAP_ENTRY HeapEntry)
Definition: heap.c:3186
Definition: typedefs.h:119
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
ULONG_PTR SIZE_T
Definition: typedefs.h:80
ULONG Flags
Definition: heap.h:227
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
HEAP_ENTRY BusyBlock
Definition: heap.h:318
BOOLEAN NTAPI RtlpValidateHeapSegment(PHEAP Heap, PHEAP_SEGMENT Segment, UCHAR SegmentOffset, PULONG FreeEntriesCount, PSIZE_T TotalFreeSize, PSIZE_T TagEntries, PSIZE_T PseudoTagEntries)
Definition: heap.c:3282
base of all file and directory entries
Definition: entries.h:82
LIST_ENTRY FreeLists[HEAP_FREELISTS]
Definition: heap.h:260

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

◆ RtlpValidateHeapEntry()

BOOLEAN NTAPI RtlpValidateHeapEntry ( PHEAP  Heap,
PHEAP_ENTRY  HeapEntry 
)

Definition at line 3225 of file heap.c.

3228 {
3229  BOOLEAN BigAllocation, EntryFound = FALSE;
3231  ULONG SegmentOffset;
3232 
3233  /* Perform various consistency checks of this entry */
3234  if (!HeapEntry) goto invalid_entry;
3235  if ((ULONG_PTR)HeapEntry & (HEAP_ENTRY_SIZE - 1)) goto invalid_entry;
3236  if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY)) goto invalid_entry;
3237 
3238  BigAllocation = HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC;
3239  Segment = Heap->Segments[HeapEntry->SegmentOffset];
3240 
3241  if (BigAllocation &&
3242  (((ULONG_PTR)HeapEntry & (PAGE_SIZE - 1)) != FIELD_OFFSET(HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock)))
3243  goto invalid_entry;
3244 
3245  if (!BigAllocation && (HeapEntry->SegmentOffset >= HEAP_SEGMENTS ||
3246  !Segment ||
3247  HeapEntry < Segment->FirstEntry ||
3248  HeapEntry >= Segment->LastValidEntry))
3249  goto invalid_entry;
3250 
3251  if ((HeapEntry->Flags & HEAP_ENTRY_FILL_PATTERN) &&
3252  !RtlpCheckInUsePattern(HeapEntry))
3253  goto invalid_entry;
3254 
3255  /* Checks are done, if this is a virtual entry, that's all */
3256  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) return TRUE;
3257 
3258  /* Go through segments and check if this entry fits into any of them */
3259  for (SegmentOffset = 0; SegmentOffset < HEAP_SEGMENTS; SegmentOffset++)
3260  {
3261  Segment = Heap->Segments[SegmentOffset];
3262  if (!Segment) continue;
3263 
3264  if ((HeapEntry >= Segment->FirstEntry) &&
3265  (HeapEntry < Segment->LastValidEntry))
3266  {
3267  /* Got it */
3268  EntryFound = TRUE;
3269  break;
3270  }
3271  }
3272 
3273  /* Return our result of finding entry in the segments */
3274  return EntryFound;
3275 
3276 invalid_entry:
3277  DPRINT1("HEAP: Invalid heap entry %p in heap %p\n", HeapEntry, Heap);
3278  return FALSE;
3279 }
Definition: heap.h:312
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:44
#define HEAP_SEGMENTS
Definition: heap.h:16
#define TRUE
Definition: types.h:120
uint32_t ULONG_PTR
Definition: typedefs.h:65
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:254
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define HEAP_ENTRY_SIZE
Definition: heap.h:18
BOOLEAN NTAPI RtlpCheckInUsePattern(PHEAP_ENTRY HeapEntry)
Definition: heap.c:3186
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1

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

◆ RtlpValidateHeapHeaders()

BOOLEAN NTAPI RtlpValidateHeapHeaders ( PHEAP  Heap,
BOOLEAN  Recalculate 
)

Definition at line 3216 of file heap.c.

3219 {
3220  // We skip header validation for now
3221  return TRUE;
3222 }
#define TRUE
Definition: types.h:120

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

◆ RtlpValidateHeapSegment()

BOOLEAN NTAPI RtlpValidateHeapSegment ( PHEAP  Heap,
PHEAP_SEGMENT  Segment,
UCHAR  SegmentOffset,
PULONG  FreeEntriesCount,
PSIZE_T  TotalFreeSize,
PSIZE_T  TagEntries,
PSIZE_T  PseudoTagEntries 
)

Definition at line 3282 of file heap.c.

3290 {
3291  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
3292  PLIST_ENTRY UcrEntry;
3294  PHEAP_ENTRY CurrentEntry;
3295  ULONG UnCommittedPages;
3296  ULONG UnCommittedRanges;
3297  ULONG PreviousSize;
3298 
3299  UnCommittedPages = 0;
3300  UnCommittedRanges = 0;
3301 
3302  if (IsListEmpty(&Segment->UCRSegmentList))
3303  {
3304  UcrEntry = NULL;
3305  UcrDescriptor = NULL;
3306  }
3307  else
3308  {
3309  UcrEntry = Segment->UCRSegmentList.Flink;
3310  UcrDescriptor =