ReactOS  0.4.14-dev-41-g31d7680
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)
 
NTSTATUS NTAPI RtlMultipleAllocateHeap (IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size, IN ULONG Count, OUT PVOID *Array)
 
NTSTATUS NTAPI RtlMultipleFreeHeap (IN PVOID HeapHandle, IN ULONG Flags, IN ULONG Count, OUT PVOID *Array)
 

Variables

UCHAR RtlpBitsClearLow []
 
UCHAR FillPattern [HEAP_ENTRY_SIZE]
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 24 of file heap.c.

Function Documentation

◆ RtlAllocateHeap()

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

Definition at line 1914 of file heap.c.

1917 {
1918  PHEAP Heap = (PHEAP)HeapPtr;
1919  PULONG FreeListsInUse;
1920  ULONG FreeListsInUseUlong;
1922  SIZE_T Index, InUseIndex, i;
1923  PLIST_ENTRY FreeListHead;
1924  PHEAP_ENTRY InUseEntry;
1925  PHEAP_FREE_ENTRY FreeBlock;
1926  UCHAR FreeFlags, EntryFlags = HEAP_ENTRY_BUSY;
1927  EXCEPTION_RECORD ExceptionRecord;
1928  BOOLEAN HeapLocked = FALSE;
1929  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualBlock = NULL;
1930  PHEAP_ENTRY_EXTRA Extra;
1931  NTSTATUS Status;
1932 
1933  /* Force flags */
1934  Flags |= Heap->ForceFlags;
1935 
1936  /* Call special heap */
1937  if (RtlpHeapIsSpecial(Flags))
1938  return RtlDebugAllocateHeap(Heap, Flags, Size);
1939 
1940  /* Check for the maximum size */
1941  if (Size >= 0x80000000)
1942  {
1944  DPRINT1("HEAP: Allocation failed!\n");
1945  return NULL;
1946  }
1947 
1949  {
1950  DPRINT1("HEAP: RtlAllocateHeap is called with unsupported flags %x, ignoring\n", Flags);
1951  }
1952 
1953  //DPRINT("RtlAllocateHeap(%p %x %x)\n", Heap, Flags, Size);
1954 
1955  /* Calculate allocation size and index */
1956  if (Size)
1957  AllocationSize = Size;
1958  else
1959  AllocationSize = 1;
1960  AllocationSize = (AllocationSize + Heap->AlignRound) & Heap->AlignMask;
1961 
1962  /* Add extra flags in case of settable user value feature is requested,
1963  or there is a tag (small or normal) or there is a request to
1964  capture stack backtraces */
1966  Heap->PseudoTagEntries)
1967  {
1968  /* Add flag which means that the entry will have extra stuff attached */
1969  EntryFlags |= HEAP_ENTRY_EXTRA_PRESENT;
1970 
1971  /* Account for extra stuff size */
1972  AllocationSize += sizeof(HEAP_ENTRY_EXTRA);
1973  }
1974 
1975  /* Add settable user flags, if any */
1976  EntryFlags |= (Flags & HEAP_SETTABLE_USER_FLAGS) >> 4;
1977 
1979 
1980  /* Acquire the lock if necessary */
1981  if (!(Flags & HEAP_NO_SERIALIZE))
1982  {
1984  HeapLocked = TRUE;
1985  }
1986 
1987  /* Depending on the size, the allocation is going to be done from dedicated,
1988  non-dedicated lists or a virtual block of memory */
1989  if (Index < HEAP_FREELISTS)
1990  {
1991  FreeListHead = &Heap->FreeLists[Index];
1992 
1993  if (!IsListEmpty(FreeListHead))
1994  {
1995  /* There is a free entry in this list */
1996  FreeBlock = CONTAINING_RECORD(FreeListHead->Blink,
1998  FreeList);
1999 
2000  /* Save flags and remove the free entry */
2001  FreeFlags = FreeBlock->Flags;
2002  RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, FALSE);
2003 
2004  /* Update the total free size of the heap */
2005  Heap->TotalFreeSize -= Index;
2006 
2007  /* Initialize this block */
2008  InUseEntry = (PHEAP_ENTRY)FreeBlock;
2009  InUseEntry->Flags = EntryFlags | (FreeFlags & HEAP_ENTRY_LAST_ENTRY);
2010  InUseEntry->UnusedBytes = (UCHAR)(AllocationSize - Size);
2011  InUseEntry->SmallTagIndex = 0;
2012  }
2013  else
2014  {
2015  /* Find smallest free block which this request could fit in */
2016  InUseIndex = Index >> 5;
2017  FreeListsInUse = &Heap->u.FreeListsInUseUlong[InUseIndex];
2018 
2019  /* This bit magic disables all sizes which are less than the requested allocation size */
2020  FreeListsInUseUlong = *FreeListsInUse++ & ~((1 << ((ULONG)Index & 0x1f)) - 1);
2021 
2022  /* If size is definitily more than our lists - go directly to the non-dedicated one */
2023  if (InUseIndex > 3)
2024  return RtlpAllocateNonDedicated(Heap, Flags, Size, AllocationSize, Index, HeapLocked);
2025 
2026  /* Go through the list */
2027  for (i = InUseIndex; i < 4; i++)
2028  {
2029  if (FreeListsInUseUlong)
2030  {
2031  FreeListHead = &Heap->FreeLists[i * 32];
2032  break;
2033  }
2034 
2035  if (i < 3) FreeListsInUseUlong = *FreeListsInUse++;
2036  }
2037 
2038  /* Nothing found, search in the non-dedicated list */
2039  if (i == 4)
2040  return RtlpAllocateNonDedicated(Heap, Flags, Size, AllocationSize, Index, HeapLocked);
2041 
2042  /* That list is found, now calculate exact block */
2043  FreeListHead += RtlpFindLeastSetBit(FreeListsInUseUlong);
2044 
2045  /* Take this entry and remove it from the list of free blocks */
2046  FreeBlock = CONTAINING_RECORD(FreeListHead->Blink,
2048  FreeList);
2049  RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE, FALSE);
2050 
2051  /* Split it */
2052  InUseEntry = RtlpSplitEntry(Heap, Flags, FreeBlock, AllocationSize, Index, Size);
2053  }
2054 
2055  /* Release the lock */
2056  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2057 
2058  /* Zero memory if that was requested */
2059  if (Flags & HEAP_ZERO_MEMORY)
2060  RtlZeroMemory(InUseEntry + 1, Size);
2061  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
2062  {
2063  /* Fill this block with a special pattern */
2064  RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
2065  }
2066 
2067  /* Fill tail of the block with a special pattern too if requested */
2068  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
2069  {
2070  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY), HEAP_TAIL_FILL);
2071  InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
2072  }
2073 
2074  /* Prepare extra if it's present */
2075  if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
2076  {
2077  Extra = RtlpGetExtraStuffPointer(InUseEntry);
2078  RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
2079 
2080  // TODO: Tagging
2081  }
2082 
2083  /* User data starts right after the entry's header */
2084  return InUseEntry + 1;
2085  }
2086  else if (Index <= Heap->VirtualMemoryThreshold)
2087  {
2088  /* The block is too large for dedicated lists, but fine for a non-dedicated one */
2089  return RtlpAllocateNonDedicated(Heap, Flags, Size, AllocationSize, Index, HeapLocked);
2090  }
2091  else if (Heap->Flags & HEAP_GROWABLE)
2092  {
2093  /* We've got a very big allocation request, satisfy it by directly allocating virtual memory */
2094  AllocationSize += sizeof(HEAP_VIRTUAL_ALLOC_ENTRY) - sizeof(HEAP_ENTRY);
2095 
2096  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
2097  (PVOID *)&VirtualBlock,
2098  0,
2099  &AllocationSize,
2100  MEM_COMMIT,
2101  PAGE_READWRITE);
2102 
2103  if (!NT_SUCCESS(Status))
2104  {
2105  // Set STATUS!
2106  /* Release the lock */
2107  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2108  DPRINT1("HEAP: Allocation failed!\n");
2109  return NULL;
2110  }
2111 
2112  /* Initialize the newly allocated block */
2113  VirtualBlock->BusyBlock.Size = (USHORT)(AllocationSize - Size);
2114  ASSERT(VirtualBlock->BusyBlock.Size >= sizeof(HEAP_VIRTUAL_ALLOC_ENTRY));
2115  VirtualBlock->BusyBlock.Flags = EntryFlags | HEAP_ENTRY_VIRTUAL_ALLOC | HEAP_ENTRY_EXTRA_PRESENT;
2116  VirtualBlock->CommitSize = AllocationSize;
2117  VirtualBlock->ReserveSize = AllocationSize;
2118 
2119  /* Insert it into the list of virtual allocations */
2120  InsertTailList(&Heap->VirtualAllocdBlocks, &VirtualBlock->Entry);
2121 
2122  /* Release the lock */
2123  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2124 
2125  /* Return pointer to user data */
2126  return VirtualBlock + 1;
2127  }
2128 
2129  /* Generate an exception */
2131  {
2132  ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY;
2133  ExceptionRecord.ExceptionRecord = NULL;
2134  ExceptionRecord.NumberParameters = 1;
2135  ExceptionRecord.ExceptionFlags = 0;
2136  ExceptionRecord.ExceptionInformation[0] = AllocationSize;
2137 
2138  RtlRaiseException(&ExceptionRecord);
2139  }
2140 
2142 
2143  /* Release the lock */
2144  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2145  DPRINT1("HEAP: Allocation failed!\n");
2146  return NULL;
2147 }
signed char * PCHAR
Definition: retypes.h:7
LIST_ENTRY Entry
Definition: heap.h:323
#define ARENA_INUSE_FILLER
Definition: oleaut.c:108
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
Definition: heap.h:321
#define TRUE
Definition: types.h:120
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:44
SIZE_T TotalFreeSize
Definition: heap.h:236
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
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:2526
_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:260
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
#define HEAP_CREATE_ENABLE_TRACING
Definition: nt_native.h:1702
DWORD ExceptionCode
Definition: compat.h:196
_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:247
SIZE_T ReserveSize
Definition: heap.h:326
Definition: heap.h:305
PHEAP_LOCK LockVariable
Definition: heap.h:263
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries
Definition: heap.h:255
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:201
SIZE_T CommitSize
Definition: heap.h:325
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
union _HEAP::@4000 u
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:248
#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:52
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:382
#define HEAP_FREELISTS
Definition: heap.h:15
unsigned char UCHAR
Definition: xmlstorage.h:181
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:1628
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:198
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:310
ULONG_PTR SIZE_T
Definition: typedefs.h:78
ULONG_PTR AlignRound
Definition: heap.h:246
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
ULONG Flags
Definition: heap.h:223
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
struct _HEAP_ENTRY_EXTRA HEAP_ENTRY_EXTRA
unsigned int * PULONG
Definition: retypes.h:1
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#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:1761
#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:261
DWORD ExceptionFlags
Definition: compat.h:197
ULONG ForceFlags
Definition: heap.h:224
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42
HEAP_ENTRY BusyBlock
Definition: heap.h:327
DWORD NumberParameters
Definition: compat.h:200
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
LIST_ENTRY FreeLists[HEAP_FREELISTS]
Definition: heap.h:256
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 2968 of file heap.c.

2970 {
2971  UNIMPLEMENTED;
2972  return 0;
2973 }
#define UNIMPLEMENTED
Definition: debug.h:114

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 1221 of file heap.c.

1227 {
1228  PVOID CommittedAddress = NULL, UncommittedAddress = NULL;
1229  PHEAP Heap = NULL;
1230  RTL_HEAP_PARAMETERS SafeParams = {0};
1231  ULONG_PTR MaximumUserModeAddress;
1232  SYSTEM_BASIC_INFORMATION SystemInformation;
1233  MEMORY_BASIC_INFORMATION MemoryInfo;
1234  ULONG NtGlobalFlags = RtlGetNtGlobalFlags();
1235  ULONG HeapSegmentFlags = 0;
1236  NTSTATUS Status;
1237  ULONG MaxBlockSize;
1238 
1239  /* Check for a special heap */
1240  if (RtlpPageHeapEnabled && !Addr && !Lock)
1241  {
1242  Heap = RtlpPageHeapCreate(Flags, Addr, TotalSize, CommitSize, Lock, Parameters);
1243  if (Heap) return Heap;
1244 
1245  /* Reset a special Parameters == -1 hack */
1246  if ((ULONG_PTR)Parameters == (ULONG_PTR)-1)
1247  Parameters = NULL;
1248  else
1249  DPRINT1("Enabling page heap failed\n");
1250  }
1251 
1252  /* Check validation flags */
1254  {
1255  DPRINT1("Invalid flags 0x%08x, fixing...\n", Flags);
1257  }
1258 
1259  /* Capture parameters */
1260  if (Parameters)
1261  {
1262  _SEH2_TRY
1263  {
1264  /* If size of structure correct, then copy it */
1265  if (Parameters->Length == sizeof(RTL_HEAP_PARAMETERS))
1266  RtlCopyMemory(&SafeParams, Parameters, sizeof(RTL_HEAP_PARAMETERS));
1267  }
1269  {
1270  _SEH2_YIELD(return NULL);
1271  }
1272  _SEH2_END;
1273  }
1274 
1275  Parameters = &SafeParams;
1276 
1277  /* Check global flags */
1278  if (NtGlobalFlags & FLG_HEAP_DISABLE_COALESCING)
1280 
1281  if (NtGlobalFlags & FLG_HEAP_ENABLE_FREE_CHECK)
1283 
1284  if (NtGlobalFlags & FLG_HEAP_ENABLE_TAIL_CHECK)
1286 
1287  if (RtlpGetMode() == UserMode)
1288  {
1289  /* Also check these flags if in usermode */
1290  if (NtGlobalFlags & FLG_HEAP_VALIDATE_ALL)
1292 
1293  if (NtGlobalFlags & FLG_HEAP_VALIDATE_PARAMETERS)
1295 
1296  if (NtGlobalFlags & FLG_USER_STACK_TRACE_DB)
1298  }
1299 
1300  /* Set tunable parameters */
1302 
1303  /* Get the max um address */
1305  &SystemInformation,
1306  sizeof(SystemInformation),
1307  NULL);
1308 
1309  if (!NT_SUCCESS(Status))
1310  {
1311  DPRINT1("Getting max usermode address failed with status 0x%08x\n", Status);
1312  return NULL;
1313  }
1314 
1315  MaximumUserModeAddress = SystemInformation.MaximumUserModeAddress;
1316 
1317  /* Calculate max alloc size */
1318  if (!Parameters->MaximumAllocationSize)
1319  Parameters->MaximumAllocationSize = MaximumUserModeAddress - (ULONG_PTR)0x10000 - PAGE_SIZE;
1320 
1321  MaxBlockSize = 0x80000 - PAGE_SIZE;
1322 
1323  if (!Parameters->VirtualMemoryThreshold ||
1324  Parameters->VirtualMemoryThreshold > MaxBlockSize)
1325  {
1326  Parameters->VirtualMemoryThreshold = MaxBlockSize;
1327  }
1328 
1329  /* Check reserve/commit sizes and set default values */
1330  if (!CommitSize)
1331  {
1333  if (TotalSize)
1334  TotalSize = ROUND_UP(TotalSize, PAGE_SIZE);
1335  else
1336  TotalSize = 64 * PAGE_SIZE;
1337  }
1338  else
1339  {
1340  /* Round up the commit size to be at least the page size */
1342 
1343  if (TotalSize)
1344  TotalSize = ROUND_UP(TotalSize, PAGE_SIZE);
1345  else
1346  TotalSize = ROUND_UP(CommitSize, 16 * PAGE_SIZE);
1347  }
1348 
1349  /* Call special heap */
1350  if (RtlpHeapIsSpecial(Flags))
1351  return RtlDebugCreateHeap(Flags, Addr, TotalSize, CommitSize, Lock, Parameters);
1352 
1353  /* Without serialization, a lock makes no sense */
1354  if ((Flags & HEAP_NO_SERIALIZE) && (Lock != NULL))
1355  return NULL;
1356 
1357  /* See if we are already provided with an address for the heap */
1358  if (Addr)
1359  {
1360  if (Parameters->CommitRoutine)
1361  {
1362  /* There is a commit routine, so no problem here, check params */
1363  if ((Flags & HEAP_GROWABLE) ||
1364  !Parameters->InitialCommit ||
1365  !Parameters->InitialReserve ||
1366  (Parameters->InitialCommit > Parameters->InitialReserve))
1367  {
1368  /* Fail */
1369  return NULL;
1370  }
1371 
1372  /* Calculate committed and uncommitted addresses */
1373  CommittedAddress = Addr;
1374  UncommittedAddress = (PCHAR)Addr + Parameters->InitialCommit;
1375  TotalSize = Parameters->InitialReserve;
1376 
1377  /* Zero the initial page ourselves */
1378  RtlZeroMemory(CommittedAddress, PAGE_SIZE);
1379  }
1380  else
1381  {
1382  /* Commit routine is absent, so query how much memory caller reserved */
1384  Addr,
1386  &MemoryInfo,
1387  sizeof(MemoryInfo),
1388  NULL);
1389 
1390  if (!NT_SUCCESS(Status))
1391  {
1392  DPRINT1("Querying amount of user supplied memory failed with status 0x%08X\n", Status);
1393  return NULL;
1394  }
1395 
1396  /* Validate it */
1397  if (MemoryInfo.BaseAddress != Addr ||
1398  MemoryInfo.State == MEM_FREE)
1399  {
1400  return NULL;
1401  }
1402 
1403  /* Validation checks passed, set committed/uncommitted addresses */
1404  CommittedAddress = Addr;
1405 
1406  /* Check if it's committed or not */
1407  if (MemoryInfo.State == MEM_COMMIT)
1408  {
1409  /* Zero it out because it's already committed */
1410  RtlZeroMemory(CommittedAddress, PAGE_SIZE);
1411 
1412  /* Calculate uncommitted address value */
1413  CommitSize = MemoryInfo.RegionSize;
1414  TotalSize = CommitSize;
1415  UncommittedAddress = (PCHAR)Addr + CommitSize;
1416 
1417  /* Check if uncommitted address is reserved */
1419  UncommittedAddress,
1421  &MemoryInfo,
1422  sizeof(MemoryInfo),
1423  NULL);
1424 
1425  if (NT_SUCCESS(Status) &&
1426  MemoryInfo.State == MEM_RESERVE)
1427  {
1428  /* It is, so add it up to the reserve size */
1429  TotalSize += MemoryInfo.RegionSize;
1430  }
1431  }
1432  else
1433  {
1434  /* It's not committed, inform following code that a commit is necessary */
1436  UncommittedAddress = Addr;
1437  }
1438  }
1439 
1440  /* Mark this as a user-committed mem */
1441  HeapSegmentFlags = HEAP_USER_ALLOCATED;
1442  Heap = (PHEAP)Addr;
1443  }
1444  else
1445  {
1446  /* Check commit routine */
1447  if (Parameters->CommitRoutine) return NULL;
1448 
1449  /* Reserve memory */
1450  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1451  (PVOID *)&Heap,
1452  0,
1453  &TotalSize,
1454  MEM_RESERVE,
1455  PAGE_READWRITE);
1456 
1457  if (!NT_SUCCESS(Status))
1458  {
1459  DPRINT1("Failed to reserve memory with status 0x%08x\n", Status);
1460  return NULL;
1461  }
1462 
1463  /* Set base addresses */
1464  CommittedAddress = Heap;
1465  UncommittedAddress = Heap;
1466  }
1467 
1468  /* Check if we need to commit something */
1469  if (CommittedAddress == UncommittedAddress)
1470  {
1471  /* Commit the required size */
1472  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1473  &CommittedAddress,
1474  0,
1475  &CommitSize,
1476  MEM_COMMIT,
1477  PAGE_READWRITE);
1478 
1479  DPRINT("Committed %Iu bytes at base %p\n", CommitSize, CommittedAddress);
1480 
1481  if (!NT_SUCCESS(Status))
1482  {
1483  DPRINT1("Failure, Status 0x%08X\n", Status);
1484 
1485  /* Release memory if it was reserved */
1486  if (!Addr) ZwFreeVirtualMemory(NtCurrentProcess(),
1487  (PVOID *)&Heap,
1488  &TotalSize,
1489  MEM_RELEASE);
1490 
1491  return NULL;
1492  }
1493 
1494  /* Calculate new uncommitted address */
1495  UncommittedAddress = (PCHAR)UncommittedAddress + CommitSize;
1496  }
1497 
1498  /* Initialize the heap */
1500  if (!NT_SUCCESS(Status))
1501  {
1502  DPRINT1("Failed to initialize heap (%x)\n", Status);
1503  return NULL;
1504  }
1505 
1506  /* Initialize heap's first segment */
1507  Status = RtlpInitializeHeapSegment(Heap, (PHEAP_SEGMENT) (Heap), 0, HeapSegmentFlags, TotalSize, CommitSize);
1508  if (!NT_SUCCESS(Status))
1509  {
1510  DPRINT1("Failed to initialize heap segment (%x)\n", Status);
1511  return NULL;
1512  }
1513 
1514  DPRINT("Created heap %p, CommitSize %x, ReserveSize %x\n", Heap, CommitSize, TotalSize);
1515 
1516  /* Add heap to process list in case of usermode heap */
1517  if (RtlpGetMode() == UserMode)
1518  {
1520 
1521  // FIXME: What about lookasides?
1522  }
1523 
1524  return Heap;
1525 }
#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:4250
uint32_t ULONG_PTR
Definition: typedefs.h:63
#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:86
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:872
#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
Status
Definition: gdiplustypes.h:24
_SEH2_END
Definition: create.c:4424
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:875
#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:261
#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 3884 of file heap.c.

3888 {
3889  /* TODO */
3890  UNIMPLEMENTED;
3891  return 0;
3892 }
#define UNIMPLEMENTED
Definition: debug.h:114

Referenced by HeapCreateTagsW(), and SmpInit().

◆ RtlDestroyHeap()

HANDLE NTAPI RtlDestroyHeap ( HANDLE  HeapPtr)

Definition at line 1540 of file heap.c.

1541 {
1542  PHEAP Heap = (PHEAP)HeapPtr;
1543  PLIST_ENTRY Current;
1544  PHEAP_UCR_SEGMENT UcrSegment;
1545  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
1547  SIZE_T Size;
1548  LONG i;
1550 
1551  if (!HeapPtr) return NULL;
1552 
1553  /* Call page heap routine if required */
1554  if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS) return RtlpPageHeapDestroy(HeapPtr);
1555 
1556  /* Call special heap */
1557  if (RtlpHeapIsSpecial(Heap->Flags))
1558  {
1559  if (!RtlDebugDestroyHeap(Heap)) return HeapPtr;
1560  }
1561 
1562  /* Check for a process heap */
1563  if (RtlpGetMode() == UserMode &&
1564  HeapPtr == NtCurrentPeb()->ProcessHeap) return HeapPtr;
1565 
1566  /* Free up all big allocations */
1567  Current = Heap->VirtualAllocdBlocks.Flink;
1568  while (Current != &Heap->VirtualAllocdBlocks)
1569  {
1570  VirtualEntry = CONTAINING_RECORD(Current, HEAP_VIRTUAL_ALLOC_ENTRY, Entry);
1571  BaseAddress = (PVOID)VirtualEntry;
1572  Current = Current->Flink;
1573  Size = 0;
1574  ZwFreeVirtualMemory(NtCurrentProcess(),
1575  &BaseAddress,
1576  &Size,
1577  MEM_RELEASE);
1578  }
1579 
1580  /* Delete tags and remove heap from the process heaps list in user mode */
1581  if (RtlpGetMode() == UserMode)
1582  {
1583  // FIXME DestroyTags
1585  }
1586 
1587  /* Delete the heap lock */
1588  if (!(Heap->Flags & HEAP_NO_SERIALIZE))
1589  {
1590  /* Delete it if it wasn't user allocated */
1591  if (!(Heap->Flags & HEAP_LOCK_USER_ALLOCATED))
1593 
1594  /* Clear out the lock variable */
1595  Heap->LockVariable = NULL;
1596  }
1597 
1598  /* Free UCR segments if any were created */
1599  Current = Heap->UCRSegments.Flink;
1600  while (Current != &Heap->UCRSegments)
1601  {
1602  UcrSegment = CONTAINING_RECORD(Current, HEAP_UCR_SEGMENT, ListEntry);
1603 
1604  /* Advance to the next descriptor */
1605  Current = Current->Flink;
1606 
1607  BaseAddress = (PVOID)UcrSegment;
1608  Size = 0;
1609 
1610  /* Release that memory */
1611  ZwFreeVirtualMemory(NtCurrentProcess(),
1612  &BaseAddress,
1613  &Size,
1614  MEM_RELEASE);
1615  }
1616 
1617  /* Go through segments and destroy them */
1618  for (i = HEAP_SEGMENTS - 1; i >= 0; i--)
1619  {
1620  Segment = Heap->Segments[i];
1622  }
1623 
1624  return NULL;
1625 }
Definition: heap.h:321
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:250
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:263
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:893
#define NtCurrentProcess()
Definition: nt_native.h:1657
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
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:245
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:248
#define HEAP_LOCK_USER_ALLOCATED
Definition: rtltypes.h:168
Definition: typedefs.h:117
#define HEAP_FLAG_PAGE_ALLOCS
Definition: rtltypes.h:160
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
HANDLE ProcessHeap
Definition: servman.c:15
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define NtCurrentPeb()
Definition: FLS.c:20
ULONG Flags
Definition: heap.h:223
#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:224
VOID NTAPI RtlpDestroyHeapSegment(PHEAP_SEGMENT Segment)
Definition: heap.c:948
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 3615 of file heap.c.

3617 {
3618  UNIMPLEMENTED;
3619  return STATUS_NOT_IMPLEMENTED;
3620 }
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlExtendHeap()

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

Definition at line 3872 of file heap.c.

3876 {
3877  /* TODO */
3878  UNIMPLEMENTED;
3879  return 0;
3880 }
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlFreeHeap()

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

Definition at line 2158 of file heap.c.

2163 {
2164  PHEAP Heap;
2165  PHEAP_ENTRY HeapEntry;
2166  USHORT TagIndex = 0;
2167  SIZE_T BlockSize;
2168  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
2169  BOOLEAN Locked = FALSE;
2170  NTSTATUS Status;
2171 
2172  /* Freeing NULL pointer is a legal operation */
2173  if (!Ptr) return TRUE;
2174 
2175  /* Get pointer to the heap and force flags */
2176  Heap = (PHEAP)HeapPtr;
2177  Flags |= Heap->ForceFlags;
2178 
2179  /* Call special heap */
2180  if (RtlpHeapIsSpecial(Flags))
2181  return RtlDebugFreeHeap(Heap, Flags, Ptr);
2182 
2183  /* Get pointer to the heap entry */
2184  HeapEntry = (PHEAP_ENTRY)Ptr - 1;
2185 
2186  /* Protect with SEH in case the pointer is not valid */
2187  _SEH2_TRY
2188  {
2189  /* Check this entry, fail if it's invalid */
2190  if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY) ||
2191  (((ULONG_PTR)Ptr & 0x7) != 0) ||
2192  (HeapEntry->SegmentOffset >= HEAP_SEGMENTS))
2193  {
2194  /* This is an invalid block */
2195  DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
2197  _SEH2_YIELD(return FALSE);
2198  }
2199  }
2201  {
2202  /* The pointer was invalid */
2203  DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
2205  _SEH2_YIELD(return FALSE);
2206  }
2207  _SEH2_END;
2208 
2209  /* Lock if necessary */
2210  if (!(Flags & HEAP_NO_SERIALIZE))
2211  {
2213  Locked = TRUE;
2214  }
2215 
2216  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
2217  {
2218  /* Big allocation */
2219  VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
2220 
2221  /* Remove it from the list */
2222  RemoveEntryList(&VirtualEntry->Entry);
2223 
2224  // TODO: Tagging
2225 
2226  BlockSize = 0;
2227  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
2228  (PVOID *)&VirtualEntry,
2229  &BlockSize,
2230  MEM_RELEASE);
2231 
2232  if (!NT_SUCCESS(Status))
2233  {
2234  DPRINT1("HEAP: Failed releasing memory with Status 0x%08X. Heap %p, ptr %p, base address %p\n",
2235  Status, Heap, Ptr, VirtualEntry);
2237  }
2238  }
2239  else
2240  {
2241  /* Normal allocation */
2242  BlockSize = HeapEntry->Size;
2243 
2244  // TODO: Tagging
2245 
2246  /* Coalesce in kernel mode, and in usermode if it's not disabled */
2247  if (RtlpGetMode() == KernelMode ||
2249  {
2250  HeapEntry = (PHEAP_ENTRY)RtlpCoalesceFreeBlocks(Heap,
2251  (PHEAP_FREE_ENTRY)HeapEntry,
2252  &BlockSize,
2253  FALSE);
2254  }
2255 
2256  /* If there is no need to decommit the block - put it into a free list */
2257  if (BlockSize < Heap->DeCommitFreeBlockThreshold ||
2258  (Heap->TotalFreeSize + BlockSize < Heap->DeCommitTotalFreeThreshold))
2259  {
2260  /* Check if it needs to go to a 0 list */
2261  if (BlockSize > HEAP_MAX_BLOCK_SIZE)
2262  {
2263  /* General-purpose 0 list */
2264  RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY)HeapEntry, BlockSize);
2265  }
2266  else
2267  {
2268  /* Usual free list */
2269  RtlpInsertFreeBlockHelper(Heap, (PHEAP_FREE_ENTRY)HeapEntry, BlockSize, FALSE);
2270 
2271  /* Assert sizes are consistent */
2272  if (!(HeapEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
2273  {
2274  ASSERT((HeapEntry + BlockSize)->PreviousSize == BlockSize);
2275  }
2276 
2277  /* Increase the free size */
2278  Heap->TotalFreeSize += BlockSize;
2279  }
2280 
2281 
2282  if (RtlpGetMode() == UserMode &&
2283  TagIndex != 0)
2284  {
2285  // FIXME: Tagging
2286  UNIMPLEMENTED;
2287  }
2288  }
2289  else
2290  {
2291  /* Decommit this block */
2292  RtlpDeCommitFreeBlock(Heap, (PHEAP_FREE_ENTRY)HeapEntry, BlockSize);
2293  }
2294  }
2295 
2296  /* Release the heap lock */
2297  if (Locked) RtlLeaveHeapLock(Heap->LockVariable);
2298 
2299  return TRUE;
2300 }
LIST_ENTRY Entry
Definition: heap.h:323
Definition: heap.h:321
#define TRUE
Definition: types.h:120
#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:250
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
SIZE_T TotalFreeSize
Definition: heap.h:236
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceFreeBlocks(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, PSIZE_T FreeSize, BOOLEAN Remove)
Definition: heap.c:980
#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:737
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#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:4250
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:260
PHEAP_LOCK LockVariable
Definition: heap.h:263
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:318
#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)
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:78
_SEH2_END
Definition: create.c:4424
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
ULONG Flags
Definition: heap.h:223
#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:114
#define ULONG_PTR
Definition: config.h:101
ULONG ForceFlags
Definition: heap.h:224
#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 3627 of file heap.c.

3629 {
3630  UNIMPLEMENTED;
3631  return 0;
3632 }
#define UNIMPLEMENTED
Definition: debug.h:114

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 3781 of file heap.c.

3786 {
3787  PHEAP Heap = (PHEAP)HeapHandle;
3788  PHEAP_ENTRY HeapEntry;
3789  PHEAP_ENTRY_EXTRA Extra;
3790  BOOLEAN HeapLocked = FALSE;
3791 
3792  /* Force flags */
3793  Flags |= Heap->Flags;
3794 
3795  /* Call special heap */
3796  if (RtlpHeapIsSpecial(Flags))
3797  return RtlDebugGetUserInfoHeap(Heap, Flags, BaseAddress, UserValue, UserFlags);
3798 
3799  /* Lock if it's lockable */
3800  if (!(Heap->Flags & HEAP_NO_SERIALIZE))
3801  {
3803  HeapLocked = TRUE;
3804  }
3805 
3806  /* Get a pointer to the entry */
3807  HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
3808 
3809  /* If it's a free entry - return error */
3810  if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
3811  {
3813 
3814  /* Release the heap lock if it was acquired */
3815  if (HeapLocked)
3817 
3818  return FALSE;
3819  }
3820 
3821  /* Check if this entry has an extra stuff associated with it */
3822  if (HeapEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
3823  {
3824  /* Get pointer to extra data */
3825  Extra = RtlpGetExtraStuffPointer(HeapEntry);
3826 
3827  /* Pass user value */
3828  if (UserValue)
3829  *UserValue = (PVOID)Extra->Settable;
3830  }
3831 
3832  /* Decode and return user flags */
3833  if (UserFlags)
3834  *UserFlags = (HeapEntry->Flags & HEAP_ENTRY_SETTABLE_FLAGS) << 4;
3835 
3836  /* Release the heap lock if it was acquired */
3837  if (HeapLocked)
3839 
3840  return TRUE;
3841 }
ULONG_PTR Settable
Definition: heap.h:313
#define HEAP_ENTRY_SETTABLE_FLAGS
Definition: heap.h:49
#define TRUE
Definition: types.h:120
#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 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:2526
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
Definition: heap.h:305
PHEAP_LOCK LockVariable
Definition: heap.h:263
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
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
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:223
struct _HEAP * PHEAP
#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 2990 of file heap.c.

2991 {
2992  PHEAP Heap = (PHEAP)HeapPtr;
2993 
2994  /* Check for page heap */
2995  if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
2996  {
2997  return RtlpPageHeapLock(Heap);
2998  }
2999 
3000  /* Check if it's really a heap */
3001  if (Heap->Signature != HEAP_SIGNATURE) return FALSE;
3002 
3003  /* Lock if it's lockable */
3004  if (!(Heap->Flags & HEAP_NO_SERIALIZE))
3005  {
3007  }
3008 
3009  return TRUE;
3010 }
#define TRUE
Definition: types.h:120
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
ULONG Signature
Definition: heap.h:231
BOOLEAN NTAPI RtlpPageHeapLock(HANDLE HeapPtr)
Definition: heappage.c:2354
PHEAP_LOCK LockVariable
Definition: heap.h:263
#define HEAP_FLAG_PAGE_ALLOCS
Definition: rtltypes.h:160
ULONG Flags
Definition: heap.h:223
#define HEAP_SIGNATURE
Definition: heap.h:52
struct _HEAP * PHEAP
ULONG ForceFlags
Definition: heap.h:224
Definition: heap.c:51

◆ RtlMultipleAllocateHeap()

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

Definition at line 3977 of file heap.c.

3982 {
3983  UNIMPLEMENTED;
3984  return 0;
3985 }
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlMultipleFreeHeap()

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

Definition at line 3989 of file heap.c.

3993 {
3994  UNIMPLEMENTED;
3995  return 0;
3996 }
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlpAllocateNonDedicated()

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

Definition at line 1761 of file heap.c.

1767 {
1768  PLIST_ENTRY FreeListHead, Next;
1769  PHEAP_FREE_ENTRY FreeBlock;
1770  PHEAP_ENTRY InUseEntry;
1771  PHEAP_ENTRY_EXTRA Extra;
1772  EXCEPTION_RECORD ExceptionRecord;
1773 
1774  /* Go through the zero list to find a place where to insert the new entry */
1775  FreeListHead = &Heap->FreeLists[0];
1776 
1777  /* Start from the largest block to reduce time */
1778  Next = FreeListHead->Blink;
1779  if (FreeListHead != Next)
1780  {
1781  FreeBlock = CONTAINING_RECORD(Next, HEAP_FREE_ENTRY, FreeList);
1782 
1783  if (FreeBlock->Size >= Index)
1784  {
1785  /* Our request is smaller than the largest entry in the zero list */
1786 
1787  /* Go through the list to find insertion place */
1788  Next = FreeListHead->Flink;
1789  while (FreeListHead != Next)
1790  {
1791  FreeBlock = CONTAINING_RECORD(Next, HEAP_FREE_ENTRY, FreeList);
1792 
1793  if (FreeBlock->Size >= Index)
1794  {
1795  /* Found minimally fitting entry. Proceed to either using it as it is
1796  or splitting it to two entries */
1797  RemoveEntryList(&FreeBlock->FreeList);
1798 
1799  /* Split it */
1800  InUseEntry = RtlpSplitEntry(Heap, Flags, FreeBlock, AllocationSize, Index, Size);
1801 
1802  /* Release the lock */
1803  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
1804 
1805  /* Zero memory if that was requested */
1806  if (Flags & HEAP_ZERO_MEMORY)
1807  RtlZeroMemory(InUseEntry + 1, Size);
1808  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
1809  {
1810  /* Fill this block with a special pattern */
1811  RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
1812  }
1813 
1814  /* Fill tail of the block with a special pattern too if requested */
1815  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
1816  {
1817  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY), HEAP_TAIL_FILL);
1818  InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
1819  }
1820 
1821  /* Prepare extra if it's present */
1822  if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
1823  {
1824  Extra = RtlpGetExtraStuffPointer(InUseEntry);
1825  RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
1826 
1827  // TODO: Tagging
1828  }
1829 
1830  /* Return pointer to the */
1831  return InUseEntry + 1;
1832  }
1833 
1834  /* Advance to the next entry */
1835  Next = Next->Flink;
1836  }
1837  }
1838  }
1839 
1840  /* Extend the heap, 0 list didn't have anything suitable */
1841  FreeBlock = RtlpExtendHeap(Heap, AllocationSize);
1842 
1843  /* Use the new biggest entry we've got */
1844  if (FreeBlock)
1845  {
1846  RemoveEntryList(&FreeBlock->FreeList);
1847 
1848  /* Split it */
1849  InUseEntry = RtlpSplitEntry(Heap, Flags, FreeBlock, AllocationSize, Index, Size);
1850 
1851  /* Release the lock */
1852  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
1853 
1854  /* Zero memory if that was requested */
1855  if (Flags & HEAP_ZERO_MEMORY)
1856  RtlZeroMemory(InUseEntry + 1, Size);
1857  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
1858  {
1859  /* Fill this block with a special pattern */
1860  RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
1861  }
1862 
1863  /* Fill tail of the block with a special pattern too if requested */
1864  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
1865  {
1866  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY), HEAP_TAIL_FILL);
1867  InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
1868  }
1869 
1870  /* Prepare extra if it's present */
1871  if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
1872  {
1873  Extra = RtlpGetExtraStuffPointer(InUseEntry);
1874  RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
1875 
1876  // TODO: Tagging
1877  }
1878 
1879  /* Return pointer to the */
1880  return InUseEntry + 1;
1881  }
1882 
1883  /* Really unfortunate, out of memory condition */
1885 
1886  /* Generate an exception */
1888  {
1889  ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY;
1890  ExceptionRecord.ExceptionRecord = NULL;
1891  ExceptionRecord.NumberParameters = 1;
1892  ExceptionRecord.ExceptionFlags = 0;
1893  ExceptionRecord.ExceptionInformation[0] = AllocationSize;
1894 
1895  RtlRaiseException(&ExceptionRecord);
1896  }
1897 
1898  /* Release the lock */
1899  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
1900  DPRINT1("HEAP: Allocation failed!\n");
1901  DPRINT1("Flags %x\n", Heap->Flags);
1902  return NULL;
1903 }
signed char * PCHAR
Definition: retypes.h:7
#define ARENA_INUSE_FILLER
Definition: oleaut.c:108
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
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:2526
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
DWORD ExceptionCode
Definition: compat.h:196
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
Definition: heap.h:305
PHEAP_LOCK LockVariable
Definition: heap.h:263
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:119
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:201
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:1628
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:198
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:310
Definition: heap.h:136
ULONG Flags
Definition: heap.h:223
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#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:1065
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
DWORD ExceptionFlags
Definition: compat.h:197
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42
DWORD NumberParameters
Definition: compat.h:200
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
LIST_ENTRY FreeLists[HEAP_FREELISTS]
Definition: heap.h:256

Referenced by RtlAllocateHeap().

◆ RtlpCheckInUsePattern()

BOOLEAN NTAPI RtlpCheckInUsePattern ( PHEAP_ENTRY  HeapEntry)

Definition at line 3114 of file heap.c.

3115 {
3116  SIZE_T Size, Result;
3117  PCHAR TailPart;
3118 
3119  /* Calculate size */
3120  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
3121  Size = RtlpGetSizeOfBigBlock(HeapEntry);
3122  else
3123  Size = (HeapEntry->Size << HEAP_ENTRY_SHIFT) - HeapEntry->UnusedBytes;
3124 
3125  /* Calculate pointer to the tail part of the block */
3126  TailPart = (PCHAR)(HeapEntry + 1) + Size;
3127 
3128  /* Compare tail pattern */
3129  Result = RtlCompareMemory(TailPart,
3130  FillPattern,
3131  HEAP_ENTRY_SIZE);
3132 
3133  if (Result != HEAP_ENTRY_SIZE)
3134  {
3135  DPRINT1("HEAP: Heap entry (size %x) %p tail is modified at %p\n", Size, HeapEntry, TailPart + Result);
3136  return FALSE;
3137  }
3138 
3139  /* All is fine */
3140  return TRUE;
3141 }
SIZE_T NTAPI RtlpGetSizeOfBigBlock(PHEAP_ENTRY HeapEntry)
Definition: heap.c:424
signed char * PCHAR
Definition: retypes.h:7
#define TRUE
Definition: types.h:120
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:44
UCHAR FillPattern[HEAP_ENTRY_SIZE]
Definition: heap.c:71
_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:359
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#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 230 of file heap.c.

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

Referenced by RtlpRemoveFreeBlock().

◆ RtlpCoalesceFreeBlocks()

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

Definition at line 980 of file heap.c.

984 {
985  PHEAP_FREE_ENTRY CurrentEntry, NextEntry;
986 
987  /* Get the previous entry */
988  CurrentEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry - FreeEntry->PreviousSize);
989 
990  /* Check it */
991  if (CurrentEntry != FreeEntry &&
992  !(CurrentEntry->Flags & HEAP_ENTRY_BUSY) &&
993  (*FreeSize + CurrentEntry->Size) <= HEAP_MAX_BLOCK_SIZE)
994  {
995  ASSERT(FreeEntry->PreviousSize == CurrentEntry->Size);
996 
997  /* Remove it if asked for */
998  if (Remove)
999  {
1000  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE, FALSE);
1001  Heap->TotalFreeSize -= FreeEntry->Size;
1002 
1003  /* Remove it only once! */
1004  Remove = FALSE;
1005  }
1006 
1007  /* Remove previous entry too */
1008  RtlpRemoveFreeBlock(Heap, CurrentEntry, FALSE, FALSE);
1009 
1010  /* Copy flags */
1011  CurrentEntry->Flags = FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY;
1012 
1013  /* Advance FreeEntry and update sizes */
1014  FreeEntry = CurrentEntry;
1015  *FreeSize = *FreeSize + CurrentEntry->Size;
1016  Heap->TotalFreeSize -= CurrentEntry->Size;
1017  FreeEntry->Size = (USHORT)(*FreeSize);
1018 
1019  /* Also update previous size if needed */
1020  if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1021  {
1022  ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
1023  }
1024  }
1025 
1026  /* Check the next block if it exists */
1027  if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1028  {
1029  NextEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + *FreeSize);
1030 
1031  if (!(NextEntry->Flags & HEAP_ENTRY_BUSY) &&
1032  NextEntry->Size + *FreeSize <= HEAP_MAX_BLOCK_SIZE)
1033  {
1034  ASSERT(*FreeSize == NextEntry->PreviousSize);
1035 
1036  /* Remove it if asked for */
1037  if (Remove)
1038  {
1039  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE, FALSE);
1040  Heap->TotalFreeSize -= FreeEntry->Size;
1041  }
1042 
1043  /* Copy flags */
1044  FreeEntry->Flags = NextEntry->Flags & HEAP_ENTRY_LAST_ENTRY;
1045 
1046  /* Remove next entry now */
1047  RtlpRemoveFreeBlock(Heap, NextEntry, FALSE, FALSE);
1048 
1049  /* Update sizes */
1050  *FreeSize = *FreeSize + NextEntry->Size;
1051  Heap->TotalFreeSize -= NextEntry->Size;
1052  FreeEntry->Size = (USHORT)(*FreeSize);
1053 
1054  /* Also update previous size if needed */
1055  if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1056  {
1057  ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
1058  }
1059  }
1060  }
1061  return FreeEntry;
1062 }
SIZE_T TotalFreeSize
Definition: heap.h:236
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:24
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:382
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 973 of file heap.c.

974 {
976  return NULL;
977 }
smooth NULL
Definition: ftsmooth.c:416
#define UNIMPLEMENTED
Definition: debug.h:114

Referenced by RtlpExtendHeap().

◆ RtlpCreateUnCommittedRange()

PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange ( PHEAP_SEGMENT  Segment)

Definition at line 437 of file heap.c.

438 {
440  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
441  PHEAP_UCR_SEGMENT UcrSegment;
442  PHEAP Heap = Segment->Heap;
446 
447  DPRINT("RtlpCreateUnCommittedRange(%p)\n", Segment);
448 
449  /* Check if we have unused UCRs */
450  if (IsListEmpty(&Heap->UCRList))
451  {
452  /* Get a pointer to the first UCR segment */
453  UcrSegment = CONTAINING_RECORD(Heap->UCRSegments.Flink, HEAP_UCR_SEGMENT, ListEntry);
454 
455  /* Check the list of UCR segments */
456  if (IsListEmpty(&Heap->UCRSegments) ||
457  UcrSegment->ReservedSize == UcrSegment->CommittedSize)
458  {
459  /* We need to create a new one. Reserve 16 pages for it */
460  UcrSegment = NULL;
461  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
462  (PVOID *)&UcrSegment,
463  0,
464  &ReserveSize,
465  MEM_RESERVE,
467 
468  if (!NT_SUCCESS(Status)) return NULL;
469 
470  /* Commit one page */
471  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
472  (PVOID *)&UcrSegment,
473  0,
474  &CommitSize,
475  MEM_COMMIT,
477 
478  if (!NT_SUCCESS(Status))
479  {
480  /* Release reserved memory */
481  ZwFreeVirtualMemory(NtCurrentProcess(),
482  (PVOID *)&UcrSegment,
483  &ReserveSize,
484  MEM_RELEASE);
485  return NULL;
486  }
487 
488  /* Set it's data */
489  UcrSegment->ReservedSize = ReserveSize;
490  UcrSegment->CommittedSize = CommitSize;
491 
492  /* Add it to the head of the list */
493  InsertHeadList(&Heap->UCRSegments, &UcrSegment->ListEntry);
494 
495  /* Get a pointer to the first available UCR descriptor */
496  UcrDescriptor = (PHEAP_UCR_DESCRIPTOR)(UcrSegment + 1);
497  }
498  else
499  {
500  /* It's possible to use existing UCR segment. Commit one more page */
501  UcrDescriptor = (PHEAP_UCR_DESCRIPTOR)((PCHAR)UcrSegment + UcrSegment->CommittedSize);
502  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
503  (PVOID *)&UcrDescriptor,
504  0,
505  &CommitSize,
506  MEM_COMMIT,
508 
509  if (!NT_SUCCESS(Status)) return NULL;
510 
511  /* Update sizes */
512  UcrSegment->CommittedSize += CommitSize;
513  }
514 
515  /* There is a whole bunch of new UCR descriptors. Put them into the unused list */
516  while ((PCHAR)(UcrDescriptor + 1) <= (PCHAR)UcrSegment + UcrSegment->CommittedSize)
517  {
518  InsertTailList(&Heap->UCRList, &UcrDescriptor->ListEntry);
519  UcrDescriptor++;
520  }
521  }
522 
523  /* There are unused UCRs, just get the first one */
524  Entry = RemoveHeadList(&Heap->UCRList);
525  UcrDescriptor = CONTAINING_RECORD(Entry, HEAP_UCR_DESCRIPTOR, ListEntry);
526  return UcrDescriptor;
527 }
signed char * PCHAR
Definition: retypes.h:7
struct _Entry Entry
Definition: kefuncs.h:640
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:301
#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:302
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:893
#define NtCurrentProcess()
Definition: nt_native.h:1657
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
LIST_ENTRY UCRSegments
Definition: heap.h:245
#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
LIST_ENTRY UCRList
Definition: heap.h:244
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:117
LIST_ENTRY ListEntry
Definition: heap.h:292
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:78
_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:300
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 737 of file heap.c.

740 {
742  PHEAP_ENTRY PrecedingInUseEntry = NULL, NextInUseEntry = NULL;
743  PHEAP_FREE_ENTRY NextFreeEntry;
744  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
745  SIZE_T PrecedingSize, NextSize, DecommitSize;
746  ULONG_PTR DecommitBase;
748 
749  DPRINT("Decommitting %p %p %x\n", Heap, FreeEntry, Size);
750 
751  /* We can't decommit if there is a commit routine! */
752  if (Heap->CommitRoutine)
753  {
754  /* Just add it back the usual way */
755  RtlpInsertFreeBlock(Heap, FreeEntry, Size);
756  return;
757  }
758 
759  /* Get the segment */
760  Segment = Heap->Segments[FreeEntry->SegmentOffset];
761 
762  /* Get the preceding entry */
763  DecommitBase = ROUND_UP(FreeEntry, PAGE_SIZE);
764  PrecedingSize = (PHEAP_ENTRY)DecommitBase - (PHEAP_ENTRY)FreeEntry;
765 
766  if (PrecedingSize == 1)
767  {
768  /* Just 1 heap entry, increase the base/size */
769  DecommitBase += PAGE_SIZE;
770  PrecedingSize += PAGE_SIZE >> HEAP_ENTRY_SHIFT;
771  }
772  else if (FreeEntry->PreviousSize &&
773  (DecommitBase == (ULONG_PTR)FreeEntry))
774  {
775  PrecedingInUseEntry = (PHEAP_ENTRY)FreeEntry - FreeEntry->PreviousSize;
776  }
777 
778  /* Get the next entry */
779  NextFreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + Size);
780  DecommitSize = ROUND_DOWN(NextFreeEntry, PAGE_SIZE);
781  NextSize = (PHEAP_ENTRY)NextFreeEntry - (PHEAP_ENTRY)DecommitSize;
782 
783  if (NextSize == 1)
784  {
785  /* Just 1 heap entry, increase the size */
786  DecommitSize -= PAGE_SIZE;
787  NextSize += PAGE_SIZE >> HEAP_ENTRY_SHIFT;
788  }
789  else if (NextSize == 0 &&
790  !(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
791  {
792  NextInUseEntry = (PHEAP_ENTRY)NextFreeEntry;
793  }
794 
795  NextFreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)NextFreeEntry - NextSize);
796 
797  /* Calculate real decommit size */
798  if (DecommitSize > DecommitBase)
799  {
800  DecommitSize -= DecommitBase;
801  }
802  else
803  {
804  /* Nothing to decommit */
805  RtlpInsertFreeBlock(Heap, FreeEntry, Size);
806  return;
807  }
808 
809  /* A decommit is necessary. Create a UCR descriptor */
810  UcrDescriptor = RtlpCreateUnCommittedRange(Segment);
811  if (!UcrDescriptor)
812  {
813  DPRINT1("HEAP: Failed to create UCR descriptor\n");
814  RtlpInsertFreeBlock(Heap, FreeEntry, PrecedingSize);
815  return;
816  }
817 
818  /* Decommit the memory */
819  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
820  (PVOID *)&DecommitBase,
821  &DecommitSize,
822  MEM_DECOMMIT);
823 
824  /* Delete that UCR. This is needed to assure there is an unused UCR entry in the list */
825  RtlpDestroyUnCommittedRange(Segment, UcrDescriptor);
826 
827  if (!NT_SUCCESS(Status))
828  {
829  RtlpInsertFreeBlock(Heap, FreeEntry, Size);
830  return;
831  }
832 
833  /* Insert uncommitted pages */
834  RtlpInsertUnCommittedPages(Segment, DecommitBase, DecommitSize);
835  Segment->NumberOfUnCommittedPages += (ULONG)(DecommitSize / PAGE_SIZE);
836 
837  if (PrecedingSize)
838  {
839  /* Adjust size of this free entry and insert it */
840  FreeEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
841  FreeEntry->Size = (USHORT)PrecedingSize;
842  Heap->TotalFreeSize += PrecedingSize;
843 
844  /* Insert it into the free list */
845  RtlpInsertFreeBlockHelper(Heap, FreeEntry, PrecedingSize, FALSE);
846  }
847  else if (PrecedingInUseEntry)
848  {
849  /* Adjust preceding in use entry */
850  PrecedingInUseEntry->Flags |= HEAP_ENTRY_LAST_ENTRY;
851  }
852 
853  /* Now the next one */
854  if (NextSize)
855  {
856  /* Adjust size of this free entry and insert it */
857  NextFreeEntry->Flags = 0;
858  NextFreeEntry->PreviousSize = 0;
859  NextFreeEntry->SegmentOffset = Segment->Entry.SegmentOffset;
860  NextFreeEntry->Size = (USHORT)NextSize;
861 
862  ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)NextFreeEntry + NextSize))->PreviousSize = (USHORT)NextSize;
863 
864  Heap->TotalFreeSize += NextSize;
865  RtlpInsertFreeBlockHelper(Heap, NextFreeEntry, NextSize, FALSE);
866  }
867  else if (NextInUseEntry)
868  {
869  NextInUseEntry->PreviousSize = 0;
870  }
871 }
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine
Definition: heap.h:264
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:250
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
SIZE_T TotalFreeSize
Definition: heap.h:236
LONG NTSTATUS
Definition: precomp.h:26
uint32_t ULONG_PTR
Definition: typedefs.h:63
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:250
#define MEM_DECOMMIT
Definition: nt_native.h:1315
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:318
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:893
#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:530
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:359
PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange(PHEAP_SEGMENT Segment)
Definition: heap.c:437
Status
Definition: gdiplustypes.h:24
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
ULONG_PTR SIZE_T
Definition: typedefs.h:78
VOID NTAPI RtlpInsertUnCommittedPages(PHEAP_SEGMENT Segment, ULONG_PTR Address, SIZE_T Size)
Definition: heap.c:542
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 948 of file heap.c.

949 {
952  SIZE_T Size = 0;
953 
954  /* Make sure it's not user allocated */
955  if (Segment->SegmentFlags & HEAP_USER_ALLOCATED) return;
956 
957  BaseAddress = Segment->BaseAddress;
958  DPRINT("Destroying segment %p, BA %p\n", Segment, BaseAddress);
959 
960  /* Release virtual memory */
961  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
962  &BaseAddress,
963  &Size,
964  MEM_RELEASE);
965 
966  if (!NT_SUCCESS(Status))
967  {
968  DPRINT1("HEAP: Failed to release segment's memory with status 0x%08X\n", Status);
969  }
970 }
LONG NTSTATUS
Definition: precomp.h:26
void DPRINT(...)
Definition: polytest.cpp:61
_Inout_ PVOID Segment
Definition: exfuncs.h:893
#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
#define HEAP_USER_ALLOCATED
Definition: heap.h:56
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#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 530 of file heap.c.

532 {
533  /* Zero it out */
534  UcrDescriptor->Address = NULL;
535  UcrDescriptor->Size = 0;
536 
537  /* Put it into the heap's list of unused UCRs */
538  InsertHeadList(&Segment->Heap->UCRList, &UcrDescriptor->ListEntry);
539 }
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:893
LIST_ENTRY ListEntry
Definition: heap.h:292

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

◆ RtlpExtendHeap()

PHEAP_FREE_ENTRY NTAPI RtlpExtendHeap ( PHEAP  Heap,
SIZE_T  Size 
)

Definition at line 1065 of file heap.c.

1067 {
1068  ULONG Pages;
1069  UCHAR Index, EmptyIndex;
1070  SIZE_T FreeSize, CommitSize, ReserveSize;
1072  PHEAP_FREE_ENTRY FreeEntry;
1073  NTSTATUS Status;
1074 
1075  DPRINT("RtlpExtendHeap(%p %x)\n", Heap, Size);
1076 
1077  /* Calculate amount in pages */
1078  Pages = (ULONG)((Size + PAGE_SIZE - 1) / PAGE_SIZE);
1079  FreeSize = Pages * PAGE_SIZE;
1080  DPRINT("Pages %x, FreeSize %x. Going through segments...\n", Pages, FreeSize);
1081 
1082  /* Find an empty segment */
1083  EmptyIndex = HEAP_SEGMENTS;
1084  for (Index = 0; Index < HEAP_SEGMENTS; Index++)
1085  {
1086  Segment = Heap->Segments[Index];
1087 
1088  if (Segment) DPRINT("Segment[%u] %p with NOUCP %x\n", Index, Segment, Segment->NumberOfUnCommittedPages);
1089 
1090  /* Check if its size suits us */
1091  if (Segment &&
1092  Pages <= Segment->NumberOfUnCommittedPages)
1093  {
1094  DPRINT("This segment is suitable\n");
1095 
1096  /* Commit needed amount */
1097  FreeEntry = RtlpFindAndCommitPages(Heap, Segment, &FreeSize, NULL);
1098 
1099  /* Coalesce it with adjacent entries */
1100  if (FreeEntry)
1101  {
1102  FreeSize = FreeSize >> HEAP_ENTRY_SHIFT;
1103  FreeEntry = RtlpCoalesceFreeBlocks(Heap, FreeEntry, &FreeSize, FALSE);
1104  RtlpInsertFreeBlock(Heap, FreeEntry, FreeSize);
1105  return FreeEntry;
1106  }
1107  }
1108  else if (!Segment &&
1109  EmptyIndex == HEAP_SEGMENTS)
1110  {
1111  /* Remember the first unused segment index */
1112  EmptyIndex = Index;
1113  }
1114  }
1115 
1116  /* No luck, need to grow the heap */
1117  if ((Heap->Flags & HEAP_GROWABLE) &&
1118  (EmptyIndex != HEAP_SEGMENTS))
1119  {
1120  Segment = NULL;
1121 
1122  /* Reserve the memory */
1123  if ((Size + PAGE_SIZE) <= Heap->SegmentReserve)
1124  ReserveSize = Heap->SegmentReserve;
1125  else
1127 
1128  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1129  (PVOID)&Segment,
1130  0,
1131  &ReserveSize,
1132  MEM_RESERVE,
1133  PAGE_READWRITE);
1134 
1135  /* If it failed, retry again with a half division algorithm */
1136  while (!NT_SUCCESS(Status) &&
1137  ReserveSize != Size + PAGE_SIZE)
1138  {
1139  ReserveSize /= 2;
1140 
1141  if (ReserveSize < (Size + PAGE_SIZE))
1143 
1144  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1145  (PVOID)&Segment,
1146  0,
1147  &ReserveSize,
1148  MEM_RESERVE,
1149  PAGE_READWRITE);
1150  }
1151 
1152  /* Proceed only if it's success */
1153  if (NT_SUCCESS(Status))
1154  {
1155  Heap->SegmentReserve += ReserveSize;
1156 
1157  /* Now commit the memory */
1158  if ((Size + PAGE_SIZE) <= Heap->SegmentCommit)
1159  CommitSize = Heap->SegmentCommit;
1160  else
1162 
1163  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1164  (PVOID)&Segment,
1165  0,
1166  &CommitSize,
1167  MEM_COMMIT,
1168  PAGE_READWRITE);
1169 
1170  DPRINT("Committed %lu bytes at base %p\n", CommitSize, Segment);
1171 
1172  /* Initialize heap segment if commit was successful */
1173  if (NT_SUCCESS(Status))
1175 
1176  /* If everything worked - cool */
1177  if (NT_SUCCESS(Status)) return (PHEAP_FREE_ENTRY)Segment->FirstEntry;
1178 
1179  DPRINT1("Committing failed with status 0x%08X\n", Status);
1180 
1181  /* Nope, we failed. Free memory */
1182  ZwFreeVirtualMemory(NtCurrentProcess(),
1183  (PVOID)&Segment,
1184  &ReserveSize,
1185  MEM_RELEASE);
1186  }
1187  else
1188  {
1189  DPRINT1("Reserving failed with status 0x%08X\n", Status);
1190  }
1191  }
1192 
1193  if (RtlpGetMode() == UserMode)
1194  {
1195  /* If coalescing on free is disabled in usermode, then do it here */
1197  {
1198  FreeEntry = RtlpCoalesceHeap(Heap);
1199 
1200  /* If it's a suitable one - return it */
1201  if (FreeEntry &&
1202  FreeEntry->Size >= Size)
1203  {
1204  return FreeEntry;
1205  }
1206  }
1207  }
1208 
1209  return NULL;
1210 }
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:980
#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:973
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:250
#define MEM_RESERVE
Definition: nt_native.h:1314
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:318
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:893
#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:611
_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
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:78
SIZE_T SegmentReserve
Definition: heap.h:232
ULONG Flags
Definition: heap.h:223
SIZE_T SegmentCommit
Definition: heap.h:233
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:875
_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 611 of file heap.c.

615 {
616  PLIST_ENTRY Current;
617  ULONG_PTR Address = 0;
618  PHEAP_UCR_DESCRIPTOR UcrDescriptor, PreviousUcr = NULL;
619  PHEAP_ENTRY FirstEntry, LastEntry;
621 
622  DPRINT("RtlpFindAndCommitPages(%p %p %Ix %08Ix)\n", Heap, Segment, *Size, Address);
623 
624  /* Go through UCRs in a segment */
625  Current = Segment->UCRSegmentList.Flink;
626  while (Current != &Segment->UCRSegmentList)
627  {
628  UcrDescriptor = CONTAINING_RECORD(Current, HEAP_UCR_DESCRIPTOR, SegmentEntry);
629 
630  /* Check if we can use that one right away */
631  if (UcrDescriptor->Size >= *Size &&
632  (UcrDescriptor->Address == AddressRequested || !AddressRequested))
633  {
634  /* Get the address */
635  Address = (ULONG_PTR)UcrDescriptor->Address;
636 
637  /* Commit it */
638  if (Heap->CommitRoutine)
639  {
640  Status = Heap->CommitRoutine(Heap, (PVOID *)&Address, Size);
641  }
642  else
643  {
644  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
645  (PVOID *)&Address,
646  0,
647  Size,
648  MEM_COMMIT,
650  }
651 
652  DPRINT("Committed %Iu bytes at base %08Ix, UCR size is %lu\n", *Size, Address, UcrDescriptor->Size);
653 
654  /* Fail in unsuccessful case */
655  if (!NT_SUCCESS(Status))
656  {
657  DPRINT1("Committing page failed with status 0x%08X\n", Status);
658  return NULL;
659  }
660 
661  /* Update tracking numbers */
662  Segment->NumberOfUnCommittedPages -= (ULONG)(*Size / PAGE_SIZE);
663 
664  /* Calculate first and last entries */
665  FirstEntry = (PHEAP_ENTRY)Address;
666 
667  /* Go through the entries to find the last one */
668  if (PreviousUcr)
669  LastEntry = (PHEAP_ENTRY)((ULONG_PTR)PreviousUcr->Address + PreviousUcr->Size);
670  else
671  LastEntry = &Segment->Entry;
672 
673  while (!(LastEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
674  {
675  ASSERT(LastEntry->Size != 0);
676  LastEntry += LastEntry->Size;
677  }
678  ASSERT((LastEntry + LastEntry->Size) == FirstEntry);
679 
680  /* Unmark it as a last entry */
681  LastEntry->Flags &= ~HEAP_ENTRY_LAST_ENTRY;
682 
683  /* Update UCR descriptor */
684  UcrDescriptor->Address = (PVOID)((ULONG_PTR)UcrDescriptor->Address + *Size);
685  UcrDescriptor->Size -= *Size;
686 
687  DPRINT("Updating UcrDescriptor %p, new Address %p, size %lu\n",
688  UcrDescriptor, UcrDescriptor->Address, UcrDescriptor->Size);
689 
690  /* Set various first entry fields */
691  FirstEntry->SegmentOffset = LastEntry->SegmentOffset;
692  FirstEntry->Size = (USHORT)(*Size >> HEAP_ENTRY_SHIFT);
693  FirstEntry->PreviousSize = LastEntry->Size;
694 
695  /* Check if anything left in this UCR */
696  if (UcrDescriptor->Size == 0)
697  {
698  /* It's fully exhausted */
699 
700  /* Check if this is the end of the segment */
701  if(UcrDescriptor->Address == Segment->LastValidEntry)
702  {
703  FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
704  }
705  else
706  {
707  FirstEntry->Flags = 0;
708  /* Update field of next entry */
709  ASSERT((FirstEntry + FirstEntry->Size)->PreviousSize == 0);
710  (FirstEntry + FirstEntry->Size)->PreviousSize = FirstEntry->Size;
711  }
712 
713  /* This UCR needs to be removed because it became useless */
714  RemoveEntryList(&UcrDescriptor->SegmentEntry);
715 
716  RtlpDestroyUnCommittedRange(Segment, UcrDescriptor);
717  Segment->NumberOfUnCommittedRanges--;
718  }
719  else
720  {
721  FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
722  }
723 
724  /* We're done */
725  return (PHEAP_FREE_ENTRY)FirstEntry;
726  }
727 
728  /* Advance to the next descriptor */
729  PreviousUcr = UcrDescriptor;
730  Current = Current->Flink;
731  }
732 
733  return NULL;
734 }
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine
Definition: heap.h:264
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:63
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:893
#define NtCurrentProcess()
Definition: nt_native.h:1657
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
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:530
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LIST_ENTRY SegmentEntry
Definition: heap.h:293
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
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 52 of file heap.c.

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

Referenced by RtlAllocateHeap().

◆ RtlpGetExtraStuffPointer()

PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer ( PHEAP_ENTRY  HeapEntry)

Definition at line 2526 of file heap.c.

2527 {
2528  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
2529 
2530  /* Check if it's a big block */
2531  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
2532  {
2533  VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
2534 
2535  /* Return a pointer to the extra stuff*/
2536  return &VirtualEntry->ExtraStuff;
2537  }
2538  else
2539  {
2540  /* This is a usual entry, which means extra stuff follows this block */
2541  return (PHEAP_ENTRY_EXTRA)(HeapEntry + HeapEntry->Size - 1);
2542  }
2543 }
Definition: heap.h:321
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:44
Definition: heap.h:305
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:324

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

◆ RtlpGetSizeOfBigBlock()

SIZE_T NTAPI RtlpGetSizeOfBigBlock ( PHEAP_ENTRY  HeapEntry)

Definition at line 424 of file heap.c.

425 {
426  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
427 
428  /* Get pointer to the containing record */
429  VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
430  ASSERT(VirtualEntry->BusyBlock.Size >= sizeof(HEAP_VIRTUAL_ALLOC_ENTRY));
431 
432  /* Restore the real size */
433  return VirtualEntry->CommitSize - HeapEntry->Size;
434 }
Definition: heap.h:321
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:325
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
HEAP_ENTRY BusyBlock
Definition: heap.h:327

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 2303 of file heap.c.

2308 {
2309  UCHAR EntryFlags, RememberFlags;
2310  PHEAP_FREE_ENTRY FreeEntry, UnusedEntry, FollowingEntry;
2311  SIZE_T FreeSize, PrevSize, TailPart, AddedSize = 0;
2312  PHEAP_ENTRY_EXTRA OldExtra, NewExtra;
2313 
2314  /* We can't grow beyond specified threshold */
2315  if (Index > Heap->VirtualMemoryThreshold)
2316  return FALSE;
2317 
2318  /* Get entry flags */
2319  EntryFlags = InUseEntry->Flags;
2320 
2321  /* Get the next free entry */
2322  FreeEntry = (PHEAP_FREE_ENTRY)(InUseEntry + InUseEntry->Size);
2323 
2324  if (EntryFlags & HEAP_ENTRY_LAST_ENTRY)
2325  {
2326  /* There is no next block, just uncommitted space. Calculate how much is needed */
2327  FreeSize = (Index - InUseEntry->Size) << HEAP_ENTRY_SHIFT;
2328  FreeSize = ROUND_UP(FreeSize, PAGE_SIZE);
2329 
2330  /* Find and commit those pages */
2331  FreeEntry = RtlpFindAndCommitPages(Heap,
2332  Heap->Segments[InUseEntry->SegmentOffset],
2333  &FreeSize,
2334  FreeEntry);
2335 
2336  /* Fail if it failed... */
2337  if (!FreeEntry) return FALSE;
2338 
2339  /* It was successful, perform coalescing */
2340  FreeSize = FreeSize >> HEAP_ENTRY_SHIFT;
2341  FreeEntry = RtlpCoalesceFreeBlocks(Heap, FreeEntry, &FreeSize, FALSE);
2342 
2343  /* Check if it's enough */
2344  if (FreeSize + InUseEntry->Size < Index)
2345  {
2346  /* Still not enough */
2347  RtlpInsertFreeBlock(Heap, FreeEntry, FreeSize);
2348  Heap->TotalFreeSize += FreeSize;
2349  return FALSE;
2350  }
2351 
2352  /* Remember flags of this free entry */
2353  RememberFlags = FreeEntry->Flags;
2354 
2355  /* Sum up sizes */
2356  FreeSize += InUseEntry->Size;
2357  }
2358  else
2359  {
2360  /* The next block indeed exists. Check if it's free or in use */
2361  if (FreeEntry->Flags & HEAP_ENTRY_BUSY) return FALSE;
2362 
2363  /* Next entry is free, check if it can fit the block we need */
2364  FreeSize = InUseEntry->Size + FreeEntry->Size;
2365  if (FreeSize < Index) return FALSE;
2366 
2367  /* Remember flags of this free entry */
2368  RememberFlags = FreeEntry->Flags;
2369 
2370  /* Remove this block from the free list */
2371  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE, FALSE);
2372  Heap->TotalFreeSize -= FreeEntry->Size;
2373  }
2374 
2375  PrevSize = (InUseEntry->Size << HEAP_ENTRY_SHIFT) - InUseEntry->UnusedBytes;
2376  FreeSize -= Index;
2377 
2378  /* Don't produce too small blocks */
2379  if (FreeSize <= 2)
2380  {
2381  Index += FreeSize;
2382  FreeSize = 0;
2383  }
2384 
2385  /* Process extra stuff */
2386  if (EntryFlags & HEAP_ENTRY_EXTRA_PRESENT)
2387  {
2388  /* Calculate pointers */
2389  OldExtra = (PHEAP_ENTRY_EXTRA)(InUseEntry + InUseEntry->Size - 1);
2390  NewExtra = (PHEAP_ENTRY_EXTRA)(InUseEntry + Index - 1);
2391 
2392  /* Copy contents */
2393  *NewExtra = *OldExtra;
2394 
2395  // FIXME Tagging
2396  }
2397 
2398  /* Update sizes */
2399  InUseEntry->Size = (USHORT)Index;
2400  InUseEntry->UnusedBytes = (UCHAR)((Index << HEAP_ENTRY_SHIFT) - Size);
2401 
2402  /* Check if there is a free space remaining after merging those blocks */
2403  if (!FreeSize)
2404  {
2405  /* Update flags and sizes */
2406  InUseEntry->Flags |= RememberFlags & HEAP_ENTRY_LAST_ENTRY;
2407 
2408  /* Either update previous size of the next entry or mark it as a last
2409  entry in the segment*/
2410  if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
2411  (InUseEntry + InUseEntry->Size)->PreviousSize = InUseEntry->Size;
2412  }
2413  else
2414  {
2415  /* Complex case, we need to split the block to give unused free space
2416  back to the heap */
2417  UnusedEntry = (PHEAP_FREE_ENTRY)(InUseEntry + Index);
2418  UnusedEntry->PreviousSize = (USHORT)Index;
2419  UnusedEntry->SegmentOffset = InUseEntry->SegmentOffset;
2420 
2421  /* Update the following block or set the last entry in the segment */
2422  if (RememberFlags & HEAP_ENTRY_LAST_ENTRY)
2423  {
2424  /* Set flags and size */
2425  UnusedEntry->Flags = RememberFlags;
2426  UnusedEntry->Size = (USHORT)FreeSize;
2427 
2428  /* Insert it to the heap and update total size */
2429  RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
2430  Heap->TotalFreeSize += FreeSize;
2431  }
2432  else
2433  {
2434  /* There is a block after this one */
2435  FollowingEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)UnusedEntry + FreeSize);
2436 
2437  if (FollowingEntry->Flags & HEAP_ENTRY_BUSY)
2438  {
2439  /* Update flags and set size of the unused space entry */
2440  UnusedEntry->Flags = RememberFlags & (~HEAP_ENTRY_LAST_ENTRY);
2441  UnusedEntry->Size = (USHORT)FreeSize;
2442 
2443  /* Update previous size of the following entry */
2444  FollowingEntry->PreviousSize = (USHORT)FreeSize;
2445 
2446  /* Insert it to the heap and update total free size */
2447  RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
2448  Heap->TotalFreeSize += FreeSize;
2449  }
2450  else
2451  {
2452  /* That following entry is also free, what a fortune! */
2453  RememberFlags = FollowingEntry->Flags;
2454 
2455  /* Remove it */
2456  RtlpRemoveFreeBlock(Heap, FollowingEntry, FALSE, FALSE);
2457  Heap->TotalFreeSize -= FollowingEntry->Size;
2458 
2459  /* And make up a new combined block */
2460  FreeSize += FollowingEntry->Size;
2461  UnusedEntry->Flags = RememberFlags;
2462 
2463  /* Check where to put it */
2464  if (FreeSize <= HEAP_MAX_BLOCK_SIZE)
2465  {
2466  /* Fine for a dedicated list */
2467  UnusedEntry->Size = (USHORT)FreeSize;
2468 
2469  if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
2470  ((PHEAP_ENTRY)UnusedEntry + FreeSize)->PreviousSize = (USHORT)FreeSize;
2471 
2472  /* Insert it back and update total size */
2473  RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
2474  Heap->TotalFreeSize += FreeSize;
2475  }
2476  else
2477  {
2478  /* The block is very large, leave all the hassle to the insertion routine */
2479  RtlpInsertFreeBlock(Heap, UnusedEntry, FreeSize);
2480  }
2481  }
2482  }
2483  }
2484 
2485  /* Properly "zero out" (and fill!) the space */
2486  if (Flags & HEAP_ZERO_MEMORY)
2487  {
2488  RtlZeroMemory((PCHAR)(InUseEntry + 1) + PrevSize, Size - PrevSize);
2489  }
2490  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
2491  {
2492  /* Calculate tail part which we need to fill */
2493  TailPart = PrevSize & (sizeof(ULONG) - 1);
2494 
2495  /* "Invert" it as usual */
2496  if (TailPart) TailPart = 4 - TailPart;
2497 
2498  if (Size > (PrevSize + TailPart))
2499  AddedSize = (Size - (PrevSize + TailPart)) & ~(sizeof(ULONG) - 1);
2500 
2501  if (AddedSize)
2502  {
2503  RtlFillMemoryUlong((PCHAR)(InUseEntry + 1) + PrevSize + TailPart,
2504  AddedSize,
2506  }
2507  }
2508 
2509  /* Fill the new tail */
2510  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
2511  {
2512  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size,
2514  HEAP_TAIL_FILL);
2515  }
2516 
2517  /* Copy user settable flags */
2518  InUseEntry->Flags &= ~HEAP_ENTRY_SETTABLE_FLAGS;
2519  InUseEntry->Flags |= ((Flags & HEAP_SETTABLE_USER_FLAGS) >> 4);
2520 
2521  /* Return success */
2522  return TRUE;
2523 }
signed char * PCHAR
Definition: retypes.h:7
#define HEAP_ENTRY_SETTABLE_FLAGS
Definition: heap.h:49
#define ARENA_INUSE_FILLER
Definition: oleaut.c:108
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
#define TRUE
Definition: types.h:120
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:250
#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:980
#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
Definition: heap.h:305
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:318
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
#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:611
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
VOID NTAPI RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN Dedicated, BOOLEAN NoFill)
Definition: heap.c:382
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:359
ULONG_PTR SIZE_T
Definition: typedefs.h:78
Definition: heap.h:136
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:45
#define HEAP_TAIL_FILL
Definition: heap.h:28
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:42
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
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 86 of file heap.c.

90 {
91  ULONG NumUCRs = 8;
92  ULONG Index;
93  SIZE_T HeaderSize;
95  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
96 
97  /* Preconditions */
98  ASSERT(Heap != NULL);
101  ASSERT(!(Flags & HEAP_NO_SERIALIZE) || (Lock == NULL)); /* HEAP_NO_SERIALIZE => no lock */
102 
103  /* Start out with the size of a plain Heap header */
104  HeaderSize = ROUND_UP(sizeof(HEAP), sizeof(HEAP_ENTRY));
105 
106  /* Check if space needs to be added for the Heap Lock */
107  if (!(Flags & HEAP_NO_SERIALIZE))
108  {
109  if (Lock != NULL)
110  /* The user manages the Heap Lock */
112  else
113  if (RtlpGetMode() == UserMode)
114  {
115  /* In user mode, the Heap Lock trails the Heap header */
116  Lock = (PHEAP_LOCK) ((ULONG_PTR) (Heap) + HeaderSize);
117  HeaderSize += ROUND_UP(sizeof(HEAP_LOCK), sizeof(HEAP_ENTRY));
118  }
119  }
120 
121  /* Add space for the initial Heap UnCommitted Range Descriptor list */
122  UcrDescriptor = (PHEAP_UCR_DESCRIPTOR) ((ULONG_PTR) (Heap) + HeaderSize);
123  HeaderSize += ROUND_UP(NumUCRs * sizeof(HEAP_UCR_DESCRIPTOR), sizeof(HEAP_ENTRY));
124 
125  /* Sanity check */
126  ASSERT(HeaderSize <= PAGE_SIZE);
127 
128  /* Initialise the Heap Entry header containing the Heap header */
129  Heap->Entry.Size = (USHORT)(HeaderSize >> HEAP_ENTRY_SHIFT);
130  Heap->Entry.Flags = HEAP_ENTRY_BUSY;
131  Heap->Entry.SmallTagIndex = LOBYTE(Heap->Entry.Size) ^ HIBYTE(Heap->Entry.Size) ^ Heap->Entry.Flags;
132  Heap->Entry.PreviousSize = 0;
133  Heap->Entry.SegmentOffset = 0;
134  Heap->Entry.UnusedBytes = 0;
135 
136  /* Initialise the Heap header */
137  Heap->Signature = HEAP_SIGNATURE;
138  Heap->Flags = Flags;
139  Heap->ForceFlags = (Flags & (HEAP_NO_SERIALIZE |
148 
149  /* Initialise the Heap parameters */
150  Heap->VirtualMemoryThreshold = ROUND_UP(Parameters->VirtualMemoryThreshold, sizeof(HEAP_ENTRY)) >> HEAP_ENTRY_SHIFT;
151  Heap->SegmentReserve = Parameters->SegmentReserve;
152  Heap->SegmentCommit = Parameters->SegmentCommit;
153  Heap->DeCommitFreeBlockThreshold = Parameters->DeCommitFreeBlockThreshold >> HEAP_ENTRY_SHIFT;
154  Heap->DeCommitTotalFreeThreshold = Parameters->DeCommitTotalFreeThreshold >> HEAP_ENTRY_SHIFT;
155  Heap->MaximumAllocationSize = Parameters->MaximumAllocationSize;
156  Heap->CommitRoutine = Parameters->CommitRoutine;
157 
158  /* Initialise the Heap validation info */
159  Heap->HeaderValidateCopy = NULL;
160  Heap->HeaderValidateLength = (USHORT)HeaderSize;
161 
162  /* Initialise the Heap Lock */
164  {
166  if (!NT_SUCCESS(Status))
167  return Status;
168  }
169  Heap->LockVariable = Lock;
170 
171  /* Initialise the Heap alignment info */
173  {
174  Heap->AlignMask = (ULONG) ~15;
175  Heap->AlignRound = 15 + sizeof(HEAP_ENTRY);
176  }
177  else
178  {
179  Heap->AlignMask = (ULONG) ~(sizeof(HEAP_ENTRY) - 1);
180  Heap->AlignRound = 2 * sizeof(HEAP_ENTRY) - 1;
181  }
182 
184  Heap->AlignRound += sizeof(HEAP_ENTRY);
185 
186  /* Initialise the Heap Segment list */
187  for (Index = 0; Index < HEAP_SEGMENTS; ++Index)
188  Heap->Segments[Index] = NULL;
189 
190  /* Initialise the Heap Free Heap Entry lists */
191  for (Index = 0; Index < HEAP_FREELISTS; ++Index)
192  InitializeListHead(&Heap->FreeLists[Index]);
193 
194  /* Initialise the Heap Virtual Allocated Blocks list */
195  InitializeListHead(&Heap->VirtualAllocdBlocks);
196 
197  /* Initialise the Heap UnCommitted Region lists */
198  InitializeListHead(&Heap->UCRSegments);
199  InitializeListHead(&Heap->UCRList);
200 
201  /* Register the initial Heap UnCommitted Region Descriptors */
202  for (Index = 0; Index < NumUCRs; ++Index)
203  InsertTailList(&Heap->UCRList, &UcrDescriptor[Index].ListEntry);
204 
205  return STATUS_SUCCESS;
206 }
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:63
_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
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:872
#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
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:78
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:123
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:2966
#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 875 of file heap.c.

881 {
882  PHEAP_ENTRY HeapEntry;
883 
884  /* Preconditions */
885  ASSERT(Heap != NULL);
886  ASSERT(Segment != NULL);
887  ASSERT(SegmentCommit >= PAGE_SIZE);
888  ASSERT(ROUND_DOWN(SegmentCommit, PAGE_SIZE) == SegmentCommit);
889  ASSERT(SegmentReserve >= SegmentCommit);
890  ASSERT(ROUND_DOWN(SegmentReserve, PAGE_SIZE) == SegmentReserve);
891 
892  DPRINT("RtlpInitializeHeapSegment(%p %p %x %x %lx %lx)\n", Heap, Segment, SegmentIndex, SegmentFlags, SegmentReserve, SegmentCommit);
893 
894  /* Initialise the Heap Entry header if this is not the first Heap Segment */
895  if ((PHEAP_SEGMENT) (Heap) != Segment)
896  {
897  Segment->Entry.Size = ROUND_UP(sizeof(HEAP_SEGMENT), sizeof(HEAP_ENTRY)) >> HEAP_ENTRY_SHIFT;
898  Segment->Entry.Flags = HEAP_ENTRY_BUSY;
899  Segment->Entry.SmallTagIndex = LOBYTE(Segment->Entry.Size) ^ HIBYTE(Segment->Entry.Size) ^ Segment->Entry.Flags;
900  Segment->Entry.PreviousSize = 0;
901  Segment->Entry.SegmentOffset = SegmentIndex;
902  Segment->Entry.UnusedBytes = 0;
903  }
904 
905  /* Sanity check */
906  ASSERT((Segment->Entry.Size << HEAP_ENTRY_SHIFT) <= PAGE_SIZE);
907 
908  /* Initialise the Heap Segment header */
909  Segment->SegmentSignature = HEAP_SEGMENT_SIGNATURE;
910  Segment->SegmentFlags = SegmentFlags;
911  Segment->Heap = Heap;
912  Heap->Segments[SegmentIndex] = Segment;
913 
914  /* Initialise the Heap Segment location information */
915  Segment->BaseAddress = Segment;
916  Segment->NumberOfPages = (ULONG)(SegmentReserve >> PAGE_SHIFT);
917 
918  /* Initialise the Heap Entries contained within the Heap Segment */
919  Segment->FirstEntry = &Segment->Entry + Segment->Entry.Size;
920  Segment->LastValidEntry = (PHEAP_ENTRY)((ULONG_PTR)Segment + SegmentReserve);
921 
922  if (((SIZE_T)Segment->Entry.Size << HEAP_ENTRY_SHIFT) < SegmentCommit)
923  {
924  HeapEntry = Segment->FirstEntry;
925 
926  /* Prepare a Free Heap Entry header */
927  HeapEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
928  HeapEntry->PreviousSize = Segment->Entry.Size;
929  HeapEntry->SegmentOffset = SegmentIndex;
930 
931  /* Register the Free Heap Entry */
932  RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY) HeapEntry, (SegmentCommit >> HEAP_ENTRY_SHIFT) - Segment->Entry.Size);
933  }
934 
935  /* Initialise the Heap Segment UnCommitted Range information */
936  Segment->NumberOfUnCommittedPages = (ULONG)((SegmentReserve - SegmentCommit) >> PAGE_SHIFT);
937  Segment->NumberOfUnCommittedRanges = 0;
938  InitializeListHead(&Segment->UCRSegmentList);
939 
940  /* Register the UnCommitted Range of the Heap Segment */
941  if (Segment->NumberOfUnCommittedPages != 0)
942  RtlpInsertUnCommittedPages(Segment, (ULONG_PTR) (Segment) + SegmentCommit, SegmentReserve - SegmentCommit);
943 
944  return STATUS_SUCCESS;
945 }
#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:63
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:318
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:893
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:78
VOID NTAPI RtlpInsertUnCommittedPages(PHEAP_SEGMENT Segment, ULONG_PTR Address, SIZE_T Size)
Definition: heap.c:542
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:2966

Referenced by RtlCreateHeap(), and RtlpExtendHeap().

◆ RtlpInsertFreeBlock()

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

Definition at line 318 of file heap.c.

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

254 {
255  PLIST_ENTRY FreeListHead, Current;
256  PHEAP_FREE_ENTRY CurrentEntry;
257 
258  ASSERT(FreeEntry->Size == BlockSize);
259 
260  /* Fill if it's not denied */
261  if (!NoFill)
262  {
263  FreeEntry->Flags &= ~(HEAP_ENTRY_FILL_PATTERN |
266 
267  if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
268  {
269  RtlFillMemoryUlong((PCHAR)(FreeEntry + 1),
270  (BlockSize << HEAP_ENTRY_SHIFT) - sizeof(*FreeEntry),
272 
273  FreeEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
274  }
275  }
276  else
277  {
278  /* Clear out all flags except the last entry one */
279  FreeEntry->Flags &= HEAP_ENTRY_LAST_ENTRY;
280  }
281 
282  /* Insert it either into dedicated or non-dedicated list */
283  if (BlockSize < HEAP_FREELISTS)
284  {
285  /* Dedicated list */
286  FreeListHead = &Heap->FreeLists[BlockSize];
287 
288  if (IsListEmpty(FreeListHead))
289  {
290  RtlpSetFreeListsBit(Heap, FreeEntry);
291  }
292  }
293  else
294  {
295  /* Non-dedicated one */
296  FreeListHead = &Heap->FreeLists[0];
297  Current = FreeListHead->Flink;
298 
299  /* Find a position where to insert it to (the list must be sorted) */
300  while (FreeListHead != Current)
301  {
302  CurrentEntry = CONTAINING_RECORD(Current, HEAP_FREE_ENTRY, FreeList);
303 
304  if (BlockSize <= CurrentEntry->Size)
305  break;
306 
307  Current = Current->Flink;
308  }
309 
310  FreeListHead = Current;
311  }
312 
313  /* Actually insert it into the list */
314  InsertTailList(FreeListHead, &FreeEntry->FreeList);
315 }
signed char * PCHAR
Definition: retypes.h:7
#define ARENA_FREE_FILLER
Definition: jsutils.c:62
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:119
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define HEAP_FREELISTS
Definition: heap.h:15
MmuFreePage * FreeList
Definition: mmuobject.c:60
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
ULONG Flags
Definition: heap.h:223
#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:210
LIST_ENTRY FreeLists[HEAP_FREELISTS]
Definition: heap.h:256

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 542 of file heap.c.

545 {
546  PLIST_ENTRY Current;
547  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
548 
549  DPRINT("RtlpInsertUnCommittedPages(%p %08Ix %Ix)\n", Segment, Address, Size);
550 
551  /* Go through the list of UCR descriptors, they are sorted from lowest address
552  to the highest */
553  Current = Segment->UCRSegmentList.Flink;
554  while (Current != &Segment->UCRSegmentList)
555  {
556  UcrDescriptor = CONTAINING_RECORD(Current, HEAP_UCR_DESCRIPTOR, SegmentEntry);
557 
558  if ((ULONG_PTR)UcrDescriptor->Address > Address)
559  {
560  /* Check for a really lucky case */
561  if ((Address + Size) == (ULONG_PTR)UcrDescriptor->Address)
562  {
563  /* Exact match */
564  UcrDescriptor->Address = (PVOID)Address;
565  UcrDescriptor->Size += Size;
566  return;
567  }
568 
569  /* We found the block before which the new one should go */
570  break;
571  }
572  else if (((ULONG_PTR)UcrDescriptor->Address + UcrDescriptor->Size) == Address)
573  {
574  /* Modify this entry */
575  Address = (ULONG_PTR)UcrDescriptor->Address;
576  Size += UcrDescriptor->Size;
577 
578  /* Advance to the next descriptor */
579  Current = Current->Flink;
580 
581  /* Remove the current descriptor from the list and destroy it */
582  RemoveEntryList(&UcrDescriptor->SegmentEntry);
583  RtlpDestroyUnCommittedRange(Segment, UcrDescriptor);
584 
585  Segment->NumberOfUnCommittedRanges--;
586  }
587  else
588  {
589  /* Advance to the next descriptor */
590  Current = Current->Flink;
591  }
592  }
593 
594  /* Create a new UCR descriptor */
595  UcrDescriptor = RtlpCreateUnCommittedRange(Segment);
596  if (!UcrDescriptor) return;
597 
598  UcrDescriptor->Address = (PVOID)Address;
599  UcrDescriptor->Size = Size;
600 
601  /* "Current" is the descriptor before which our one should go */
602  InsertTailList(Current, &UcrDescriptor->SegmentEntry);
603 
604  DPRINT("Added segment UCR with base %08Ix, size 0x%x\n", Address, Size);
605 
606  /* Increase counters */
607  Segment->NumberOfUnCommittedRanges++;
608 }
static PVOID
Definition: heap.c:41
#define InsertTailList(ListHead, Entry)
uint32_t ULONG_PTR
Definition: typedefs.h:63
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:893
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID NTAPI RtlpDestroyUnCommittedRange(PHEAP_SEGMENT Segment, PHEAP_UCR_DESCRIPTOR UcrDescriptor)
Definition: heap.c:530
LIST_ENTRY SegmentEntry
Definition: heap.h:293
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange(PHEAP_SEGMENT Segment)
Definition: heap.c:437
#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 382 of file heap.c.

386 {
387  SIZE_T Result, RealSize;
388 
389  /* Remove the free block and update the freelists bitmap */
390  if (RemoveEntryList(&FreeEntry->FreeList) &&
391  (Dedicated || (!Dedicated && FreeEntry->Size < HEAP_FREELISTS)))
392  {
393  RtlpClearFreeListsBit(Heap, FreeEntry);
394  }
395 
396  /* Fill with pattern if necessary */
397  if (!NoFill &&
398  (FreeEntry->Flags & HEAP_ENTRY_FILL_PATTERN))
399  {
400  RealSize = (FreeEntry->Size << HEAP_ENTRY_SHIFT) - sizeof(*FreeEntry);
401 
402  /* Deduct extra stuff from block's real size */
403  if (FreeEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT &&
404  RealSize > sizeof(HEAP_FREE_ENTRY_EXTRA))
405  {
406  RealSize -= sizeof(HEAP_FREE_ENTRY_EXTRA);
407  }
408 
409  /* Check if the free filler is intact */
410  Result = RtlCompareMemoryUlong((PCHAR)(FreeEntry + 1),
411  RealSize,
413 
414  if (Result != RealSize)
415  {
416  DPRINT1("Free heap block %p modified at %p after it was freed\n",
417  FreeEntry,
418  (PCHAR)(FreeEntry + 1) + Result);
419  }
420  }
421 }
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:62
LIST_ENTRY FreeList
Definition: heap.h:132
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
Definition: heap.h:305
_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:78
#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:319
FORCEINLINE VOID RtlpClearFreeListsBit(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry)
Definition: heap.c:230

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

◆ RtlProtectHeap()

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

Definition at line 3905 of file heap.c.

3907 {
3908  UNIMPLEMENTED;
3909  return NULL;
3910 }
smooth NULL
Definition: ftsmooth.c:416
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlpSetFreeListsBit()

FORCEINLINE VOID RtlpSetFreeListsBit ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry 
)

Definition at line 210 of file heap.c.

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

1634 {
1635  PHEAP_FREE_ENTRY SplitBlock, SplitBlock2;
1636  UCHAR FreeFlags, EntryFlags = HEAP_ENTRY_BUSY;
1637  PHEAP_ENTRY InUseEntry;
1638  SIZE_T FreeSize;
1639 
1640  /* Add extra flags in case of settable user value feature is requested,
1641  or there is a tag (small or normal) or there is a request to
1642  capture stack backtraces */
1643  if ((Flags & HEAP_EXTRA_FLAGS_MASK) ||
1644  Heap->PseudoTagEntries)
1645  {
1646  /* Add flag which means that the entry will have extra stuff attached */
1647  EntryFlags |= HEAP_ENTRY_EXTRA_PRESENT;
1648 
1649  /* NB! AllocationSize is already adjusted by RtlAllocateHeap */
1650  }
1651 
1652  /* Add settable user flags, if any */
1653  EntryFlags |= (Flags & HEAP_SETTABLE_USER_FLAGS) >> 4;
1654 
1655  /* Save flags, update total free size */
1656  FreeFlags = FreeBlock->Flags;
1657  Heap->TotalFreeSize -= FreeBlock->Size;
1658 
1659  /* Make this block an in-use one */
1660  InUseEntry = (PHEAP_ENTRY)FreeBlock;
1661  InUseEntry->Flags = EntryFlags;
1662  InUseEntry->SmallTagIndex = 0;
1663 
1664  /* Calculate the extra amount */
1665  FreeSize = InUseEntry->Size - Index;
1666 
1667  /* Update it's size fields (we don't need their data anymore) */
1668  InUseEntry->Size = (USHORT)Index;
1669  InUseEntry->UnusedBytes = (UCHAR)(AllocationSize - Size);
1670 
1671  /* If there is something to split - do the split */
1672  if (FreeSize != 0)
1673  {
1674  /* Don't split if resulting entry can't contain any payload data
1675  (i.e. being just HEAP_ENTRY_SIZE) */
1676  if (FreeSize == 1)
1677  {
1678  /* Increase sizes of the in-use entry */
1679  InUseEntry->Size++;
1680  InUseEntry->UnusedBytes += sizeof(HEAP_ENTRY);
1681  }
1682  else
1683  {
1684  /* Calculate a pointer to the new entry */
1685  SplitBlock = (PHEAP_FREE_ENTRY)(InUseEntry + Index);
1686 
1687  /* Initialize it */
1688  SplitBlock->Flags = FreeFlags;
1689  SplitBlock->SegmentOffset = InUseEntry->SegmentOffset;
1690  SplitBlock->Size = (USHORT)FreeSize;
1691  SplitBlock->PreviousSize = (USHORT)Index;
1692 
1693  /* Check if it's the last entry */
1694  if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
1695  {
1696  /* Insert it to the free list if it's the last entry */
1697  RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
1698  Heap->TotalFreeSize += FreeSize;
1699  }
1700  else
1701  {
1702  /* Not so easy - need to update next's previous size too */
1703  SplitBlock2 = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize);
1704 
1705  if (SplitBlock2->Flags & HEAP_ENTRY_BUSY)
1706  {
1707  SplitBlock2->PreviousSize = (USHORT)FreeSize;
1708  RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
1709  Heap->TotalFreeSize += FreeSize;
1710  }
1711  else
1712  {
1713  /* Even more complex - the next entry is free, so we can merge them into one! */
1714  SplitBlock->Flags = SplitBlock2->Flags;
1715 
1716  /* Remove that next entry */
1717  RtlpRemoveFreeBlock(Heap, SplitBlock2, FALSE, FALSE);
1718 
1719  /* Update sizes */
1720  FreeSize += SplitBlock2->Size;
1721  Heap->TotalFreeSize -= SplitBlock2->Size;
1722 
1723  if (FreeSize <= HEAP_MAX_BLOCK_SIZE)
1724  {
1725  /* Insert it back */
1726  SplitBlock->Size = (USHORT)FreeSize;
1727 
1728  /* Don't forget to update previous size of the next entry! */
1729  if (!(SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY))
1730  {
1731  ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize))->PreviousSize = (USHORT)FreeSize;
1732  }
1733 
1734  /* Actually insert it */
1735  RtlpInsertFreeBlockHelper(Heap, SplitBlock, (USHORT)FreeSize, FALSE);
1736 
1737  /* Update total size */
1738  Heap->TotalFreeSize += FreeSize;
1739  }
1740  else
1741  {
1742  /* Resulting block is quite big */
1743  RtlpInsertFreeBlock(Heap, SplitBlock, FreeSize);
1744  }
1745  }
1746  }
1747 
1748  /* Reset flags of the free entry */
1749  FreeFlags = 0;
1750  }
1751  }
1752 
1753  /* Set last entry flag */
1754  if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
1755  InUseEntry->Flags |= HEAP_ENTRY_LAST_ENTRY;
1756 
1757  return InUseEntry;
1758 }
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:250
SIZE_T TotalFreeSize
Definition: heap.h:236
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:24
#define HEAP_EXTRA_FLAGS_MASK
Definition: heap.h:36
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries
Definition: heap.h:255
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:318
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
VOID NTAPI RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN Dedicated, BOOLEAN NoFill)
Definition: heap.c:382
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:359
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:310
ULONG_PTR SIZE_T
Definition: typedefs.h:78
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 3397 of file heap.c.

3399 {
3401  BOOLEAN EmptyList;
3402  UCHAR SegmentOffset;
3403  SIZE_T Size, TotalFreeSize;
3404  ULONG PreviousSize;
3405  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock;
3406  PLIST_ENTRY ListHead, NextEntry;
3407  PHEAP_FREE_ENTRY FreeEntry;
3408  ULONG FreeBlocksCount, FreeListEntriesCount;
3409 
3410  /* Check headers */
3411  if (!RtlpValidateHeapHeaders(Heap, FALSE))
3412  return FALSE;
3413 
3414  /* Skip validation if it's not needed */
3415  if (!ForceValidation && !(Heap->Flags & HEAP_VALIDATE_ALL_ENABLED))
3416  return TRUE;
3417 
3418  /* Check free lists bitmaps */
3419  FreeListEntriesCount = 0;
3420  ListHead = &Heap->FreeLists[0];
3421 
3422  for (Size = 0; Size < HEAP_FREELISTS; Size++)
3423  {
3424  if (Size)
3425  {
3426  /* This is a dedicated list. Check if it's empty */
3427  EmptyList = IsListEmpty(ListHead);
3428 
3429  if (Heap->u.FreeListsInUseBytes[Size >> 3] & (1 << (Size & 7)))
3430  {
3431  if (EmptyList)
3432  {
3433  DPRINT1("HEAP: Empty %x-free list marked as non-empty\n", Size);
3434  return FALSE;
3435  }
3436  }
3437  else
3438  {
3439  if (!EmptyList)
3440  {
3441  DPRINT1("HEAP: Non-empty %x-free list marked as empty\n", Size);
3442  return FALSE;
3443  }
3444  }
3445  }
3446 
3447  /* Now check this list entries */
3448  NextEntry = ListHead->Flink;
3449  PreviousSize = 0;
3450 
3451  while (ListHead != NextEntry)
3452  {
3453  FreeEntry = CONTAINING_RECORD(NextEntry, HEAP_FREE_ENTRY, FreeList);
3454  NextEntry = NextEntry->Flink;
3455 
3456  /* If there is an in-use entry in a free list - that's quite a big problem */
3457  if (FreeEntry->Flags & HEAP_ENTRY_BUSY)
3458  {
3459  DPRINT1("HEAP: %Ix-dedicated list free element %p is marked in-use\n", Size, FreeEntry);
3460  return FALSE;
3461  }
3462 
3463  /* Check sizes according to that specific list's size */
3464  if ((Size == 0) && (FreeEntry->Size < HEAP_FREELISTS))
3465  {
3466  DPRINT1("HEAP: Non dedicated list free element %p has size %x which would fit a dedicated list\n", FreeEntry, FreeEntry->Size);
3467  return FALSE;
3468  }
3469  else if (Size && (FreeEntry->Size != Size))
3470  {
3471  DPRINT1("HEAP: %Ix-dedicated list free element %p has incorrect size %x\n", Size, FreeEntry, FreeEntry->Size);
3472  return FALSE;
3473  }
3474  else if ((Size == 0) && (FreeEntry->Size < PreviousSize))
3475  {
3476  DPRINT1("HEAP: Non dedicated list free element %p is not put in order\n", FreeEntry);
3477  return FALSE;
3478  }
3479 
3480  /* Remember previous size*/
3481  PreviousSize = FreeEntry->Size;
3482 
3483  /* Add up to the total amount of free entries */
3484  FreeListEntriesCount++;
3485  }
3486 
3487  /* Go to the head of the next free list */
3488  ListHead++;
3489  }
3490 
3491  /* Check big allocations */
3492  ListHead = &Heap->VirtualAllocdBlocks;
3493  NextEntry = ListHead->Flink;
3494 
3495  while (ListHead != NextEntry)
3496  {
3497  VirtualAllocBlock = CONTAINING_RECORD(NextEntry, HEAP_VIRTUAL_ALLOC_ENTRY, Entry);
3498 
3499  /* We can only check the fill pattern */
3500  if (VirtualAllocBlock->BusyBlock.Flags & HEAP_ENTRY_FILL_PATTERN)
3501  {
3502  if (!RtlpCheckInUsePattern(&VirtualAllocBlock->BusyBlock))
3503  return FALSE;
3504  }
3505 
3506  NextEntry = NextEntry->Flink;
3507  }
3508 
3509  /* Check all segments */
3510  FreeBlocksCount = 0;
3511  TotalFreeSize = 0;
3512 
3513  for (SegmentOffset = 0; SegmentOffset < HEAP_SEGMENTS; SegmentOffset++)
3514  {
3515  Segment = Heap->Segments[SegmentOffset];
3516 
3517  /* Go to the next one if there is no segment */
3518  if (!Segment) continue;
3519 
3520  if (!RtlpValidateHeapSegment(Heap,
3521  Segment,
3522  SegmentOffset,
3523  &FreeBlocksCount,
3524  &TotalFreeSize,
3525  NULL,
3526  NULL))
3527  {
3528  return FALSE;
3529  }
3530  }
3531 
3532  if (FreeListEntriesCount != FreeBlocksCount)
3533  {
3534  DPRINT1("HEAP: Free blocks count in arena (%lu) does not match free blocks number in the free lists (%lu)\n", FreeBlocksCount, FreeListEntriesCount);
3535  return FALSE;
3536  }
3537 
3538  if (Heap->TotalFreeSize != TotalFreeSize)
3539  {
3540  DPRINT1("HEAP: Total size of free blocks in arena (%Iu) does not equal to the one in heap header (%Iu)\n", TotalFreeSize, Heap->TotalFreeSize);
3541  return FALSE;
3542  }
3543 
3544  return TRUE;
3545 }
Definition: heap.h:321
#define TRUE
Definition: types.h:120
UCHAR FreeListsInUseBytes[HEAP_FREELISTS/(sizeof(UCHAR) *8)]
Definition: heap.h:261
SIZE_T TotalFreeSize
Definition: heap.h:236
#define HEAP_SEGMENTS
Definition: heap.h:16
_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:3144
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:250
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:893
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
union _HEAP::@4000 u
#define HEAP_VALIDATE_ALL_ENABLED
Definition: rtltypes.h:166
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:248
#define HEAP_FREELISTS
Definition: heap.h:15
unsigned char UCHAR
Definition: xmlstorage.h:181
MmuFreePage * FreeList
Definition: mmuobject.c:60
BOOLEAN NTAPI RtlpCheckInUsePattern(PHEAP_ENTRY HeapEntry)
Definition: heap.c:3114
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:43
ULONG_PTR SIZE_T
Definition: typedefs.h:78
ULONG Flags
Definition: heap.h:223
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
HEAP_ENTRY BusyBlock
Definition: heap.h:327
BOOLEAN NTAPI RtlpValidateHeapSegment(PHEAP Heap, PHEAP_SEGMENT Segment, UCHAR SegmentOffset, PULONG FreeEntriesCount, PSIZE_T TotalFreeSize, PSIZE_T TagEntries, PSIZE_T PseudoTagEntries)
Definition: heap.c:3210
base of all file and directory entries
Definition: entries.h:82
LIST_ENTRY FreeLists[HEAP_FREELISTS]
Definition: heap.h:256

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

◆ RtlpValidateHeapEntry()

BOOLEAN NTAPI RtlpValidateHeapEntry ( PHEAP  Heap,
PHEAP_ENTRY  HeapEntry 
)

Definition at line 3153 of file heap.c.

3156 {
3157  BOOLEAN BigAllocation, EntryFound = FALSE;
3159  ULONG SegmentOffset;
3160 
3161  /* Perform various consistency checks of this entry */
3162  if (!HeapEntry) goto invalid_entry;
3163  if ((ULONG_PTR)HeapEntry & (HEAP_ENTRY_SIZE - 1)) goto invalid_entry;
3164  if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY)) goto invalid_entry;
3165 
3166  BigAllocation = HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC;
3167  Segment = Heap->Segments[HeapEntry->SegmentOffset];
3168 
3169  if (BigAllocation &&
3170  (((ULONG_PTR)HeapEntry & (PAGE_SIZE - 1)) != FIELD_OFFSET(HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock)))
3171  goto invalid_entry;
3172 
3173  if (!BigAllocation && (HeapEntry->SegmentOffset >= HEAP_SEGMENTS ||
3174  !Segment ||
3175  HeapEntry < Segment->FirstEntry ||
3176  HeapEntry >= Segment->LastValidEntry))
3177  goto invalid_entry;
3178 
3179  if ((HeapEntry->Flags & HEAP_ENTRY_FILL_PATTERN) &&
3180  !RtlpCheckInUsePattern(HeapEntry))
3181  goto invalid_entry;
3182 
3183  /* Checks are done, if this is a virtual entry, that's all */
3184  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) return TRUE;
3185 
3186  /* Go through segments and check if this entry fits into any of them */
3187  for (SegmentOffset = 0; SegmentOffset < HEAP_SEGMENTS; SegmentOffset++)
3188  {
3189  Segment = Heap->Segments[SegmentOffset];
3190  if (!Segment) continue;
3191 
3192  if ((HeapEntry >= Segment->FirstEntry) &&
3193  (HeapEntry < Segment->LastValidEntry))
3194  {
3195  /* Got it */
3196  EntryFound = TRUE;
3197  break;
3198  }
3199  }
3200 
3201  /* Return our result of finding entry in the segments */
3202  return EntryFound;
3203 
3204 invalid_entry:
3205  DPRINT1("HEAP: Invalid heap entry %p in heap %p\n", HeapEntry, Heap);
3206  return FALSE;
3207 }
Definition: heap.h:321
#define TRUE
Definition: types.h:120
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:44
#define HEAP_SEGMENTS
Definition: heap.h:16
uint32_t ULONG_PTR
Definition: typedefs.h:63
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:250
unsigned char BOOLEAN
#define HEAP_ENTRY_BUSY
Definition: heap.h:41
_Inout_ PVOID Segment
Definition: exfuncs.h:893
#define HEAP_ENTRY_SIZE
Definition: heap.h:18
BOOLEAN NTAPI RtlpCheckInUsePattern(PHEAP_ENTRY HeapEntry)
Definition: heap.c:3114
#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:254
#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 3144 of file heap.c.

3147 {
3148  // We skip header validation for now
3149  return TRUE;
3150 }
#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 3210 of file heap.c.

3218 {
3219  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
3220  PLIST_ENTRY UcrEntry;
3222  PHEAP_ENTRY CurrentEntry;
3223  ULONG UnCommittedPages;
3224  ULONG UnCommittedRanges;
3225  ULONG PreviousSize;
3226 
3227  UnCommittedPages = 0;
3228  UnCommittedRanges = 0;
3229 
3230  if (IsListEmpty(&Segment->UCRSegmentList))
3231  {
3232  UcrEntry = NULL;
3233  UcrDescriptor = NULL;
3234  }
3235  else
3236  {
3237  UcrEntry = Segment->UCRSegmentList.Flink;
3238  UcrDescriptor = CONTAINING_RECORD(UcrEntry, HEAP_UCR_DESCRIPTOR, SegmentEntry);
3239  }
3240 
3241  if (Segment->BaseAddress == Heap)
3242  CurrentEntry = &Heap->Entry;
3243  else
3244  CurrentEntry = &Segment->Entry;
3245 
3246  while (CurrentEntry < Segment->LastValidEntry)
3247  {
3248  if (UcrDescriptor &&
3249  ((PVOID)CurrentEntry >= UcrDescriptor->Address))
3250  {
3251  DPRINT1("HEAP: Entry %p is not inside uncommited range [%p .. %p)\n",
3252  CurrentEntry, UcrDescriptor->Address,
3253  (PCHAR)UcrDescriptor->Address + UcrDescriptor->Size);
3254 
3255  return FALSE;
3256  }
3257 
3258  PreviousSize = 0;
3259 
3260  while (CurrentEntry < Segment->LastValidEntry)
3261  {
3262  if (PreviousSize != CurrentEntry->PreviousSize)
3263  {
3264  DPRINT1("HEAP: Entry %p has incorrect PreviousSize %x instead of %x\n",
3265  CurrentEntry, CurrentEntry->PreviousSize, PreviousSize);
3266 
3267  return FALSE;
3268  }
3269 
3270  PreviousSize = CurrentEntry->Size;
3271  Size = CurrentEntry->Size << HEAP_ENTRY_SHIFT;
3272 
3273  if (CurrentEntry->Flags & HEAP_ENTRY_BUSY)
3274  {
3275  if (TagEntries)
3276  {
3277  UNIMPLEMENTED;
3278  }
3279 
3280  /* Check fill pattern */
3281  if (CurrentEntry->Flags & HEAP_ENTRY_FILL_PATTERN)
3282  {
3283  if (!RtlpCheckInUsePattern(CurrentEntry))
3284  return FALSE;
3285  }
3286  }
3287  else
3288  {
3289  /* The entry is free, increase free entries count and total free size */
3290  *FreeEntriesCount = *FreeEntriesCount + 1;
3291  *TotalFreeSize += CurrentEntry->Size;
3292 
3293  if ((Heap->Flags & HEAP_FREE_CHECKING_ENABLED) &&
3294  (CurrentEntry->Flags & HEAP_ENTRY_FILL_PATTERN))
3295  {
3296  ByteSize = Size - sizeof(HEAP_FREE_ENTRY);
3297 
3298  if ((CurrentEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT) &&
3299  (ByteSize > sizeof(HEAP_FREE_ENTRY_EXTRA)))
3300  {
3301  ByteSize -= sizeof(HEAP_FREE_ENTRY_EXTRA);
3302  }
3303 
3304  Result = RtlCompareMemoryUlong((PCHAR)((PHEAP_FREE_ENTRY)CurrentEntry + 1),
3305  ByteSize,
3307 
3308  if (Result != ByteSize)
3309  {
3310  DPRINT1("HEAP: Free heap block %p modified at %p after it was freed\n",
3311  CurrentEntry,
3312  (PCHAR)(CurrentEntry + 1) + Result);
3313 
3314  return FALSE;
3315  }
3316  }
3317  }
3318 
3319  if (CurrentEntry->SegmentOffset != SegmentOffset)
3320  {
3321  DPRINT1("HEAP: Heap entry %p SegmentOffset is incorrect %x (should be %x)\n",
3322  CurrentEntry, SegmentOffset, CurrentEntry->SegmentOffset);
3323  return FALSE;
3324  }
3325 
3326  /* Check if it's the last entry */
3327  if (CurrentEntry->Flags & HEAP_ENTRY_LAST_ENTRY)
3328  {
3329  CurrentEntry = (PHEAP_ENTRY)((PCHAR)CurrentEntry + Size);
3330 
3331  if (!UcrDescriptor)
3332  {
3333  /* Check if it's not really the last one */
3334  if (CurrentEntry != Segment->LastValidEntry)
3335  {
3336  DPRINT1("HEAP: Heap entry %p is not last block in segment (%p)\n",
3337  CurrentEntry, Segment->LastValidEntry);
3338  return FALSE;
3339  }
3340  }
3341  else if (CurrentEntry != UcrDescriptor->Address)
3342  {
3343  DPRINT1("HEAP: Heap entry %p does not match next uncommitted address (%p)\n",
3344  CurrentEntry, UcrDescriptor->Address);
3345 
3346  return FALSE;
3347  }
3348  else
3349  {
3350  UnCommittedPages += (ULONG)(UcrDescriptor->Size / PAGE_SIZE);
3351  UnCommittedRanges++;
3352 
3353  CurrentEntry = (PHEAP_ENTRY)((PCHAR)UcrDescriptor->Address + UcrDescriptor->Size);
3354 
3355  /* Go to the next UCR descriptor */
3356  UcrEntry = UcrEntry->Flink;
3357  if (UcrEntry == &Segment->UCRSegmentList)
3358  {
3359  UcrEntry = NULL;
3360  UcrDescriptor = NULL;
3361  }
3362  else
3363  {
3364  UcrDescriptor = CONTAINING_RECORD(UcrEntry, HEAP_UCR_DESCRIPTOR, SegmentEntry);
3365  }
3366  }
3367 
3368  break;
3369  }
3370 
3371  /* Advance to the next entry */
3372  CurrentEntry = (PHEAP_ENTRY)((PCHAR)CurrentEntry + Size);
3373  }
3374  }
3375 
3376  /* Check total numbers of UCP and UCR */
3377  if (Segment->NumberOfUnCommittedPages != UnCommittedPages)
3378  {
3379  DPRINT1("HEAP: Segment %p NumberOfUnCommittedPages is invalid (%x != %x)\n",
3380  Segment, Segment->NumberOfUnCommittedPages, UnCommittedPages);
3381 
3382  return FALSE;
3383  }
3384 
3385  if (Segment->NumberOfUnCommittedRanges != UnCommittedRanges)
3386  {
3387  DPRINT1("HEAP: Segment %p NumberOfUnCommittedRanges is invalid (%x != %x)\n",
3388  Segment, Segment->NumberOfUnCommittedRanges, UnCommittedRanges);
3389 
3390  return FALSE;
3391  }
3392 
3393  return TRUE;
3394 }
signed char * PCHAR
Definition: retypes.h:7
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
#define TRUE
Definition: types.h:120
_Must_inspect_result_ NTSYSAPI SIZE_T NTAPI RtlCompareMemoryUlong(_In_reads_bytes_(Length) PVOID Source, _In_ SIZE_T Length, _In_ ULONG Pattern)
struct _HEAP_FREE_ENTRY HEAP_FREE_ENTRY
#define ARENA_FREE_FILLER
Definition: jsutils.c:62
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
Definition: heap.h:130
struct _HEAP_ENTRY * PHEAP_ENTRY
smooth NULL
Definition: ftsmooth.c:416
_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_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
_Inout_ PVOID Segment
Definition: exfuncs.h:893
struct _LIST_ENTRY * Flink
Definition: