ReactOS  0.4.15-dev-3165-gdf6fff7
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)
 
static BOOLEAN RtlpIsLastCommittedEntry (PHEAP_ENTRY Entry)
 
NTSTATUS NTAPI RtlpInitializeHeap (OUT PHEAP Heap, IN ULONG Flags, IN PHEAP_LOCK Lock OPTIONAL, IN PRTL_HEAP_PARAMETERS Parameters)
 
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)
 
static VOID RtlpRemoveFreeBlock (PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, 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)
 
static PHEAP_FREE_ENTRY RtlpFindAndCommitPages (PHEAP Heap, PHEAP_SEGMENT Segment, PSIZE_T Size, PVOID AddressRequested)
 
static VOID 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)
 
static PHEAP_FREE_ENTRY 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)
 
static PVOID RtlpAllocateNonDedicated (PHEAP Heap, ULONG Flags, SIZE_T Size, SIZE_T AllocationSize, SIZE_T Index, BOOLEAN HeapLocked)
 
PVOID NTAPI RtlAllocateHeap (IN PVOID HeapPtr, IN ULONG Flags, IN SIZE_T Size)
 
BOOLEAN NTAPI RtlFreeHeap (HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
 
BOOLEAN NTAPI RtlpGrowBlockInPlace (IN PHEAP Heap, IN ULONG Flags, IN PHEAP_ENTRY InUseEntry, IN SIZE_T Size, IN SIZE_T Index)
 
PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer (PHEAP_ENTRY HeapEntry)
 
PVOID NTAPI RtlReAllocateHeap (HANDLE HeapPtr, ULONG Flags, PVOID Ptr, SIZE_T Size)
 
ULONG NTAPI RtlCompactHeap (HANDLE Heap, ULONG Flags)
 
BOOLEAN NTAPI RtlLockHeap (IN HANDLE HeapPtr)
 
BOOLEAN NTAPI RtlUnlockHeap (HANDLE HeapPtr)
 
SIZE_T NTAPI RtlSizeHeap (HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
 
BOOLEAN NTAPI RtlpCheckInUsePattern (PHEAP_ENTRY HeapEntry)
 
BOOLEAN NTAPI RtlpValidateHeapHeaders (PHEAP Heap, BOOLEAN Recalculate)
 
BOOLEAN NTAPI RtlpValidateHeapEntry (PHEAP Heap, PHEAP_ENTRY HeapEntry)
 
BOOLEAN NTAPI RtlpValidateHeapSegment (PHEAP Heap, PHEAP_SEGMENT Segment, UCHAR SegmentOffset, PULONG FreeEntriesCount, PSIZE_T TotalFreeSize, PSIZE_T TagEntries, PSIZE_T PseudoTagEntries)
 
BOOLEAN NTAPI RtlpValidateHeap (PHEAP Heap, BOOLEAN ForceValidation)
 
BOOLEAN NTAPI RtlValidateHeap (HANDLE HeapPtr, ULONG Flags, PVOID Block)
 
NTSTATUS NTAPI RtlEnumProcessHeaps (PHEAP_ENUMERATION_ROUTINE HeapEnumerationRoutine, PVOID lParam)
 
ULONG NTAPI RtlGetProcessHeaps (ULONG count, HANDLE *heaps)
 
BOOLEAN NTAPI RtlValidateProcessHeaps (VOID)
 
BOOLEAN NTAPI RtlZeroHeap (IN PVOID HeapHandle, IN ULONG Flags)
 
BOOLEAN NTAPI RtlSetUserValueHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN PVOID UserValue)
 
BOOLEAN NTAPI RtlSetUserFlagsHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, IN ULONG UserFlagsReset, IN ULONG UserFlagsSet)
 
BOOLEAN NTAPI RtlGetUserInfoHeap (IN PVOID HeapHandle, IN ULONG Flags, IN PVOID BaseAddress, OUT PVOID *UserValue, OUT PULONG UserFlags)
 
NTSTATUS NTAPI RtlUsageHeap (IN HANDLE Heap, IN ULONG Flags, OUT PRTL_HEAP_USAGE Usage)
 
PWSTR NTAPI RtlQueryTagHeap (IN PVOID HeapHandle, IN ULONG Flags, IN USHORT TagIndex, IN BOOLEAN ResetCounters, OUT PRTL_HEAP_TAG_INFO HeapTagInfo)
 
ULONG NTAPI RtlExtendHeap (IN HANDLE Heap, IN ULONG Flags, IN PVOID P, IN SIZE_T Size)
 
ULONG NTAPI RtlCreateTagHeap (IN HANDLE HeapHandle, IN ULONG Flags, IN PWSTR TagName, IN PWSTR TagSubName)
 
NTSTATUS NTAPI RtlWalkHeap (IN HANDLE HeapHandle, IN PVOID HeapEntry)
 
PVOID NTAPI RtlProtectHeap (IN PVOID HeapHandle, IN BOOLEAN ReadOnly)
 
NTSTATUS NTAPI RtlSetHeapInformation (IN HANDLE HeapHandle OPTIONAL, IN HEAP_INFORMATION_CLASS HeapInformationClass, IN PVOID HeapInformation, IN SIZE_T HeapInformationLength)
 
NTSTATUS NTAPI RtlQueryHeapInformation (HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass, PVOID HeapInformation, SIZE_T HeapInformationLength, PSIZE_T ReturnLength OPTIONAL)
 
ULONG NTAPI RtlMultipleAllocateHeap (IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size, IN ULONG Count, OUT PVOID *Array)
 
ULONG NTAPI RtlMultipleFreeHeap (IN PVOID HeapHandle, IN ULONG Flags, IN ULONG Count, OUT PVOID *Array)
 
NTSTATUS NTAPI RtlQueryProcessHeapInformation (IN struct _DEBUG_BUFFER *DebugBuffer)
 

Variables

UCHAR RtlpBitsClearLow []
 
UCHAR FillPattern [HEAP_ENTRY_SIZE]
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 25 of file heap.c.

Function Documentation

◆ RtlAllocateHeap()

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

Definition at line 2049 of file heap.c.

2052 {
2053  PHEAP Heap = (PHEAP)HeapPtr;
2055  SIZE_T Index;
2056  UCHAR EntryFlags = HEAP_ENTRY_BUSY;
2057  BOOLEAN HeapLocked = FALSE;
2058  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualBlock = NULL;
2059  PHEAP_ENTRY_EXTRA Extra;
2060  NTSTATUS Status;
2061 
2062  /* Force flags */
2063  Flags |= Heap->ForceFlags;
2064 
2065  /* Call special heap */
2066  if (RtlpHeapIsSpecial(Flags))
2067  return RtlDebugAllocateHeap(Heap, Flags, Size);
2068 
2069  /* Check for the maximum size */
2070  if (Size >= 0x80000000)
2071  {
2073  DPRINT1("HEAP: Allocation failed!\n");
2074  return NULL;
2075  }
2076 
2078  {
2079  DPRINT1("HEAP: RtlAllocateHeap is called with unsupported flags %x, ignoring\n", Flags);
2080  }
2081 
2082  //DPRINT("RtlAllocateHeap(%p %x %x)\n", Heap, Flags, Size);
2083 
2084  /* Calculate allocation size and index */
2085  if (Size)
2086  AllocationSize = Size;
2087  else
2088  AllocationSize = 1;
2089  AllocationSize = (AllocationSize + Heap->AlignRound) & Heap->AlignMask;
2090 
2091  /* Add extra flags in case of settable user value feature is requested,
2092  or there is a tag (small or normal) or there is a request to
2093  capture stack backtraces */
2095  Heap->PseudoTagEntries)
2096  {
2097  /* Add flag which means that the entry will have extra stuff attached */
2098  EntryFlags |= HEAP_ENTRY_EXTRA_PRESENT;
2099 
2100  /* Account for extra stuff size */
2101  AllocationSize += sizeof(HEAP_ENTRY_EXTRA);
2102  }
2103 
2104  /* Add settable user flags, if any */
2105  EntryFlags |= (Flags & HEAP_SETTABLE_USER_FLAGS) >> 4;
2106 
2108 
2109  /* Acquire the lock if necessary */
2110  if (!(Flags & HEAP_NO_SERIALIZE))
2111  {
2113  HeapLocked = TRUE;
2114  }
2115 
2116  /* Depending on the size, the allocation is going to be done from dedicated,
2117  non-dedicated lists or a virtual block of memory */
2118  if (Index <= Heap->VirtualMemoryThreshold)
2119  {
2120  PHEAP_ENTRY InUseEntry;
2121  PHEAP_FREE_ENTRY FreeEntry;
2122 
2123  /* First quick check: Anybody here ? */
2124  if (IsListEmpty(&Heap->FreeLists))
2125  return RtlpAllocateNonDedicated(Heap, Flags, Size, AllocationSize, Index, HeapLocked);
2126 
2127  /* Second quick check: Is there someone for us ? */
2128  FreeEntry = CONTAINING_RECORD(Heap->FreeLists.Blink, HEAP_FREE_ENTRY, FreeList);
2129  if (FreeEntry->Size < Index)
2130  {
2131  /* Largest entry in the list doesnt fit. */
2132  return RtlpAllocateNonDedicated(Heap, Flags, Size, AllocationSize, Index, HeapLocked);
2133  }
2134 
2135  if (Index > Heap->DeCommitFreeBlockThreshold)
2136  {
2137  /* Find an entry from the non dedicated list */
2138  FreeEntry = CONTAINING_RECORD(Heap->FreeHints[0],
2140  FreeList);
2141 
2142  while (FreeEntry->Size < Index)
2143  {
2144  /* We made sure we had the right size available */
2145  ASSERT(FreeEntry->FreeList.Flink != &Heap->FreeLists);
2146  FreeEntry = CONTAINING_RECORD(FreeEntry->FreeList.Flink,
2148  FreeList);
2149  }
2150  }
2151  else
2152  {
2153  /* Get the free entry from the hint */
2155  ASSERT(HintIndex != 0xFFFFFFFF);
2156  ASSERT((HintIndex >= (Index - 1)) || (HintIndex == 0));
2157  FreeEntry = CONTAINING_RECORD(Heap->FreeHints[HintIndex],
2159  FreeList);
2160  }
2161 
2162  /* Remove the free block, split, profit. */
2163  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE);
2164  InUseEntry = RtlpSplitEntry(Heap, Flags, FreeEntry, AllocationSize, Index, Size);
2165 
2166  /* Release the lock */
2167  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2168 
2169  /* Zero memory if that was requested */
2170  if (Flags & HEAP_ZERO_MEMORY)
2171  RtlZeroMemory(InUseEntry + 1, Size);
2172  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
2173  {
2174  /* Fill this block with a special pattern */
2175  RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
2176  }
2177 
2178  /* Fill tail of the block with a special pattern too if requested */
2179  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
2180  {
2181  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY), HEAP_TAIL_FILL);
2182  InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
2183  }
2184 
2185  /* Prepare extra if it's present */
2186  if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
2187  {
2188  Extra = RtlpGetExtraStuffPointer(InUseEntry);
2189  RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
2190 
2191  // TODO: Tagging
2192  }
2193 
2194  /* User data starts right after the entry's header */
2195  return InUseEntry + 1;
2196  }
2197 
2198  if (Heap->Flags & HEAP_GROWABLE)
2199  {
2200  /* We've got a very big allocation request, satisfy it by directly allocating virtual memory */
2201  AllocationSize += sizeof(HEAP_VIRTUAL_ALLOC_ENTRY) - sizeof(HEAP_ENTRY);
2202 
2203  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
2204  (PVOID *)&VirtualBlock,
2205  0,
2206  &AllocationSize,
2207  MEM_COMMIT,
2208  PAGE_READWRITE);
2209 
2210  if (!NT_SUCCESS(Status))
2211  {
2212  // Set STATUS!
2213  /* Release the lock */
2214  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2215  DPRINT1("HEAP: Allocation failed!\n");
2216  return NULL;
2217  }
2218 
2219  /* Initialize the newly allocated block */
2220  VirtualBlock->BusyBlock.Size = (USHORT)(AllocationSize - Size);
2221  ASSERT(VirtualBlock->BusyBlock.Size >= sizeof(HEAP_VIRTUAL_ALLOC_ENTRY));
2222  VirtualBlock->BusyBlock.Flags = EntryFlags | HEAP_ENTRY_VIRTUAL_ALLOC | HEAP_ENTRY_EXTRA_PRESENT;
2223  VirtualBlock->CommitSize = AllocationSize;
2224  VirtualBlock->ReserveSize = AllocationSize;
2225 
2226  /* Insert it into the list of virtual allocations */
2227  InsertTailList(&Heap->VirtualAllocdBlocks, &VirtualBlock->Entry);
2228 
2229  /* Release the lock */
2230  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2231 
2232  /* Return pointer to user data */
2233  return VirtualBlock + 1;
2234  }
2235 
2236  /* Generate an exception */
2238  {
2239  EXCEPTION_RECORD ExceptionRecord;
2240 
2241  ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY;
2242  ExceptionRecord.ExceptionRecord = NULL;
2243  ExceptionRecord.NumberParameters = 1;
2244  ExceptionRecord.ExceptionFlags = 0;
2245  ExceptionRecord.ExceptionInformation[0] = AllocationSize;
2246 
2247  RtlRaiseException(&ExceptionRecord);
2248  }
2249 
2251 
2252  /* Release the lock */
2253  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2254  DPRINT1("HEAP: Allocation failed!\n");
2255  return NULL;
2256 }
signed char * PCHAR
Definition: retypes.h:7
LIST_ENTRY Entry
Definition: heap.h:309
#define ARENA_INUSE_FILLER
Definition: oleaut.c:105
Definition: heap.h:307
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:43
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#define TRUE
Definition: types.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
static VOID RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN NoFill)
Definition: heap.c:422
LIST_ENTRY FreeLists
Definition: heap.h:259
LONG NTSTATUS
Definition: precomp.h:26
LIST_ENTRY FreeList
Definition: heap.h:131
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define HEAP_EXTRA_FLAGS_MASK
Definition: heap.h:35
NTSYSAPI ULONG WINAPI RtlFindSetBits(PCRTL_BITMAP, ULONG, ULONG)
#define InsertTailList(ListHead, Entry)
NTSYSAPI VOID NTAPI RtlRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord)
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#define MEM_COMMIT
Definition: nt_native.h:1313
PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer(PHEAP_ENTRY HeapEntry)
Definition: heap.c:2632
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
_In_ ULONG _In_ ULONG HintIndex
Definition: rtlfuncs.h:609
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define HEAP_CREATE_ENABLE_TRACING
Definition: nt_native.h:1702
DWORD ExceptionCode
Definition: compat.h:208
ULONG_PTR AlignMask
Definition: heap.h:250
SIZE_T ReserveSize
Definition: heap.h:312
#define FALSE
Definition: types.h:117
Definition: heap.h:291
PHEAP_LOCK LockVariable
Definition: heap.h:260
PLIST_ENTRY FreeHints[ANYSIZE_ARRAY]
Definition: heap.h:268
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries
Definition: heap.h:258
Definition: heap.h:129
unsigned char BOOLEAN
RTL_BITMAP FreeHintBitmap
Definition: heap.h:267
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
#define HEAP_ENTRY_SHIFT
Definition: heap.h:21
static PVOID RtlpAllocateNonDedicated(PHEAP Heap, ULONG Flags, SIZE_T Size, SIZE_T AllocationSize, SIZE_T Index, BOOLEAN HeapLocked)
Definition: heap.c:1957
#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
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
SIZE_T CommitSize
Definition: heap.h:311
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
_In_ WDFCOLLECTION _In_ ULONG Index
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:251
#define HEAP_GROWABLE
Definition: nt_native.h:1693
struct _HEAP_VIRTUAL_ALLOC_ENTRY HEAP_VIRTUAL_ALLOC_ENTRY
#define HEAP_SETTABLE_USER_FLAGS
Definition: nt_native.h:1708
unsigned char UCHAR
Definition: xmlstorage.h:181
PHEAP_ENTRY NTAPI RtlpSplitEntry(PHEAP Heap, ULONG Flags, PHEAP_FREE_ENTRY FreeBlock, SIZE_T AllocationSize, SIZE_T Index, SIZE_T Size)
Definition: heap.c:1817
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:42
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:319
ULONG_PTR SIZE_T
Definition: typedefs.h:80
ULONG_PTR AlignRound
Definition: heap.h:249
Definition: heap.h:135
unsigned short USHORT
Definition: pedump.c:61
ULONG Flags
Definition: heap.h:226
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
struct _HEAP_ENTRY_EXTRA HEAP_ENTRY_EXTRA
#define NULL
Definition: types.h:112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define DPRINT1
Definition: precomp.h:8
PVOID NTAPI RtlDebugAllocateHeap(PVOID HeapPtr, ULONG Flags, SIZE_T Size)
Definition: heapdbg.c:130
SIZE_T DeCommitFreeBlockThreshold
Definition: heap.h:237
#define HEAP_TAIL_FILL
Definition: heap.h:27
unsigned int ULONG
Definition: retypes.h:1
struct _HEAP * PHEAP
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
DWORD ExceptionFlags
Definition: compat.h:209
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
ULONG ForceFlags
Definition: heap.h:227
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:41
HEAP_ENTRY BusyBlock
Definition: heap.h:313
DWORD NumberParameters
Definition: compat.h:212
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
Definition: heap.c:51
#define PAGE_READWRITE
Definition: nt_native.h:1304
FORCEINLINE BOOLEAN RtlpHeapIsSpecial(ULONG Flags)
Definition: heap.h:59

◆ RtlCompactHeap()

ULONG NTAPI RtlCompactHeap ( HANDLE  Heap,
ULONG  Flags 
)

Definition at line 3084 of file heap.c.

3086 {
3087  UNIMPLEMENTED;
3088  return 0;
3089 }
#define UNIMPLEMENTED
Definition: debug.h:115

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

◆ RtlCreateHeap()

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

Definition at line 1403 of file heap.c.

1409 {
1410  PVOID CommittedAddress = NULL, UncommittedAddress = NULL;
1411  PHEAP Heap = NULL;
1412  RTL_HEAP_PARAMETERS SafeParams = {0};
1413  ULONG_PTR MaximumUserModeAddress;
1414  SYSTEM_BASIC_INFORMATION SystemInformation;
1415  MEMORY_BASIC_INFORMATION MemoryInfo;
1416  ULONG NtGlobalFlags = RtlGetNtGlobalFlags();
1417  ULONG HeapSegmentFlags = 0;
1418  NTSTATUS Status;
1419  ULONG MaxBlockSize;
1420 
1421  /* Check for a special heap */
1422  if (RtlpPageHeapEnabled && !Addr && !Lock)
1423  {
1424  Heap = RtlpPageHeapCreate(Flags, Addr, TotalSize, CommitSize, Lock, Parameters);
1425  if (Heap) return Heap;
1426 
1427  /* Reset a special Parameters == -1 hack */
1428  if ((ULONG_PTR)Parameters == (ULONG_PTR)-1)
1429  Parameters = NULL;
1430  else
1431  DPRINT1("Enabling page heap failed\n");
1432  }
1433 
1434  /* Check validation flags */
1436  {
1437  DPRINT1("Invalid flags 0x%08x, fixing...\n", Flags);
1439  }
1440 
1441  /* Capture parameters */
1442  if (Parameters)
1443  {
1444  _SEH2_TRY
1445  {
1446  /* If size of structure correct, then copy it */
1447  if (Parameters->Length == sizeof(RTL_HEAP_PARAMETERS))
1448  RtlCopyMemory(&SafeParams, Parameters, sizeof(RTL_HEAP_PARAMETERS));
1449  }
1451  {
1452  _SEH2_YIELD(return NULL);
1453  }
1454  _SEH2_END;
1455  }
1456 
1457  Parameters = &SafeParams;
1458 
1459  /* Check global flags */
1460  if (NtGlobalFlags & FLG_HEAP_DISABLE_COALESCING)
1462 
1463  if (NtGlobalFlags & FLG_HEAP_ENABLE_FREE_CHECK)
1465 
1466  if (NtGlobalFlags & FLG_HEAP_ENABLE_TAIL_CHECK)
1468 
1469  if (RtlpGetMode() == UserMode)
1470  {
1471  /* Also check these flags if in usermode */
1472  if (NtGlobalFlags & FLG_HEAP_VALIDATE_ALL)
1474 
1475  if (NtGlobalFlags & FLG_HEAP_VALIDATE_PARAMETERS)
1477 
1478  if (NtGlobalFlags & FLG_USER_STACK_TRACE_DB)
1480  }
1481 
1482  /* Set tunable parameters */
1484 
1485  /* Get the max um address */
1487  &SystemInformation,
1488  sizeof(SystemInformation),
1489  NULL);
1490 
1491  if (!NT_SUCCESS(Status))
1492  {
1493  DPRINT1("Getting max usermode address failed with status 0x%08x\n", Status);
1494  return NULL;
1495  }
1496 
1497  MaximumUserModeAddress = SystemInformation.MaximumUserModeAddress;
1498 
1499  /* Calculate max alloc size */
1500  if (!Parameters->MaximumAllocationSize)
1501  Parameters->MaximumAllocationSize = MaximumUserModeAddress - (ULONG_PTR)0x10000 - PAGE_SIZE;
1502 
1503  MaxBlockSize = 0x80000 - PAGE_SIZE;
1504 
1505  if (!Parameters->VirtualMemoryThreshold ||
1506  Parameters->VirtualMemoryThreshold > MaxBlockSize)
1507  {
1508  Parameters->VirtualMemoryThreshold = MaxBlockSize;
1509  }
1510 
1511  if (Parameters->DeCommitFreeBlockThreshold != PAGE_SIZE)
1512  {
1513  DPRINT1("WARNING: Ignoring DeCommitFreeBlockThreshold %lx, setting it to PAGE_SIZE.\n",
1514  Parameters->DeCommitFreeBlockThreshold);
1515  Parameters->DeCommitFreeBlockThreshold = PAGE_SIZE;
1516  }
1517 
1518  /* Check reserve/commit sizes and set default values */
1519  if (!CommitSize)
1520  {
1522  if (TotalSize)
1523  TotalSize = ROUND_UP(TotalSize, PAGE_SIZE);
1524  else
1525  TotalSize = 64 * PAGE_SIZE;
1526  }
1527  else
1528  {
1529  /* Round up the commit size to be at least the page size */
1531 
1532  if (TotalSize)
1533  TotalSize = ROUND_UP(TotalSize, PAGE_SIZE);
1534  else
1535  TotalSize = ROUND_UP(CommitSize, 16 * PAGE_SIZE);
1536  }
1537 
1538  /* Call special heap */
1539  if (RtlpHeapIsSpecial(Flags))
1540  return RtlDebugCreateHeap(Flags, Addr, TotalSize, CommitSize, Lock, Parameters);
1541 
1542  /* Without serialization, a lock makes no sense */
1543  if ((Flags & HEAP_NO_SERIALIZE) && (Lock != NULL))
1544  return NULL;
1545 
1546  /* See if we are already provided with an address for the heap */
1547  if (Addr)
1548  {
1549  if (Parameters->CommitRoutine)
1550  {
1551  /* There is a commit routine, so no problem here, check params */
1552  if ((Flags & HEAP_GROWABLE) ||
1553  !Parameters->InitialCommit ||
1554  !Parameters->InitialReserve ||
1555  (Parameters->InitialCommit > Parameters->InitialReserve))
1556  {
1557  /* Fail */
1558  return NULL;
1559  }
1560 
1561  /* Calculate committed and uncommitted addresses */
1562  CommittedAddress = Addr;
1563  UncommittedAddress = (PCHAR)Addr + Parameters->InitialCommit;
1564  TotalSize = Parameters->InitialReserve;
1565 
1566  /* Zero the initial page ourselves */
1567  RtlZeroMemory(CommittedAddress, PAGE_SIZE);
1568  }
1569  else
1570  {
1571  /* Commit routine is absent, so query how much memory caller reserved */
1573  Addr,
1575  &MemoryInfo,
1576  sizeof(MemoryInfo),
1577  NULL);
1578 
1579  if (!NT_SUCCESS(Status))
1580  {
1581  DPRINT1("Querying amount of user supplied memory failed with status 0x%08X\n", Status);
1582  return NULL;
1583  }
1584 
1585  /* Validate it */
1586  if (MemoryInfo.BaseAddress != Addr ||
1587  MemoryInfo.State == MEM_FREE)
1588  {
1589  return NULL;
1590  }
1591 
1592  /* Validation checks passed, set committed/uncommitted addresses */
1593  CommittedAddress = Addr;
1594 
1595  /* Check if it's committed or not */
1596  if (MemoryInfo.State == MEM_COMMIT)
1597  {
1598  /* Zero it out because it's already committed */
1599  RtlZeroMemory(CommittedAddress, PAGE_SIZE);
1600 
1601  /* Calculate uncommitted address value */
1602  CommitSize = MemoryInfo.RegionSize;
1603  TotalSize = CommitSize;
1604  UncommittedAddress = (PCHAR)Addr + CommitSize;
1605 
1606  /* Check if uncommitted address is reserved */
1608  UncommittedAddress,
1610  &MemoryInfo,
1611  sizeof(MemoryInfo),
1612  NULL);
1613 
1614  if (NT_SUCCESS(Status) &&
1615  MemoryInfo.State == MEM_RESERVE)
1616  {
1617  /* It is, so add it up to the reserve size */
1618  TotalSize += MemoryInfo.RegionSize;
1619  }
1620  }
1621  else
1622  {
1623  /* It's not committed, inform following code that a commit is necessary */
1625  UncommittedAddress = Addr;
1626  }
1627  }
1628 
1629  /* Mark this as a user-committed mem */
1630  HeapSegmentFlags = HEAP_USER_ALLOCATED;
1631  Heap = (PHEAP)Addr;
1632  }
1633  else
1634  {
1635  /* Check commit routine */
1636  if (Parameters->CommitRoutine) return NULL;
1637 
1638  /* Reserve memory */
1639  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1640  (PVOID *)&Heap,
1641  0,
1642  &TotalSize,
1643  MEM_RESERVE,
1644  PAGE_READWRITE);
1645 
1646  if (!NT_SUCCESS(Status))
1647  {
1648  DPRINT1("Failed to reserve memory with status 0x%08x\n", Status);
1649  return NULL;
1650  }
1651 
1652  /* Set base addresses */
1653  CommittedAddress = Heap;
1654  UncommittedAddress = Heap;
1655  }
1656 
1657  /* Check if we need to commit something */
1658  if (CommittedAddress == UncommittedAddress)
1659  {
1660  /* Commit the required size */
1661  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1662  &CommittedAddress,
1663  0,
1664  &CommitSize,
1665  MEM_COMMIT,
1666  PAGE_READWRITE);
1667 
1668  DPRINT("Committed %Iu bytes at base %p\n", CommitSize, CommittedAddress);
1669 
1670  if (!NT_SUCCESS(Status))
1671  {
1672  DPRINT1("Failure, Status 0x%08X\n", Status);
1673 
1674  /* Release memory if it was reserved */
1675  if (!Addr) ZwFreeVirtualMemory(NtCurrentProcess(),
1676  (PVOID *)&Heap,
1677  &TotalSize,
1678  MEM_RELEASE);
1679 
1680  return NULL;
1681  }
1682 
1683  /* Calculate new uncommitted address */
1684  UncommittedAddress = (PCHAR)UncommittedAddress + CommitSize;
1685  }
1686 
1687  /* Initialize the heap */
1689  if (!NT_SUCCESS(Status))
1690  {
1691  DPRINT1("Failed to initialize heap (%x)\n", Status);
1692  return NULL;
1693  }
1694 
1695  /* Initialize heap's first segment */
1696  Status = RtlpInitializeHeapSegment(Heap, (PHEAP_SEGMENT) (Heap), 0, HeapSegmentFlags, TotalSize, CommitSize);
1697  if (!NT_SUCCESS(Status))
1698  {
1699  DPRINT1("Failed to initialize heap segment (%x)\n", Status);
1700  return NULL;
1701  }
1702 
1703  DPRINT("Created heap %p, CommitSize %x, ReserveSize %x\n", Heap, CommitSize, TotalSize);
1704 
1705  /* Add heap to process list in case of usermode heap */
1706  if (RtlpGetMode() == UserMode)
1707  {
1709 
1710  // FIXME: What about lookasides?
1711  }
1712 
1713  return Heap;
1714 }
#define FLG_HEAP_DISABLE_COALESCING
Definition: pstypes.h:80
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:863
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
#define FLG_HEAP_ENABLE_TAIL_CHECK
Definition: pstypes.h:60
LONG NTSTATUS
Definition: precomp.h:26
#define HEAP_DISABLE_COALESCE_ON_FREE
Definition: nt_native.h:1699
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
#define MEM_COMMIT
Definition: nt_native.h:1313
BOOLEAN RtlpPageHeapEnabled
Definition: heappage.c:106
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define HEAP_SKIP_VALIDATION_CHECKS
Definition: rtltypes.h:165
VOID NTAPI RtlpSetHeapParameters(IN PRTL_HEAP_PARAMETERS Parameters)
Definition: libsupp.c:174
#define MEM_RESERVE
Definition: nt_native.h:1314
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:237
#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)
Status
Definition: gdiplustypes.h:24
#define MEM_FREE
Definition: nt_native.h:1317
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#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:106
#define HEAP_USER_ALLOCATED
Definition: heap.h:55
#define FLG_HEAP_ENABLE_FREE_CHECK
Definition: pstypes.h:61
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_SEH2_END
Definition: create.c:4400
#define NULL
Definition: types.h:112
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:1002
#define DPRINT1
Definition: precomp.h:8
#define FLG_HEAP_VALIDATE_ALL
Definition: pstypes.h:63
#define MEM_RELEASE
Definition: nt_native.h:1316
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
unsigned int ULONG
Definition: retypes.h:1
struct _HEAP * PHEAP
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define FLG_USER_STACK_TRACE_DB
Definition: pstypes.h:67
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define HEAP_CAPTURE_STACK_BACKTRACES
Definition: rtltypes.h:164
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define DPRINT
Definition: sndvol32.h:71
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:59
#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 4031 of file heap.c.

4035 {
4036  /* TODO */
4037  UNIMPLEMENTED;
4038  return 0;
4039 }
#define UNIMPLEMENTED
Definition: debug.h:115

Referenced by HeapCreateTagsW(), and SmpInit().

◆ RtlDestroyHeap()

HANDLE NTAPI RtlDestroyHeap ( HANDLE  HeapPtr)

Definition at line 1729 of file heap.c.

1730 {
1731  PHEAP Heap = (PHEAP)HeapPtr;
1732  PLIST_ENTRY Current;
1733  PHEAP_UCR_SEGMENT UcrSegment;
1734  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
1736  SIZE_T Size;
1737  LONG i;
1739 
1740  if (!HeapPtr) return NULL;
1741 
1742  /* Call page heap routine if required */
1743  if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS) return RtlpPageHeapDestroy(HeapPtr);
1744 
1745  /* Call special heap */
1746  if (RtlpHeapIsSpecial(Heap->Flags))
1747  {
1748  if (!RtlDebugDestroyHeap(Heap)) return HeapPtr;
1749  }
1750 
1751  /* Check for a process heap */
1752  if (RtlpGetMode() == UserMode &&
1753  HeapPtr == NtCurrentPeb()->ProcessHeap) return HeapPtr;
1754 
1755  /* Free up all big allocations */
1756  Current = Heap->VirtualAllocdBlocks.Flink;
1757  while (Current != &Heap->VirtualAllocdBlocks)
1758  {
1759  VirtualEntry = CONTAINING_RECORD(Current, HEAP_VIRTUAL_ALLOC_ENTRY, Entry);
1760  BaseAddress = (PVOID)VirtualEntry;
1761  Current = Current->Flink;
1762  Size = 0;
1763  ZwFreeVirtualMemory(NtCurrentProcess(),
1764  &BaseAddress,
1765  &Size,
1766  MEM_RELEASE);
1767  }
1768 
1769  /* Delete tags and remove heap from the process heaps list in user mode */
1770  if (RtlpGetMode() == UserMode)
1771  {
1772  // FIXME DestroyTags
1774  }
1775 
1776  /* Delete the heap lock */
1777  if (!(Heap->Flags & HEAP_NO_SERIALIZE))
1778  {
1779  /* Delete it if it wasn't user allocated */
1780  if (!(Heap->Flags & HEAP_LOCK_USER_ALLOCATED))
1782 
1783  /* Clear out the lock variable */
1784  Heap->LockVariable = NULL;
1785  }
1786 
1787  /* Free UCR segments if any were created */
1788  Current = Heap->UCRSegments.Flink;
1789  while (Current != &Heap->UCRSegments)
1790  {
1791  UcrSegment = CONTAINING_RECORD(Current, HEAP_UCR_SEGMENT, ListEntry);
1792 
1793  /* Advance to the next descriptor */
1794  Current = Current->Flink;
1795 
1796  BaseAddress = (PVOID)UcrSegment;
1797  Size = 0;
1798 
1799  /* Release that memory */
1800  ZwFreeVirtualMemory(NtCurrentProcess(),
1801  &BaseAddress,
1802  &Size,
1803  MEM_RELEASE);
1804  }
1805 
1806  /* Go through segments and destroy them */
1807  for (i = HEAP_SEGMENTS - 1; i >= 0; i--)
1808  {
1809  Segment = Heap->Segments[i];
1811  }
1812 
1813  return NULL;
1814 }
Definition: heap.h:307
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
#define HEAP_SEGMENTS
Definition: heap.h:15
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
static PVOID
Definition: heap.c:41
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:253
long LONG
Definition: pedump.c:60
PHEAP_LOCK LockVariable
Definition: heap.h:260
VOID NTAPI RtlpRemoveHeapFromProcessList(struct _HEAP *Heap)
Definition: libsupp.c:244
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PVOID NTAPI RtlpPageHeapDestroy(HANDLE HeapPtr)
Definition: heappage.c:1613
BOOLEAN NTAPI RtlDebugDestroyHeap(HANDLE HeapPtr)
Definition: heapdbg.c:95
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
LIST_ENTRY UCRSegments
Definition: heap.h:248
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:251
#define HEAP_LOCK_USER_ALLOCATED
Definition: rtltypes.h:168
Definition: typedefs.h:119
#define HEAP_FLAG_PAGE_ALLOCS
Definition: rtltypes.h:160
HANDLE ProcessHeap
Definition: servman.c:15
ULONG_PTR SIZE_T
Definition: typedefs.h:80
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
#define NtCurrentPeb()
Definition: FLS.c:22
ULONG Flags
Definition: heap.h:226
#define NULL
Definition: types.h:112
#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:227
VOID NTAPI RtlpDestroyHeapSegment(PHEAP_SEGMENT Segment)
Definition: heap.c:1118
base of all file and directory entries
Definition: entries.h:82
Definition: heap.c:51
FORCEINLINE BOOLEAN RtlpHeapIsSpecial(ULONG Flags)
Definition: heap.h:59

◆ RtlEnumProcessHeaps()

NTSTATUS NTAPI RtlEnumProcessHeaps ( PHEAP_ENUMERATION_ROUTINE  HeapEnumerationRoutine,
PVOID  lParam 
)

Definition at line 3762 of file heap.c.

3764 {
3765  UNIMPLEMENTED;
3766  return STATUS_NOT_IMPLEMENTED;
3767 }
return STATUS_NOT_IMPLEMENTED
#define UNIMPLEMENTED
Definition: debug.h:115

◆ RtlExtendHeap()

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

Definition at line 4019 of file heap.c.

4023 {
4024  /* TODO */
4025  UNIMPLEMENTED;
4026  return 0;
4027 }
#define UNIMPLEMENTED
Definition: debug.h:115

◆ RtlFreeHeap()

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

Definition at line 2267 of file heap.c.

2272 {
2273  PHEAP Heap;
2274  PHEAP_ENTRY HeapEntry;
2275  USHORT TagIndex = 0;
2276  SIZE_T BlockSize;
2277  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
2278  BOOLEAN Locked = FALSE;
2279  NTSTATUS Status;
2280 
2281  /* Freeing NULL pointer is a legal operation */
2282  if (!Ptr) return TRUE;
2283 
2284  /* Get pointer to the heap and force flags */
2285  Heap = (PHEAP)HeapPtr;
2286  Flags |= Heap->ForceFlags;
2287 
2288  /* Call special heap */
2289  if (RtlpHeapIsSpecial(Flags))
2290  return RtlDebugFreeHeap(Heap, Flags, Ptr);
2291 
2292  /* Get pointer to the heap entry */
2293  HeapEntry = (PHEAP_ENTRY)Ptr - 1;
2294 
2295  /* Protect with SEH in case the pointer is not valid */
2296  _SEH2_TRY
2297  {
2298  /* Check this entry, fail if it's invalid */
2299  if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY) ||
2300  (((ULONG_PTR)Ptr & 0x7) != 0) ||
2301  (HeapEntry->SegmentOffset >= HEAP_SEGMENTS))
2302  {
2303  /* This is an invalid block */
2304  DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
2306  _SEH2_YIELD(return FALSE);
2307  }
2308  }
2310  {
2311  /* The pointer was invalid */
2312  DPRINT1("HEAP: Trying to free an invalid address %p!\n", Ptr);
2314  _SEH2_YIELD(return FALSE);
2315  }
2316  _SEH2_END;
2317 
2318  /* Lock if necessary */
2319  if (!(Flags & HEAP_NO_SERIALIZE))
2320  {
2322  Locked = TRUE;
2323  }
2324 
2325  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
2326  {
2327  /* Big allocation */
2328  VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
2329 
2330  /* Remove it from the list */
2331  RemoveEntryList(&VirtualEntry->Entry);
2332 
2333  // TODO: Tagging
2334 
2335  BlockSize = 0;
2336  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
2337  (PVOID *)&VirtualEntry,
2338  &BlockSize,
2339  MEM_RELEASE);
2340 
2341  if (!NT_SUCCESS(Status))
2342  {
2343  DPRINT1("HEAP: Failed releasing memory with Status 0x%08X. Heap %p, ptr %p, base address %p\n",
2344  Status, Heap, Ptr, VirtualEntry);
2346  }
2347  }
2348  else
2349  {
2350  /* Normal allocation */
2351  BlockSize = HeapEntry->Size;
2352 
2353  // TODO: Tagging
2354 
2355  /* Coalesce in kernel mode, and in usermode if it's not disabled */
2356  if (RtlpGetMode() == KernelMode ||
2358  {
2359  HeapEntry = (PHEAP_ENTRY)RtlpCoalesceFreeBlocks(Heap,
2360  (PHEAP_FREE_ENTRY)HeapEntry,
2361  &BlockSize,
2362  FALSE);
2363  }
2364 
2365  /* See if we should decommit this block */
2366  if ((BlockSize >= Heap->DeCommitFreeBlockThreshold) ||
2367  (Heap->TotalFreeSize + BlockSize >= Heap->DeCommitTotalFreeThreshold))
2368  {
2369  RtlpDeCommitFreeBlock(Heap, (PHEAP_FREE_ENTRY)HeapEntry, BlockSize);
2370  }
2371  else
2372  {
2373  /* Insert into the free list */
2374  RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY)HeapEntry, BlockSize);
2375 
2376  if (RtlpGetMode() == UserMode &&
2377  TagIndex != 0)
2378  {
2379  // FIXME: Tagging
2380  UNIMPLEMENTED;
2381  }
2382  }
2383  }
2384 
2385  /* Release the heap lock */
2386  if (Locked) RtlLeaveHeapLock(Heap->LockVariable);
2387 
2388  return TRUE;
2389 }
LIST_ENTRY Entry
Definition: heap.h:309
Definition: heap.h:307
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:43
KPROCESSOR_MODE NTAPI RtlpGetMode(VOID)
Definition: libsupp.c:53
SIZE_T TotalFreeSize
Definition: heap.h:239
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceFreeBlocks(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, PSIZE_T FreeSize, BOOLEAN Remove)
Definition: heap.c:1150
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
#define HEAP_SEGMENTS
Definition: heap.h:15
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
LONG NTSTATUS
Definition: precomp.h:26
#define HEAP_DISABLE_COALESCE_ON_FREE
Definition: nt_native.h:1699
_SEH2_TRY
Definition: create.c:4226
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define FALSE
Definition: types.h:117
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:207
PHEAP_LOCK LockVariable
Definition: heap.h:260
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:357
Definition: heap.h:129
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:40
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
Status
Definition: gdiplustypes.h:24
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
static VOID RtlpDeCommitFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T Size)
Definition: heap.c:834
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_SEH2_END
Definition: create.c:4400
Definition: heap.h:135
unsigned short USHORT
Definition: pedump.c:61
ULONG Flags
Definition: heap.h:226
#define DPRINT1
Definition: precomp.h:8
#define MEM_RELEASE
Definition: nt_native.h:1316
SIZE_T DeCommitFreeBlockThreshold
Definition: heap.h:237
struct _HEAP * PHEAP
#define UNIMPLEMENTED
Definition: debug.h:115
#define ULONG_PTR
Definition: config.h:101
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
ULONG ForceFlags
Definition: heap.h:227
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
SIZE_T DeCommitTotalFreeThreshold
Definition: heap.h:238
Definition: heap.c:51
FORCEINLINE BOOLEAN RtlpHeapIsSpecial(ULONG Flags)
Definition: heap.h:59

◆ RtlGetProcessHeaps()

ULONG NTAPI RtlGetProcessHeaps ( ULONG  count,
HANDLE heaps 
)

Definition at line 3774 of file heap.c.

3776 {
3777  UNIMPLEMENTED;
3778  return 0;
3779 }
#define UNIMPLEMENTED
Definition: debug.h:115

Referenced by GetProcessHeaps().

◆ RtlGetUserInfoHeap()

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

Definition at line 3928 of file heap.c.

3933 {
3934  PHEAP Heap = (PHEAP)HeapHandle;
3935  PHEAP_ENTRY HeapEntry;
3936  PHEAP_ENTRY_EXTRA Extra;
3937  BOOLEAN HeapLocked = FALSE;
3938 
3939  /* Force flags */
3940  Flags |= Heap->ForceFlags;
3941 
3942  /* Call special heap */
3943  if (RtlpHeapIsSpecial(Flags))
3944  return RtlDebugGetUserInfoHeap(Heap, Flags, BaseAddress, UserValue, UserFlags);
3945 
3946  /* Lock if it's lockable */
3947  if (!(Flags & HEAP_NO_SERIALIZE))
3948  {
3950  HeapLocked = TRUE;
3951  }
3952 
3953  /* Get a pointer to the entry */
3954  HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
3955 
3956  /* If it's a free entry - return error */
3957  if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
3958  {
3960 
3961  /* Release the heap lock if it was acquired */
3962  if (HeapLocked)
3964 
3965  return FALSE;
3966  }
3967 
3968  /* Check if this entry has an extra stuff associated with it */
3969  if (HeapEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
3970  {
3971  /* Get pointer to extra data */
3972  Extra = RtlpGetExtraStuffPointer(HeapEntry);
3973 
3974  /* Pass user value */
3975  if (UserValue)
3976  *UserValue = (PVOID)Extra->Settable;
3977  }
3978 
3979  /* Decode and return user flags */
3980  if (UserFlags)
3981  *UserFlags = (HeapEntry->Flags & HEAP_ENTRY_SETTABLE_FLAGS) << 4;
3982 
3983  /* Release the heap lock if it was acquired */
3984  if (HeapLocked)
3986 
3987  return TRUE;
3988 }
ULONG_PTR Settable
Definition: heap.h:299
#define HEAP_ENTRY_SETTABLE_FLAGS
Definition: heap.h:48
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
static PVOID
Definition: heap.c:41
PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer(PHEAP_ENTRY HeapEntry)
Definition: heap.c:2632
#define FALSE
Definition: types.h:117
Definition: heap.h:291
PHEAP_LOCK LockVariable
Definition: heap.h:260
unsigned char BOOLEAN
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
NTSTATUS NTAPI RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:133
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
BOOLEAN NTAPI RtlDebugGetUserInfoHeap(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID *UserValue, PULONG UserFlags)
Definition: heapdbg.c:322
Definition: heap.h:135
struct _HEAP * PHEAP
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
ULONG ForceFlags
Definition: heap.h:227
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:41
Definition: heap.c:51
FORCEINLINE BOOLEAN RtlpHeapIsSpecial(ULONG Flags)
Definition: heap.h:59

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

◆ RtlLockHeap()

BOOLEAN NTAPI RtlLockHeap ( IN HANDLE  HeapPtr)

Definition at line 3106 of file heap.c.

3107 {
3108  PHEAP Heap = (PHEAP)HeapPtr;
3109 
3110  /* Check for page heap */
3111  if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
3112  {
3113  return RtlpPageHeapLock(Heap);
3114  }
3115 
3116  /* Check if it's really a heap */
3117  if (Heap->Signature != HEAP_SIGNATURE) return FALSE;
3118 
3119  /* Lock if it's lockable */
3120  if (!(Heap->Flags & HEAP_NO_SERIALIZE))
3121  {
3123  }
3124 
3125  return TRUE;
3126 }
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#define TRUE
Definition: types.h:120
ULONG Signature
Definition: heap.h:234
BOOLEAN NTAPI RtlpPageHeapLock(HANDLE HeapPtr)
Definition: heappage.c:2354
#define FALSE
Definition: types.h:117
PHEAP_LOCK LockVariable
Definition: heap.h:260
#define HEAP_FLAG_PAGE_ALLOCS
Definition: rtltypes.h:160
ULONG Flags
Definition: heap.h:226
#define HEAP_SIGNATURE
Definition: heap.h:51
struct _HEAP * PHEAP
ULONG ForceFlags
Definition: heap.h:227
Definition: heap.c:51

◆ RtlMultipleAllocateHeap()

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

Definition at line 4125 of file heap.c.

4130 {
4131  ULONG Index;
4132  EXCEPTION_RECORD ExceptionRecord;
4133 
4134  for (Index = 0; Index < Count; ++Index)
4135  {
4136  Array[Index] = RtlAllocateHeap(HeapHandle, Flags, Size);
4137  if (Array[Index] == NULL)
4138  {
4139  /* ERROR_NOT_ENOUGH_MEMORY */
4141 
4143  {
4144  ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY;
4145  ExceptionRecord.ExceptionRecord = NULL;
4146  ExceptionRecord.NumberParameters = 0;
4147  ExceptionRecord.ExceptionFlags = 0;
4148 
4149  RtlRaiseException(&ExceptionRecord);
4150  }
4151  break;
4152  }
4153  }
4154 
4155  return Index;
4156 }
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
NTSYSAPI VOID NTAPI RtlRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord)
DWORD ExceptionCode
Definition: compat.h:208
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
int Count
Definition: noreturn.cpp:7
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_ WDFCOLLECTION _In_ ULONG Index
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
DWORD ExceptionFlags
Definition: compat.h:209
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
DWORD NumberParameters
Definition: compat.h:212
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694

◆ RtlMultipleFreeHeap()

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

Definition at line 4161 of file heap.c.

4165 {
4166  ULONG Index;
4167 
4168  for (Index = 0; Index < Count; ++Index)
4169  {
4170  if (Array[Index] == NULL)
4171  continue;
4172 
4173  _SEH2_TRY
4174  {
4175  if (!RtlFreeHeap(HeapHandle, Flags, Array[Index]))
4176  {
4177  /* ERROR_INVALID_PARAMETER */
4179  break;
4180  }
4181  }
4183  {
4184  /* ERROR_INVALID_PARAMETER */
4186  break;
4187  }
4188  _SEH2_END;
4189  }
4190 
4191  return Index;
4192 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
_SEH2_TRY
Definition: create.c:4226
int Count
Definition: noreturn.cpp:7
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_ WDFCOLLECTION _In_ ULONG Index
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_SEH2_END
Definition: create.c:4400
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40

◆ RtlpAllocateNonDedicated()

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

Definition at line 1957 of file heap.c.

1963 {
1964  PHEAP_FREE_ENTRY FreeBlock;
1965 
1966  /* The entries in the list must be too small for us */
1967  ASSERT(IsListEmpty(&Heap->FreeLists) ||
1968  (CONTAINING_RECORD(Heap->FreeLists.Blink, HEAP_FREE_ENTRY, FreeList)->Size < Index));
1969 
1970  /* Extend the heap */
1971  FreeBlock = RtlpExtendHeap(Heap, AllocationSize);
1972 
1973  /* Use the new biggest entry we've got */
1974  if (FreeBlock)
1975  {
1976  PHEAP_ENTRY InUseEntry;
1977  PHEAP_ENTRY_EXTRA Extra;
1978 
1979  RtlpRemoveFreeBlock(Heap, FreeBlock, TRUE);
1980 
1981  /* Split it */
1982  InUseEntry = RtlpSplitEntry(Heap, Flags, FreeBlock, AllocationSize, Index, Size);
1983 
1984  /* Release the lock */
1985  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
1986 
1987  /* Zero memory if that was requested */
1988  if (Flags & HEAP_ZERO_MEMORY)
1989  RtlZeroMemory(InUseEntry + 1, Size);
1990  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
1991  {
1992  /* Fill this block with a special pattern */
1993  RtlFillMemoryUlong(InUseEntry + 1, Size & ~0x3, ARENA_INUSE_FILLER);
1994  }
1995 
1996  /* Fill tail of the block with a special pattern too if requested */
1997  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
1998  {
1999  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size, sizeof(HEAP_ENTRY), HEAP_TAIL_FILL);
2000  InUseEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
2001  }
2002 
2003  /* Prepare extra if it's present */
2004  if (InUseEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
2005  {
2006  Extra = RtlpGetExtraStuffPointer(InUseEntry);
2007  RtlZeroMemory(Extra, sizeof(HEAP_ENTRY_EXTRA));
2008 
2009  // TODO: Tagging
2010  }
2011 
2012  /* Return pointer to the */
2013  return InUseEntry + 1;
2014  }
2015 
2016  /* Really unfortunate, out of memory condition */
2018 
2019  /* Generate an exception */
2021  {
2022  EXCEPTION_RECORD ExceptionRecord;
2023 
2024  ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY;
2025  ExceptionRecord.ExceptionRecord = NULL;
2026  ExceptionRecord.NumberParameters = 1;
2027  ExceptionRecord.ExceptionFlags = 0;
2028  ExceptionRecord.ExceptionInformation[0] = AllocationSize;
2029 
2030  RtlRaiseException(&ExceptionRecord);
2031  }
2032 
2033  /* Release the lock */
2034  if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
2035  DPRINT1("HEAP: Allocation failed!\n");
2036  DPRINT1("Flags %x\n", Heap->Flags);
2037  return NULL;
2038 }
signed char * PCHAR
Definition: retypes.h:7
#define ARENA_INUSE_FILLER
Definition: oleaut.c:105
#define TRUE
Definition: types.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
static VOID RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN NoFill)
Definition: heap.c:422
LIST_ENTRY FreeLists
Definition: heap.h:259
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
static PHEAP_FREE_ENTRY RtlpExtendHeap(PHEAP Heap, SIZE_T Size)
Definition: heap.c:1247
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:2632
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
DWORD ExceptionCode
Definition: compat.h:208
Definition: heap.h:291
PHEAP_LOCK LockVariable
Definition: heap.h:260
Definition: heap.h:129
#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
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ASSERT(a)
Definition: mode.c:44
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
_In_ WDFCOLLECTION _In_ ULONG Index
PHEAP_ENTRY NTAPI RtlpSplitEntry(PHEAP Heap, ULONG Flags, PHEAP_FREE_ENTRY FreeBlock, SIZE_T AllocationSize, SIZE_T Index, SIZE_T Size)
Definition: heap.c:1817
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:42
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:319
Definition: heap.h:135
ULONG Flags
Definition: heap.h:226
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define NULL
Definition: types.h:112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define DPRINT1
Definition: precomp.h:8
#define HEAP_TAIL_FILL
Definition: heap.h:27
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
DWORD ExceptionFlags
Definition: compat.h:209
NTSYSAPI void WINAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS)
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:41
DWORD NumberParameters
Definition: compat.h:212
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694

Referenced by RtlAllocateHeap().

◆ RtlpCheckInUsePattern()

BOOLEAN NTAPI RtlpCheckInUsePattern ( PHEAP_ENTRY  HeapEntry)

Definition at line 3230 of file heap.c.

3231 {
3232  SIZE_T Size, Result;
3233  PCHAR TailPart;
3234 
3235  /* Calculate size */
3236  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
3237  Size = RtlpGetSizeOfBigBlock(HeapEntry);
3238  else
3239  Size = (HeapEntry->Size << HEAP_ENTRY_SHIFT) - HeapEntry->UnusedBytes;
3240 
3241  /* Calculate pointer to the tail part of the block */
3242  TailPart = (PCHAR)(HeapEntry + 1) + Size;
3243 
3244  /* Compare tail pattern */
3245  Result = RtlCompareMemory(TailPart,
3246  FillPattern,
3247  HEAP_ENTRY_SIZE);
3248 
3249  if (Result != HEAP_ENTRY_SIZE)
3250  {
3251  DPRINT1("HEAP: Heap entry (size %x) %p tail is modified at %p\n", Size, HeapEntry, TailPart + Result);
3252  return FALSE;
3253  }
3254 
3255  /* All is fine */
3256  return TRUE;
3257 }
SIZE_T NTAPI RtlpGetSizeOfBigBlock(PHEAP_ENTRY HeapEntry)
Definition: heap.c:500
signed char * PCHAR
Definition: retypes.h:7
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:43
#define TRUE
Definition: types.h:120
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
UCHAR FillPattern[HEAP_ENTRY_SIZE]
Definition: heap.c:72
#define FALSE
Definition: types.h:117
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define HEAP_ENTRY_SHIFT
Definition: heap.h:21
#define HEAP_ENTRY_SIZE
Definition: heap.h:17
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define DPRINT1
Definition: precomp.h:8
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465

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

◆ RtlpCoalesceFreeBlocks()

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

Definition at line 1150 of file heap.c.

1154 {
1155  PHEAP_FREE_ENTRY CurrentEntry, NextEntry;
1156  UCHAR SegmentOffset;
1157 
1158  /* Get the previous entry */
1159  CurrentEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry - FreeEntry->PreviousSize);
1160 
1161  /* Check it */
1162  if (CurrentEntry != FreeEntry &&
1163  !(CurrentEntry->Flags & HEAP_ENTRY_BUSY) &&
1164  (*FreeSize + CurrentEntry->Size) <= HEAP_MAX_BLOCK_SIZE)
1165  {
1166  ASSERT(FreeEntry->PreviousSize == CurrentEntry->Size);
1167 
1168  /* Remove it if asked for */
1169  if (Remove)
1170  {
1171  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE);
1172  Heap->TotalFreeSize -= FreeEntry->Size;
1173 
1174  /* Remove it only once! */
1175  Remove = FALSE;
1176  }
1177 
1178  /* Remove previous entry too */
1179  RtlpRemoveFreeBlock(Heap, CurrentEntry, FALSE);
1180 
1181  /* Copy flags */
1182  CurrentEntry->Flags = FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY;
1183 
1184  /* Advance FreeEntry and update sizes */
1185  FreeEntry = CurrentEntry;
1186  *FreeSize = *FreeSize + CurrentEntry->Size;
1187  Heap->TotalFreeSize -= CurrentEntry->Size;
1188  FreeEntry->Size = (USHORT)(*FreeSize);
1189 
1190  /* Also update previous size if needed */
1191  if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1192  {
1193  ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
1194  }
1195  else
1196  {
1197  SegmentOffset = FreeEntry->SegmentOffset;
1198  ASSERT(SegmentOffset < HEAP_SEGMENTS);
1199  }
1200  }
1201 
1202  /* Check the next block if it exists */
1203  if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1204  {
1205  NextEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + *FreeSize);
1206 
1207  if (!(NextEntry->Flags & HEAP_ENTRY_BUSY) &&
1208  NextEntry->Size + *FreeSize <= HEAP_MAX_BLOCK_SIZE)
1209  {
1210  ASSERT(*FreeSize == NextEntry->PreviousSize);
1211 
1212  /* Remove it if asked for */
1213  if (Remove)
1214  {
1215  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE);
1216  Heap->TotalFreeSize -= FreeEntry->Size;
1217  }
1218 
1219  /* Copy flags */
1220  FreeEntry->Flags = NextEntry->Flags & HEAP_ENTRY_LAST_ENTRY;
1221 
1222  /* Remove next entry now */
1223  RtlpRemoveFreeBlock(Heap, NextEntry, FALSE);
1224 
1225  /* Update sizes */
1226  *FreeSize = *FreeSize + NextEntry->Size;
1227  Heap->TotalFreeSize -= NextEntry->Size;
1228  FreeEntry->Size = (USHORT)(*FreeSize);
1229 
1230  /* Also update previous size if needed */
1231  if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
1232  {
1233  ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
1234  }
1235  else
1236  {
1237  SegmentOffset = FreeEntry->SegmentOffset;
1238  ASSERT(SegmentOffset < HEAP_SEGMENTS);
1239  }
1240  }
1241  }
1242  return FreeEntry;
1243 }
SIZE_T TotalFreeSize
Definition: heap.h:239
#define HEAP_SEGMENTS
Definition: heap.h:15
static VOID RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN NoFill)
Definition: heap.c:422
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:23
#define FALSE
Definition: types.h:117
Definition: heap.h:129
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
_In_ BOOLEAN Remove
Definition: psfuncs.h:110
#define ASSERT(a)
Definition: mode.c:44
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
Definition: heap.h:135
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44

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

◆ RtlpCoalesceHeap()

PHEAP_FREE_ENTRY NTAPI RtlpCoalesceHeap ( PHEAP  Heap)

Definition at line 1143 of file heap.c.

1144 {
1145  UNIMPLEMENTED;
1146  return NULL;
1147 }
#define NULL
Definition: types.h:112
#define UNIMPLEMENTED
Definition: debug.h:115

Referenced by RtlpExtendHeap().

◆ RtlpCreateUnCommittedRange()

PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange ( PHEAP_SEGMENT  Segment)

Definition at line 513 of file heap.c.

514 {
516  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
517  PHEAP_UCR_SEGMENT UcrSegment;
518  PHEAP Heap = Segment->Heap;
522 
523  DPRINT("RtlpCreateUnCommittedRange(%p)\n", Segment);
524 
525  /* Check if we have unused UCRs */
526  if (IsListEmpty(&Heap->UCRList))
527  {
528  /* Get a pointer to the first UCR segment */
529  UcrSegment = CONTAINING_RECORD(Heap->UCRSegments.Flink, HEAP_UCR_SEGMENT, ListEntry);
530 
531  /* Check the list of UCR segments */
532  if (IsListEmpty(&Heap->UCRSegments) ||
533  UcrSegment->ReservedSize == UcrSegment->CommittedSize)
534  {
535  /* We need to create a new one. Reserve 16 pages for it */
536  UcrSegment = NULL;
537  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
538  (PVOID *)&UcrSegment,
539  0,
540  &ReserveSize,
541  MEM_RESERVE,
543 
544  if (!NT_SUCCESS(Status)) return NULL;
545 
546  /* Commit one page */
547  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
548  (PVOID *)&UcrSegment,
549  0,
550  &CommitSize,
551  MEM_COMMIT,
553 
554  if (!NT_SUCCESS(Status))
555  {
556  /* Release reserved memory */
557  ZwFreeVirtualMemory(NtCurrentProcess(),
558  (PVOID *)&UcrSegment,
559  &ReserveSize,
560  MEM_RELEASE);
561  return NULL;
562  }
563 
564  /* Set it's data */
565  UcrSegment->ReservedSize = ReserveSize;
566  UcrSegment->CommittedSize = CommitSize;
567 
568  /* Add it to the head of the list */
569  InsertHeadList(&Heap->UCRSegments, &UcrSegment->ListEntry);
570 
571  /* Get a pointer to the first available UCR descriptor */
572  UcrDescriptor = (PHEAP_UCR_DESCRIPTOR)(UcrSegment + 1);
573  }
574  else
575  {
576  /* It's possible to use existing UCR segment. Commit one more page */
577  UcrDescriptor = (PHEAP_UCR_DESCRIPTOR)((PCHAR)UcrSegment + UcrSegment->CommittedSize);
578  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
579  (PVOID *)&UcrDescriptor,
580  0,
581  &CommitSize,
582  MEM_COMMIT,
584 
585  if (!NT_SUCCESS(Status)) return NULL;
586 
587  ASSERT((PCHAR)UcrDescriptor == ((PCHAR)UcrSegment + UcrSegment->CommittedSize));
588 
589  /* Update sizes */
590  UcrSegment->CommittedSize += CommitSize;
591  }
592 
593  /* There is a whole bunch of new UCR descriptors. Put them into the unused list */
594  while ((PCHAR)(UcrDescriptor + 1) <= (PCHAR)UcrSegment + UcrSegment->CommittedSize)
595  {
596  InsertTailList(&Heap->UCRList, &UcrDescriptor->ListEntry);
597  UcrDescriptor++;
598  }
599  }
600 
601  /* There are unused UCRs, just get the first one */
602  Entry = RemoveHeadList(&Heap->UCRList);
603  UcrDescriptor = CONTAINING_RECORD(Entry, HEAP_UCR_DESCRIPTOR, ListEntry);
604  return UcrDescriptor;
605 }
signed char * PCHAR
Definition: retypes.h:7
struct _Entry Entry
Definition: kefuncs.h:627
struct _HEAP_UCR_DESCRIPTOR * PHEAP_UCR_DESCRIPTOR
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LONG NTSTATUS
Definition: precomp.h:26
#define InsertTailList(ListHead, Entry)
#define MEM_COMMIT
Definition: nt_native.h:1313
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
SIZE_T ReservedSize
Definition: heap.h:287
#define MEM_RESERVE
Definition: nt_native.h:1314
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
SIZE_T CommittedSize
Definition: heap.h:288
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ASSERT(a)
Definition: mode.c:44
LIST_ENTRY UCRSegments
Definition: heap.h:248
#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:247
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
LIST_ENTRY ListEntry
Definition: heap.h:278
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define NULL
Definition: types.h:112
_In_opt_ PVOID _In_opt_ SIZE_T ReserveSize
Definition: rtlfuncs.h:2167
#define MEM_RELEASE
Definition: nt_native.h:1316
LIST_ENTRY ListEntry
Definition: heap.h:286
#define DPRINT
Definition: sndvol32.h:71
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()

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

Definition at line 834 of file heap.c.

837 {
839  PHEAP_ENTRY NextEntry, GuardEntry;
840  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
841  SIZE_T PrecedingSize, DecommitSize;
842  ULONG_PTR DecommitBase, DecommitEnd;
844 
845  DPRINT("Decommitting %p %p %x\n", Heap, FreeEntry, Size);
846 
847  /* We can't decommit if there is a commit routine! */
848  if (Heap->CommitRoutine)
849  {
850  /* Just add it back the usual way */
851  RtlpInsertFreeBlock(Heap, FreeEntry, Size);
852  return;
853  }
854 
855  /* Get the segment */
856  Segment = Heap->Segments[FreeEntry->SegmentOffset];
857 
858  /* Get the preceding entry */
859  DecommitBase = ROUND_UP(FreeEntry, PAGE_SIZE);
860  PrecedingSize = (PHEAP_ENTRY)DecommitBase - (PHEAP_ENTRY)FreeEntry;
861 
862  if (PrecedingSize == 0)
863  {
864  /* We need some space in order to insert our guard entry */
865  DecommitBase += PAGE_SIZE;
866  PrecedingSize += PAGE_SIZE >> HEAP_ENTRY_SHIFT;
867  }
868 
869  /* Get the entry after this one. */
870 
871  /* Do we really have a next entry */
872  if (RtlpIsLastCommittedEntry((PHEAP_ENTRY)FreeEntry))
873  {
874  /* No, Decommit till the next UCR. */
875  DecommitEnd = PAGE_ROUND_UP((PHEAP_ENTRY)FreeEntry + FreeEntry->Size);
876  NextEntry = NULL;
877  }
878  else
879  {
880  NextEntry = (PHEAP_ENTRY)FreeEntry + Size;
881  DecommitEnd = PAGE_ROUND_DOWN(NextEntry);
882 
883  /* Can we make a free entry out of what's left ? */
884  if ((NextEntry - (PHEAP_ENTRY)DecommitEnd) == 1)
885  {
886  /* Nope. Let's keep one page before this */
887  DecommitEnd -= PAGE_SIZE;
888  }
889  }
890 
891  if (DecommitEnd <= DecommitBase)
892  {
893  /* There's nothing left to decommit. */
894  RtlpInsertFreeBlock(Heap, FreeEntry, Size);
895  return;
896  }
897 
898  DecommitSize = DecommitEnd - DecommitBase;
899 
900  /* A decommit is necessary. Create a UCR descriptor */
901  UcrDescriptor = RtlpCreateUnCommittedRange(Segment);
902  if (!UcrDescriptor)
903  {
904  DPRINT1("HEAP: Failed to create UCR descriptor\n");
905  RtlpInsertFreeBlock(Heap, FreeEntry, PrecedingSize);
906  return;
907  }
908 
909  /* Decommit the memory */
910  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
911  (PVOID *)&DecommitBase,
912  &DecommitSize,
913  MEM_DECOMMIT);
914  ASSERT((DecommitBase + DecommitSize) == DecommitEnd);
915 
916  /* Delete that UCR. This is needed to assure there is an unused UCR entry in the list */
917  RtlpDestroyUnCommittedRange(Segment, UcrDescriptor);
918 
919  if (!NT_SUCCESS(Status))
920  {
921  RtlpInsertFreeBlock(Heap, FreeEntry, Size);
922  return;
923  }
924 
925  /* Insert uncommitted pages */
926  RtlpInsertUnCommittedPages(Segment, DecommitBase, DecommitSize);
927  Segment->NumberOfUnCommittedPages += (ULONG)(DecommitSize / PAGE_SIZE);
928 
929  /* Insert our guard entry before this */
930  GuardEntry = (PHEAP_ENTRY)DecommitBase - 1;
931  GuardEntry->Size = 1;
932  GuardEntry->Flags = HEAP_ENTRY_BUSY | HEAP_ENTRY_LAST_ENTRY;
933  GuardEntry->SegmentOffset = FreeEntry->SegmentOffset;
934  DPRINT("Setting %p as UCR guard entry.\n", GuardEntry);
935 
936  /* Now see what's really behind us */
937  PrecedingSize--;
938  switch (PrecedingSize)
939  {
940  case 1:
941  /* No space left for a free entry. Make this another guard entry */
942  GuardEntry->PreviousSize = 1;
943  GuardEntry--;
944  GuardEntry->Size = 1;
945  GuardEntry->Flags = HEAP_ENTRY_BUSY | HEAP_ENTRY_LAST_ENTRY;
946  GuardEntry->SegmentOffset = FreeEntry->SegmentOffset;
947  /* Fall-through */
948  case 0:
949  /* There was just enough space four our guard entry */
950  ASSERT((PHEAP_ENTRY)FreeEntry == GuardEntry);
951  GuardEntry->PreviousSize = FreeEntry->PreviousSize;
952  break;
953  default:
954  /* We can insert this as a free entry */
955  GuardEntry->PreviousSize = PrecedingSize;
956  FreeEntry->Size = PrecedingSize;
957  FreeEntry->Flags &= ~HEAP_ENTRY_LAST_ENTRY;
958  FreeEntry = RtlpCoalesceFreeBlocks(Heap, FreeEntry, &PrecedingSize, FALSE);
959  RtlpInsertFreeBlock(Heap, FreeEntry, PrecedingSize);
960  break;
961  }
962 
963  /* Now the next one */
964  if (NextEntry)
965  {
966  ASSERT((PHEAP_ENTRY)DecommitEnd <= NextEntry);
967 
968  SIZE_T NextSize = NextEntry - (PHEAP_ENTRY)DecommitEnd;
969  if (NextSize)
970  {
971  PHEAP_FREE_ENTRY NextFreeEntry = (PHEAP_FREE_ENTRY)DecommitEnd;
972 
973  /* Make sure this is all valid */
974  ASSERT((PHEAP_ENTRY)DecommitEnd < Segment->LastValidEntry);
975  ASSERT(NextSize >= 2);
976 
977  /* Adjust size of this free entry and insert it */
978  NextFreeEntry->Flags = 0;
979  NextFreeEntry->PreviousSize = 0;
980  NextFreeEntry->SegmentOffset = Segment->Entry.SegmentOffset;
981  NextFreeEntry->Size = (USHORT)NextSize;
982 
983  NextEntry->PreviousSize = NextSize;
984  ASSERT(NextEntry == (PHEAP_ENTRY)NextFreeEntry + NextFreeEntry->Size);
985 
986  NextFreeEntry = RtlpCoalesceFreeBlocks(Heap, NextFreeEntry, &NextSize, FALSE);
987  RtlpInsertFreeBlock(Heap, NextFreeEntry, NextSize);
988  }
989  else
990  {
991  /* This one must be at the beginning of a page */
992  ASSERT(NextEntry == (PHEAP_ENTRY)PAGE_ROUND_DOWN(NextEntry));
993  /* And we must have a gap betwwen */
994  ASSERT(NextEntry > (PHEAP_ENTRY)DecommitBase);
995  NextEntry->PreviousSize = 0;
996  }
997  }
998 }
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine
Definition: heap.h:261
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
#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:1150
LONG NTSTATUS
Definition: precomp.h:26
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
uint32_t ULONG_PTR
Definition: typedefs.h:65
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:253
#define MEM_DECOMMIT
Definition: nt_native.h:1315
#define FALSE
Definition: types.h:117
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:357
Definition: heap.h:129
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
#define HEAP_ENTRY_SHIFT
Definition: heap.h:21
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI RtlpDestroyUnCommittedRange(PHEAP_SEGMENT Segment, PHEAP_UCR_DESCRIPTOR UcrDescriptor)
Definition: heap.c:608
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
#define PAGE_SIZE
Definition: env_spec_w32.h:49
PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange(PHEAP_SEGMENT Segment)
Definition: heap.c:513
ULONG_PTR SIZE_T
Definition: typedefs.h:80
VOID NTAPI RtlpInsertUnCommittedPages(PHEAP_SEGMENT Segment, ULONG_PTR Address, SIZE_T Size)
Definition: heap.c:620
Definition: heap.h:135
unsigned short USHORT
Definition: pedump.c:61
#define NULL
Definition: types.h:112
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44
#define DPRINT1
Definition: precomp.h:8
static BOOLEAN RtlpIsLastCommittedEntry(PHEAP_ENTRY Entry)
Definition: heap.c:86
#define DPRINT
Definition: sndvol32.h:71

Referenced by RtlFreeHeap().

◆ RtlpDestroyHeapSegment()

VOID NTAPI RtlpDestroyHeapSegment ( PHEAP_SEGMENT  Segment)

Definition at line 1118 of file heap.c.

1119 {
1120  NTSTATUS Status;
1122  SIZE_T Size = 0;
1123 
1124  /* Make sure it's not user allocated */
1125  if (Segment->SegmentFlags & HEAP_USER_ALLOCATED) return;
1126 
1127  BaseAddress = Segment->BaseAddress;
1128  DPRINT("Destroying segment %p, BA %p\n", Segment, BaseAddress);
1129 
1130  /* Release virtual memory */
1131  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
1132  &BaseAddress,
1133  &Size,
1134  MEM_RELEASE);
1135 
1136  if (!NT_SUCCESS(Status))
1137  {
1138  DPRINT1("HEAP: Failed to release segment's memory with status 0x%08X\n", Status);
1139  }
1140 }
LONG NTSTATUS
Definition: precomp.h:26
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
_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:55
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define DPRINT1
Definition: precomp.h:8
#define MEM_RELEASE
Definition: nt_native.h:1316
#define DPRINT
Definition: sndvol32.h:71

Referenced by RtlDestroyHeap().

◆ RtlpDestroyUnCommittedRange()

VOID NTAPI RtlpDestroyUnCommittedRange ( PHEAP_SEGMENT  Segment,
PHEAP_UCR_DESCRIPTOR  UcrDescriptor 
)

Definition at line 608 of file heap.c.

610 {
611  /* Zero it out */
612  UcrDescriptor->Address = NULL;
613  UcrDescriptor->Size = 0;
614 
615  /* Put it into the heap's list of unused UCRs */
616  InsertHeadList(&Segment->Heap->UCRList, &UcrDescriptor->ListEntry);
617 }
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
LIST_ENTRY ListEntry
Definition: heap.h:278
#define NULL
Definition: types.h:112

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

◆ RtlpExtendHeap()

static PHEAP_FREE_ENTRY RtlpExtendHeap ( PHEAP  Heap,
SIZE_T  Size 
)
static

Definition at line 1247 of file heap.c.

1249 {
1250  ULONG Pages;
1251  UCHAR Index, EmptyIndex;
1252  SIZE_T FreeSize, CommitSize, ReserveSize;
1254  PHEAP_FREE_ENTRY FreeEntry;
1255  NTSTATUS Status;
1256 
1257  DPRINT("RtlpExtendHeap(%p %x)\n", Heap, Size);
1258 
1259  /* Calculate amount in pages */
1260  Pages = (ULONG)((Size + PAGE_SIZE - 1) / PAGE_SIZE);
1261  FreeSize = Pages * PAGE_SIZE;
1262  DPRINT("Pages %x, FreeSize %x. Going through segments...\n", Pages, FreeSize);
1263 
1264  /* Find an empty segment */
1265  EmptyIndex = HEAP_SEGMENTS;
1266  for (Index = 0; Index < HEAP_SEGMENTS; Index++)
1267  {
1268  Segment = Heap->Segments[Index];
1269 
1270  if (Segment) DPRINT("Segment[%u] %p with NOUCP %x\n", Index, Segment, Segment->NumberOfUnCommittedPages);
1271 
1272  /* Check if its size suits us */
1273  if (Segment &&
1274  Pages <= Segment->NumberOfUnCommittedPages)
1275  {
1276  DPRINT("This segment is suitable\n");
1277 
1278  /* Commit needed amount */
1279  FreeEntry = RtlpFindAndCommitPages(Heap, Segment, &FreeSize, NULL);
1280 
1281  /* Coalesce it with adjacent entries */
1282  if (FreeEntry)
1283  {
1284  FreeSize = FreeSize >> HEAP_ENTRY_SHIFT;
1285  FreeEntry = RtlpCoalesceFreeBlocks(Heap, FreeEntry, &FreeSize, FALSE);
1286  RtlpInsertFreeBlock(Heap, FreeEntry, FreeSize);
1287  return FreeEntry;
1288  }
1289  }
1290  else if (!Segment &&
1291  EmptyIndex == HEAP_SEGMENTS)
1292  {
1293  /* Remember the first unused segment index */
1294  EmptyIndex = Index;
1295  }
1296  }
1297 
1298  /* No luck, need to grow the heap */
1299  if ((Heap->Flags & HEAP_GROWABLE) &&
1300  (EmptyIndex != HEAP_SEGMENTS))
1301  {
1302  Segment = NULL;
1303 
1304  /* Reserve the memory */
1305  if ((Size + PAGE_SIZE) <= Heap->SegmentReserve)
1306  ReserveSize = Heap->SegmentReserve;
1307  else
1309 
1310  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1311  (PVOID)&Segment,
1312  0,
1313  &ReserveSize,
1314  MEM_RESERVE,
1315  PAGE_READWRITE);
1316 
1317  /* If it failed, retry again with a half division algorithm */
1318  while (!NT_SUCCESS(Status) &&
1319  ReserveSize != Size + PAGE_SIZE)
1320  {
1321  ReserveSize /= 2;
1322 
1323  if (ReserveSize < (Size + PAGE_SIZE))
1325 
1326  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1327  (PVOID)&Segment,
1328  0,
1329  &ReserveSize,
1330  MEM_RESERVE,
1331  PAGE_READWRITE);
1332  }
1333 
1334  /* Proceed only if it's success */
1335  if (NT_SUCCESS(Status))
1336  {
1337  Heap->SegmentReserve += ReserveSize;
1338 
1339  /* Now commit the memory */
1340  if ((Size + PAGE_SIZE) <= Heap->SegmentCommit)
1341  CommitSize = Heap->SegmentCommit;
1342  else
1344 
1345  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
1346  (PVOID)&Segment,
1347  0,
1348  &CommitSize,
1349  MEM_COMMIT,
1350  PAGE_READWRITE);
1351 
1352  DPRINT("Committed %lu bytes at base %p\n", CommitSize, Segment);
1353 
1354  /* Initialize heap segment if commit was successful */
1355  if (NT_SUCCESS(Status))
1357 
1358  /* If everything worked - cool */
1359  if (NT_SUCCESS(Status)) return (PHEAP_FREE_ENTRY)Segment->FirstEntry;
1360 
1361  DPRINT1("Committing failed with status 0x%08X\n", Status);
1362 
1363  /* Nope, we failed. Free memory */
1364  ZwFreeVirtualMemory(NtCurrentProcess(),
1365  (PVOID)&Segment,
1366  &ReserveSize,
1367  MEM_RELEASE);
1368  }
1369  else
1370  {
1371  DPRINT1("Reserving failed with status 0x%08X\n", Status);
1372  }
1373  }
1374 
1375  if (RtlpGetMode() == UserMode)
1376  {
1377  /* If coalescing on free is disabled in usermode, then do it here */
1379  {
1380  FreeEntry = RtlpCoalesceHeap(Heap);
1381 
1382  /* If it's a suitable one - return it */
1383  if (FreeEntry &&
1384  FreeEntry->Size >= Size)
1385  {
1386  return FreeEntry;
1387  }
1388  }
1389  }
1390 
1391  return NULL;
1392 }
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:1150
#define HEAP_SEGMENTS
Definition: heap.h:15
LONG NTSTATUS
Definition: precomp.h:26
#define HEAP_DISABLE_COALESCE_ON_FREE
Definition: nt_native.h:1699
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define MEM_COMMIT
Definition: nt_native.h:1313
PHEAP_FREE_ENTRY NTAPI RtlpCoalesceHeap(PHEAP Heap)
Definition: heap.c:1143
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:253
static PHEAP_FREE_ENTRY RtlpFindAndCommitPages(PHEAP Heap, PHEAP_SEGMENT Segment, PSIZE_T Size, PVOID AddressRequested)
Definition: heap.c:690
#define FALSE
Definition: types.h:117
#define MEM_RESERVE
Definition: nt_native.h:1314
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:357
Definition: heap.h:129
#define HEAP_ENTRY_SHIFT
Definition: heap.h:21
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ WDFCOLLECTION _In_ ULONG Index
_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
unsigned char UCHAR
Definition: xmlstorage.h:181
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG_PTR SIZE_T
Definition: typedefs.h:80
SIZE_T SegmentReserve
Definition: heap.h:235
ULONG Flags
Definition: heap.h:226
SIZE_T SegmentCommit
Definition: heap.h:236
#define NULL
Definition: types.h:112
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:1002
_In_opt_ PVOID _In_opt_ SIZE_T ReserveSize
Definition: rtlfuncs.h:2167
#define DPRINT1
Definition: precomp.h:8
#define MEM_RELEASE
Definition: nt_native.h:1316
unsigned int ULONG
Definition: retypes.h:1
#define DPRINT
Definition: sndvol32.h:71
#define PAGE_READWRITE
Definition: nt_native.h:1304

Referenced by RtlpAllocateNonDedicated().

◆ RtlpFindAndCommitPages()

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

Definition at line 690 of file heap.c.

694 {
695  PLIST_ENTRY Current;
697 
698  DPRINT("RtlpFindAndCommitPages(%p %p %Ix %p)\n", Heap, Segment, *Size, AddressRequested);
699 
700  /* Go through UCRs in a segment */
701  Current = Segment->UCRSegmentList.Flink;
702  while (Current != &Segment->UCRSegmentList)
703  {
704  PHEAP_UCR_DESCRIPTOR UcrDescriptor = CONTAINING_RECORD(Current, HEAP_UCR_DESCRIPTOR, SegmentEntry);
705 
706  /* Check if we can use that one right away */
707  if (UcrDescriptor->Size >= *Size &&
708  (UcrDescriptor->Address == AddressRequested || !AddressRequested))
709  {
710  PHEAP_ENTRY GuardEntry, FreeEntry;
711  PVOID Address = UcrDescriptor->Address;
712 
713  /* Commit it */
714  if (Heap->CommitRoutine)
715  {
716  Status = Heap->CommitRoutine(Heap, &Address, Size);
717  }
718  else
719  {
720  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
721  &Address,
722  0,
723  Size,
724  MEM_COMMIT,
726  }
727 
728  DPRINT("Committed %Iu bytes at base %08Ix, UCR size is %lu\n", *Size, Address, UcrDescriptor->Size);
729 
730  /* Fail in unsuccessful case */
731  if (!NT_SUCCESS(Status))
732  {
733  DPRINT1("Committing page failed with status 0x%08X\n", Status);
734  return NULL;
735  }
736 
737  /* Update tracking numbers */
738  Segment->NumberOfUnCommittedPages -= (ULONG)(*Size / PAGE_SIZE);
739 
740  /* Update UCR descriptor */
741  UcrDescriptor->Address = (PVOID)((ULONG_PTR)UcrDescriptor->Address + *Size);
742  UcrDescriptor->Size -= *Size;
743 
744  /* Grab the previous guard entry */
745  GuardEntry = (PHEAP_ENTRY)Address - 1;
746  ASSERT(GuardEntry->Flags & HEAP_ENTRY_LAST_ENTRY);
747  ASSERT(GuardEntry->Flags & HEAP_ENTRY_BUSY);
748  ASSERT(GuardEntry->Size == 1);
749 
750  /* Did we have a double guard entry ? */
751  if (GuardEntry->PreviousSize == 1)
752  {
753  /* Use the one before instead */
754  GuardEntry--;
755 
756  ASSERT(GuardEntry->Flags & HEAP_ENTRY_LAST_ENTRY);
757  ASSERT(GuardEntry->Flags & HEAP_ENTRY_BUSY);
758  ASSERT(GuardEntry->Size == 1);
759 
760  /* We gain one slot more */
761  *Size += HEAP_ENTRY_SIZE;
762  }
763 
764  /* This will become our returned free entry.
765  * Now we can make it span the whole committed range.
766  * But we keep one slot for a guard entry, if needed.
767  */
768  FreeEntry = GuardEntry;
769 
770  FreeEntry->Flags &= ~(HEAP_ENTRY_BUSY | HEAP_ENTRY_LAST_ENTRY);
771  FreeEntry->Size = (*Size) >> HEAP_ENTRY_SHIFT;
772 
773  DPRINT("Updating UcrDescriptor %p, new Address %p, size %lu\n",
774  UcrDescriptor, UcrDescriptor->Address, UcrDescriptor->Size);
775 
776  /* Check if anything left in this UCR */
777  if (UcrDescriptor->Size == 0)
778  {
779  /* It's fully exhausted. Take the guard entry for us */
780  FreeEntry->Size++;
781  *Size += HEAP_ENTRY_SIZE;
782 
783  ASSERT((FreeEntry + FreeEntry->Size) == UcrDescriptor->Address);
784 
785  /* Check if this is the end of the segment */
786  if(UcrDescriptor->Address == Segment->LastValidEntry)
787  {
788  FreeEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
789  }
790  else
791  {
792  PHEAP_ENTRY NextEntry = UcrDescriptor->Address;
793 
794  /* We should not have a UCR right behind us */
795  ASSERT((UcrDescriptor->SegmentEntry.Flink == &Segment->UCRSegmentList)
796  || (CONTAINING_RECORD(UcrDescriptor->SegmentEntry.Flink, HEAP_UCR_DESCRIPTOR, SegmentEntry)->Address > UcrDescriptor->Address));
797 
798  ASSERT(NextEntry->PreviousSize == 0);
799  ASSERT(NextEntry == FreeEntry + FreeEntry->Size);
800  NextEntry->PreviousSize = FreeEntry->Size;
801  }
802 
803  /* This UCR needs to be removed because it became useless */
804  RemoveEntryList(&UcrDescriptor->SegmentEntry);
805 
806  RtlpDestroyUnCommittedRange(Segment, UcrDescriptor);
807  Segment->NumberOfUnCommittedRanges--;
808  }
809  else
810  {
811  /* Setup a guard entry */
812  GuardEntry = (PHEAP_ENTRY)UcrDescriptor->Address - 1;
813  ASSERT(GuardEntry == FreeEntry + FreeEntry->Size);
814  GuardEntry->Flags = HEAP_ENTRY_LAST_ENTRY | HEAP_ENTRY_BUSY;
815  GuardEntry->Size = 1;
816  GuardEntry->PreviousSize = FreeEntry->Size;
817  GuardEntry->SegmentOffset = FreeEntry->SegmentOffset;
818  DPRINT("Setting %p as UCR guard entry.\n", GuardEntry);
819  }
820 
821  /* We're done */
822  return (PHEAP_FREE_ENTRY)FreeEntry;
823  }
824 
825  /* Advance to the next descriptor */
826  Current = Current->Flink;
827  }
828 
829  return NULL;
830 }
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine
Definition: heap.h:261
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
LONG NTSTATUS
Definition: precomp.h:26
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
static PVOID
Definition: heap.c:41
#define MEM_COMMIT
Definition: nt_native.h:1313
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
Definition: heap.h:129
struct _HEAP_ENTRY * PHEAP_ENTRY
static WCHAR Address[46]
Definition: ping.c:68
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
#define HEAP_ENTRY_SHIFT
Definition: heap.h:21
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI RtlpDestroyUnCommittedRange(PHEAP_SEGMENT Segment, PHEAP_UCR_DESCRIPTOR UcrDescriptor)
Definition: heap.c:608
#define HEAP_ENTRY_SIZE
Definition: heap.h:17
LIST_ENTRY SegmentEntry
Definition: heap.h:279
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
Definition: heap.h:135
#define NULL
Definition: types.h:112
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44
#define DPRINT1
Definition: precomp.h:8
#define DPRINT
Definition: sndvol32.h:71
#define PAGE_READWRITE
Definition: nt_native.h:1304

Referenced by RtlpExtendHeap(), and RtlpGrowBlockInPlace().

◆ RtlpFindLeastSetBit()

FORCEINLINE UCHAR RtlpFindLeastSetBit ( ULONG  Bits)

Definition at line 53 of file heap.c.

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

◆ RtlpGetExtraStuffPointer()

PHEAP_ENTRY_EXTRA NTAPI RtlpGetExtraStuffPointer ( PHEAP_ENTRY  HeapEntry)

Definition at line 2632 of file heap.c.

2633 {
2634  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
2635 
2636  /* Check if it's a big block */
2637  if (HeapEntry->Flags & HEAP_ENTRY_VIRTUAL_ALLOC)
2638  {
2639  VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
2640 
2641  /* Return a pointer to the extra stuff*/
2642  return &VirtualEntry->ExtraStuff;
2643  }
2644  else
2645  {
2646  /* This is a usual entry, which means extra stuff follows this block */
2647  return (PHEAP_ENTRY_EXTRA)(HeapEntry + HeapEntry->Size - 1);
2648  }
2649 }
Definition: heap.h:307
#define HEAP_ENTRY_VIRTUAL_ALLOC
Definition: heap.h:43
Definition: heap.h:291
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:310

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

◆ RtlpGetSizeOfBigBlock()

SIZE_T NTAPI RtlpGetSizeOfBigBlock ( PHEAP_ENTRY  HeapEntry)

Definition at line 500 of file heap.c.

501 {
502  PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
503 
504  /* Get pointer to the containing record */
505  VirtualEntry = CONTAINING_RECORD(HeapEntry, HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock);
506  ASSERT(VirtualEntry->BusyBlock.Size >= sizeof(HEAP_VIRTUAL_ALLOC_ENTRY));
507 
508  /* Restore the real size */
509  return VirtualEntry->CommitSize - HeapEntry->Size;
510 }
Definition: heap.h:307
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:311
#define ASSERT(a)
Definition: mode.c:44
HEAP_ENTRY BusyBlock
Definition: heap.h:313

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

2397 {
2398  UCHAR EntryFlags, RememberFlags;
2399  PHEAP_FREE_ENTRY FreeEntry, UnusedEntry, FollowingEntry;
2400  SIZE_T FreeSize, PrevSize, TailPart, AddedSize = 0;
2401  PHEAP_ENTRY_EXTRA OldExtra, NewExtra;
2402  UCHAR SegmentOffset;
2403 
2404  /* We can't grow beyond specified threshold */
2405  if (Index > Heap->VirtualMemoryThreshold)
2406  return FALSE;
2407 
2408  /* Get entry flags */
2409  EntryFlags = InUseEntry->Flags;
2410 
2411  if (RtlpIsLastCommittedEntry(InUseEntry))
2412  {
2413  /* There is no next block, just uncommitted space. Calculate how much is needed */
2414  FreeSize = (Index - InUseEntry->Size) << HEAP_ENTRY_SHIFT;
2415  FreeSize = ROUND_UP(FreeSize, PAGE_SIZE);
2416 
2417  /* Find and commit those pages */
2418  FreeEntry = RtlpFindAndCommitPages(Heap,
2419  Heap->Segments[InUseEntry->SegmentOffset],
2420  &FreeSize,
2421  (PVOID)PAGE_ROUND_UP(InUseEntry + InUseEntry->Size));
2422 
2423  /* Fail if it failed... */
2424  if (!FreeEntry) return FALSE;
2425 
2426  /* It was successful, perform coalescing */
2427  FreeSize = FreeSize >> HEAP_ENTRY_SHIFT;
2428  FreeEntry = RtlpCoalesceFreeBlocks(Heap, FreeEntry, &FreeSize, FALSE);
2429 
2430  /* Check if it's enough */
2431  if (FreeSize + InUseEntry->Size < Index)
2432  {
2433  /* Still not enough */
2434  RtlpInsertFreeBlock(Heap, FreeEntry, FreeSize);
2435  Heap->TotalFreeSize += FreeSize;
2436  return FALSE;
2437  }
2438 
2439  /* Remember flags of this free entry */
2440  RememberFlags = FreeEntry->Flags;
2441 
2442  /* Sum up sizes */
2443  FreeSize += InUseEntry->Size;
2444  }
2445  else
2446  {
2447  FreeEntry = (PHEAP_FREE_ENTRY)(InUseEntry + InUseEntry->Size);
2448 
2449  /* The next block indeed exists. Check if it's free or in use */
2450  if (FreeEntry->Flags & HEAP_ENTRY_BUSY) return FALSE;
2451 
2452  /* Next entry is free, check if it can fit the block we need */
2453  FreeSize = InUseEntry->Size + FreeEntry->Size;
2454  if (FreeSize < Index) return FALSE;
2455 
2456  /* Remember flags of this free entry */
2457  RememberFlags = FreeEntry->Flags;
2458 
2459  /* Remove this block from the free list */
2460  RtlpRemoveFreeBlock(Heap, FreeEntry, FALSE);
2461  Heap->TotalFreeSize -= FreeEntry->Size;
2462  }
2463 
2464  PrevSize = (InUseEntry->Size << HEAP_ENTRY_SHIFT) - InUseEntry->UnusedBytes;
2465  FreeSize -= Index;
2466 
2467  /* Don't produce too small blocks */
2468  if (FreeSize <= 2)
2469  {
2470  Index += FreeSize;
2471  FreeSize = 0;
2472  }
2473 
2474  /* Process extra stuff */
2475  if (EntryFlags & HEAP_ENTRY_EXTRA_PRESENT)
2476  {
2477  /* Calculate pointers */
2478  OldExtra = (PHEAP_ENTRY_EXTRA)(InUseEntry + InUseEntry->Size - 1);
2479  NewExtra = (PHEAP_ENTRY_EXTRA)(InUseEntry + Index - 1);
2480 
2481  /* Copy contents */
2482  *NewExtra = *OldExtra;
2483 
2484  // FIXME Tagging
2485  }
2486 
2487  /* Update sizes */
2488  InUseEntry->Size = (USHORT)Index;
2489  InUseEntry->UnusedBytes = (UCHAR)((Index << HEAP_ENTRY_SHIFT) - Size);
2490 
2491  /* Check if there is a free space remaining after merging those blocks */
2492  if (!FreeSize)
2493  {
2494  /* Update flags and sizes */
2495  InUseEntry->Flags |= RememberFlags & HEAP_ENTRY_LAST_ENTRY;
2496 
2497  /* Either update previous size of the next entry or mark it as a last
2498  entry in the segment */
2499  if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
2500  {
2501  (InUseEntry + InUseEntry->Size)->PreviousSize = InUseEntry->Size;
2502  }
2503  else
2504  {
2505  SegmentOffset = InUseEntry->SegmentOffset;
2506  ASSERT(SegmentOffset < HEAP_SEGMENTS);
2507  }
2508  }
2509  else
2510  {
2511  /* Complex case, we need to split the block to give unused free space
2512  back to the heap */
2513  UnusedEntry = (PHEAP_FREE_ENTRY)(InUseEntry + Index);
2514  UnusedEntry->PreviousSize = (USHORT)Index;
2515  UnusedEntry->SegmentOffset = InUseEntry->SegmentOffset;
2516 
2517  /* Update the following block or set the last entry in the segment */
2518  if (RememberFlags & HEAP_ENTRY_LAST_ENTRY)
2519  {
2520  SegmentOffset = UnusedEntry->SegmentOffset;
2521  ASSERT(SegmentOffset < HEAP_SEGMENTS);
2522 
2523  /* Set flags and size */
2524  UnusedEntry->Flags = RememberFlags;
2525  UnusedEntry->Size = (USHORT)FreeSize;
2526 
2527  /* Insert it to the heap and update total size */
2528  RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
2529  Heap->TotalFreeSize += FreeSize;
2530  }
2531  else
2532  {
2533  /* There is a block after this one */
2534  FollowingEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)UnusedEntry + FreeSize);
2535 
2536  if (FollowingEntry->Flags & HEAP_ENTRY_BUSY)
2537  {
2538  /* Update flags and set size of the unused space entry */
2539  UnusedEntry->Flags = RememberFlags & (~HEAP_ENTRY_LAST_ENTRY);
2540  UnusedEntry->Size = (USHORT)FreeSize;
2541 
2542  /* Update previous size of the following entry */
2543  FollowingEntry->PreviousSize = (USHORT)FreeSize;
2544 
2545  /* Insert it to the heap and update total free size */
2546  RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
2547  Heap->TotalFreeSize += FreeSize;
2548  }
2549  else
2550  {
2551  /* That following entry is also free, what a fortune! */
2552  RememberFlags = FollowingEntry->Flags;
2553 
2554  /* Remove it */
2555  RtlpRemoveFreeBlock(Heap, FollowingEntry, FALSE);
2556  Heap->TotalFreeSize -= FollowingEntry->Size;
2557 
2558  /* And make up a new combined block */
2559  FreeSize += FollowingEntry->Size;
2560  UnusedEntry->Flags = RememberFlags;
2561 
2562  /* Check where to put it */
2563  if (FreeSize <= HEAP_MAX_BLOCK_SIZE)
2564  {
2565  /* Fine for a dedicated list */
2566  UnusedEntry->Size = (USHORT)FreeSize;
2567 
2568  if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
2569  {
2570  ((PHEAP_ENTRY)UnusedEntry + FreeSize)->PreviousSize = (USHORT)FreeSize;
2571  }
2572  else
2573  {
2574  SegmentOffset = UnusedEntry->SegmentOffset;
2575  ASSERT(SegmentOffset < HEAP_SEGMENTS);
2576  }
2577 
2578  /* Insert it back and update total size */
2579  RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
2580  Heap->TotalFreeSize += FreeSize;
2581  }
2582  else
2583  {
2584  /* The block is very large, leave all the hassle to the insertion routine */
2585  RtlpInsertFreeBlock(Heap, UnusedEntry, FreeSize);
2586  }
2587  }
2588  }
2589  }
2590 
2591  /* Properly "zero out" (and fill!) the space */
2592  if (Flags & HEAP_ZERO_MEMORY)
2593  {
2594  RtlZeroMemory((PCHAR)(InUseEntry + 1) + PrevSize, Size - PrevSize);
2595  }
2596  else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
2597  {
2598  /* Calculate tail part which we need to fill */
2599  TailPart = PrevSize & (sizeof(ULONG) - 1);
2600 
2601  /* "Invert" it as usual */
2602  if (TailPart) TailPart = 4 - TailPart;
2603 
2604  if (Size > (PrevSize + TailPart))
2605  AddedSize = (Size - (PrevSize + TailPart)) & ~(sizeof(ULONG) - 1);
2606 
2607  if (AddedSize)
2608  {
2609  RtlFillMemoryUlong((PCHAR)(InUseEntry + 1) + PrevSize + TailPart,
2610  AddedSize,
2612  }
2613  }
2614 
2615  /* Fill the new tail */
2616  if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED)
2617  {
2618  RtlFillMemory((PCHAR)(InUseEntry + 1) + Size,
2620  HEAP_TAIL_FILL);
2621  }
2622 
2623  /* Copy user settable flags */
2624  InUseEntry->Flags &= ~HEAP_ENTRY_SETTABLE_FLAGS;
2625  InUseEntry->Flags |= ((Flags & HEAP_SETTABLE_USER_FLAGS) >> 4);
2626 
2627  /* Return success */
2628  return TRUE;
2629 }
signed char * PCHAR
Definition: retypes.h:7
#define HEAP_ENTRY_SETTABLE_FLAGS
Definition: heap.h:48
#define ARENA_INUSE_FILLER
Definition: oleaut.c:105
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:238
#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:1150
#define HEAP_SEGMENTS
Definition: heap.h:15
#define TRUE
Definition: types.h:120
static VOID RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN NoFill)
Definition: heap.c:422
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:23
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
if(dx==0 &&dy==0)
Definition: linetemp.h:174
static PHEAP_FREE_ENTRY RtlpFindAndCommitPages(PHEAP Heap, PHEAP_SEGMENT Segment, PSIZE_T Size, PVOID AddressRequested)
Definition: heap.c:690
#define FALSE
Definition: types.h:117
Definition: heap.h:291
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:357
Definition: heap.h:129
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
#define HEAP_ENTRY_SHIFT
Definition: heap.h:21
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ASSERT(a)
Definition: mode.c:44
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
_In_ WDFCOLLECTION _In_ ULONG Index
#define HEAP_ENTRY_SIZE
Definition: heap.h:17
#define HEAP_SETTABLE_USER_FLAGS
Definition: nt_native.h:1708
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: heap.h:135
unsigned short USHORT
Definition: pedump.c:61
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44
static BOOLEAN RtlpIsLastCommittedEntry(PHEAP_ENTRY Entry)
Definition: heap.c:86
#define HEAP_TAIL_FILL
Definition: heap.h:27
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:41
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 106 of file heap.c.

110 {
111  ULONG NumUCRs = 8;
112  ULONG Index;
113  SIZE_T HeaderSize;
115  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
116  SIZE_T DeCommitFreeBlockThreshold;
117 
118  /* Preconditions */
119  ASSERT(Heap != NULL);
120  ASSERT(Parameters != NULL);
122  ASSERT(!(Flags & HEAP_NO_SERIALIZE) || (Lock == NULL)); /* HEAP_NO_SERIALIZE => no lock */
123 
124  /* Make sure we're not doing stupid things */
125  DeCommitFreeBlockThreshold = Parameters->DeCommitFreeBlockThreshold >> HEAP_ENTRY_SHIFT;
126  /* Start out with the size of a plain Heap header + our hints of free entries + the bitmap */
127  HeaderSize = FIELD_OFFSET(HEAP, FreeHints[DeCommitFreeBlockThreshold])
128  + (ROUND_UP(DeCommitFreeBlockThreshold, RTL_BITS_OF(ULONG)) / RTL_BITS_OF(ULONG)) * sizeof(ULONG);
129 
130  /* Check if space needs to be added for the Heap Lock */
131  if (!(Flags & HEAP_NO_SERIALIZE))
132  {
133  if (Lock != NULL)
134  /* The user manages the Heap Lock */
136  else
137  if (RtlpGetMode() == UserMode)
138  {
139  /* In user mode, the Heap Lock trails the Heap header */
140  Lock = (PHEAP_LOCK) ((ULONG_PTR) (Heap) + HeaderSize);
141  HeaderSize += sizeof(HEAP_LOCK);
142  }
143  }
144 
145  /* Add space for the initial Heap UnCommitted Range Descriptor list */
146  UcrDescriptor = (PHEAP_UCR_DESCRIPTOR) ((ULONG_PTR) (Heap) + HeaderSize);
147  HeaderSize += NumUCRs * sizeof(HEAP_UCR_DESCRIPTOR);
148 
149  HeaderSize = ROUND_UP(HeaderSize, HEAP_ENTRY_SIZE);
150  /* Sanity check */
151  ASSERT(HeaderSize <= PAGE_SIZE);
152 
153  /* Initialise the Heap Entry header containing the Heap header */
154  Heap->Entry.Size = (USHORT)(HeaderSize >> HEAP_ENTRY_SHIFT);
155  Heap->Entry.Flags = HEAP_ENTRY_BUSY;
156  Heap->Entry.SmallTagIndex = LOBYTE(Heap->Entry.Size) ^ HIBYTE(Heap->Entry.Size) ^ Heap->Entry.Flags;
157  Heap->Entry.PreviousSize = 0;
158  Heap->Entry.SegmentOffset = 0;
159  Heap->Entry.UnusedBytes = 0;
160 
161  /* Initialise the Heap header */
162  Heap->Signature = HEAP_SIGNATURE;
163  Heap->Flags = Flags;
164  Heap->ForceFlags = (Flags & (HEAP_NO_SERIALIZE |
173 
174  /* Initialise the Heap parameters */
175  Heap->VirtualMemoryThreshold = ROUND_UP(Parameters->VirtualMemoryThreshold, sizeof(HEAP_ENTRY)) >> HEAP_ENTRY_SHIFT;
176  Heap->SegmentReserve = Parameters->SegmentReserve;
177  Heap->SegmentCommit = Parameters->SegmentCommit;
178  Heap->DeCommitFreeBlockThreshold = DeCommitFreeBlockThreshold;
179  Heap->DeCommitTotalFreeThreshold = Parameters->DeCommitTotalFreeThreshold >> HEAP_ENTRY_SHIFT;
180  Heap->MaximumAllocationSize = Parameters->MaximumAllocationSize;
181  Heap->CommitRoutine = Parameters->CommitRoutine;
182 
183  /* Initialise the Heap validation info */
184  Heap->HeaderValidateCopy = NULL;
185  Heap->HeaderValidateLength = (USHORT)HeaderSize;
186 
187  /* Initialise the Heap Lock */
189  {
191  if (!NT_SUCCESS(Status))
192  return Status;
193  }
194  Heap->LockVariable = Lock;
195 
196  /* Initialise the Heap alignment info */
198  {
199  Heap->AlignMask = (ULONG) ~15;
200  Heap->AlignRound = 15 + sizeof(HEAP_ENTRY);
201  }
202  else
203  {
204  Heap->AlignMask = (ULONG) ~(sizeof(HEAP_ENTRY) - 1);
205  Heap->AlignRound = 2 * sizeof(HEAP_ENTRY) - 1;
206  }
207 
209  Heap->AlignRound += sizeof(HEAP_ENTRY);
210 
211  /* Initialise the Heap Segment list */
212  for (Index = 0; Index < HEAP_SEGMENTS; ++Index)
213  Heap->Segments[Index] = NULL;
214 
215  /* Initialise the free entry lists. */
216  InitializeListHead(&Heap->FreeLists);
217  RtlInitializeBitMap(&Heap->FreeHintBitmap,
218  (PULONG)&Heap->FreeHints[DeCommitFreeBlockThreshold],
219  DeCommitFreeBlockThreshold);
220  RtlClearAllBits(&Heap->FreeHintBitmap);
221  RtlZeroMemory(&Heap->FreeHints[0], sizeof(Heap->FreeHints[0]) * DeCommitFreeBlockThreshold);
222 
223  /* Initialise the Heap Virtual Allocated Blocks list */
224  InitializeListHead(&Heap->VirtualAllocdBlocks);
225 
226  /* Initialise the Heap UnCommitted Region lists */
227  InitializeListHead(&Heap->UCRSegments);
228  InitializeListHead(&Heap->UCRList);
229 
230  /* Register the initial Heap UnCommitted Region Descriptors */
231  for (Index = 0; Index < NumUCRs; ++Index)
232  InsertTailList(&Heap->UCRList, &UcrDescriptor[Index].ListEntry);
233 
234  return STATUS_SUCCESS;
235 }
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
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:863
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
#define HEAP_SEGMENTS
Definition: heap.h:15
struct _HEAP_UCR_DESCRIPTOR * PHEAP_UCR_DESCRIPTOR
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
#define HIBYTE(W)
Definition: jmemdos.c:486
struct _HEAP_LOCK HEAP_LOCK
#define InsertTailList(ListHead, Entry)
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
struct _HEAP_LOCK * PHEAP_LOCK
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
#define HEAP_VALIDATE_PARAMETERS_ENABLED
Definition: rtltypes.h:167
#define HEAP_ENTRY_SHIFT
Definition: heap.h:21
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
Status
Definition: gdiplustypes.h:24
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ WDFCOLLECTION _In_ ULONG Index
#define HEAP_VALIDATE_ALL_ENABLED
Definition: rtltypes.h:166
#define HEAP_ENTRY_SIZE
Definition: heap.h:17
NTSTATUS NTAPI RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
Definition: libsupp.c:126
#define HEAP_LOCK_USER_ALLOCATED
Definition: rtltypes.h:168
#define PAGE_SIZE
Definition: env_spec_w32.h:49
struct _HEAP_ENTRY HEAP_ENTRY
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: heap.h:135
unsigned short USHORT
Definition: pedump.c:61
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define HEAP_SIGNATURE
Definition: heap.h:51
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_SUCCESS
Definition: shellext.h:65
#define RTL_BITS_OF(sizeOfArg)
Definition: ntbasedef.h:668
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
#define HEAP_REALLOC_IN_PLACE_ONLY
Definition: nt_native.h:1696
Definition: heap.c:51
struct _HEAP_UCR_DESCRIPTOR HEAP_UCR_DESCRIPTOR

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

1008 {
1009  /* Preconditions */
1010  ASSERT(Heap != NULL);
1011  ASSERT(Segment != NULL);
1012  ASSERT(SegmentCommit >= PAGE_SIZE);
1013  ASSERT(ROUND_DOWN(SegmentCommit, PAGE_SIZE) == SegmentCommit);
1014  ASSERT(SegmentReserve >= SegmentCommit);
1015  ASSERT(ROUND_DOWN(SegmentReserve, PAGE_SIZE) == SegmentReserve);
1016 
1017  DPRINT("RtlpInitializeHeapSegment(%p %p %x %x %lx %lx)\n", Heap, Segment, SegmentIndex, SegmentFlags, SegmentReserve, SegmentCommit);
1018 
1019  /* Initialise the Heap Entry header if this is not the first Heap Segment */
1020  if ((PHEAP_SEGMENT) (Heap) != Segment)
1021  {
1022  Segment->Entry.Size = ROUND_UP(sizeof(HEAP_SEGMENT), sizeof(HEAP_ENTRY)) >> HEAP_ENTRY_SHIFT;
1023  Segment->Entry.Flags = HEAP_ENTRY_BUSY;
1024  Segment->Entry.SmallTagIndex = LOBYTE(Segment->Entry.Size) ^ HIBYTE(Segment->Entry.Size) ^ Segment->Entry.Flags;
1025  Segment->Entry.PreviousSize = 0;
1026  Segment->Entry.SegmentOffset = SegmentIndex;
1027  Segment->Entry.UnusedBytes = 0;
1028  }
1029 
1030  /* Sanity check */
1031  ASSERT((Segment->Entry.Size << HEAP_ENTRY_SHIFT) <= PAGE_SIZE);
1032 
1033  /* Initialise the Heap Segment header */
1034  Segment->SegmentSignature = HEAP_SEGMENT_SIGNATURE;
1035  Segment->SegmentFlags = SegmentFlags;
1036  Segment->Heap = Heap;
1037  Heap->Segments[SegmentIndex] = Segment;
1038 
1039  /* Initialise the Heap Segment location information */
1040  Segment->BaseAddress = Segment;
1041  Segment->NumberOfPages = (ULONG)(SegmentReserve >> PAGE_SHIFT);
1042 
1043  /* Initialise the Heap Entries contained within the Heap Segment */
1044  Segment->FirstEntry = &Segment->Entry + Segment->Entry.Size;
1045  Segment->LastValidEntry = (PHEAP_ENTRY)((ULONG_PTR)Segment + SegmentReserve);
1046 
1047  /* Initialise the Heap Segment UnCommitted Range information */
1048  Segment->NumberOfUnCommittedPages = (ULONG)((SegmentReserve - SegmentCommit) >> PAGE_SHIFT);
1049  Segment->NumberOfUnCommittedRanges = 0;
1050  InitializeListHead(&Segment->UCRSegmentList);
1051 
1052  /* We must have space for a guard entry ! */
1053  ASSERT (((SegmentCommit >> HEAP_ENTRY_SHIFT) > Segment->Entry.Size) || (Segment->NumberOfUnCommittedPages == 0));
1054 
1055  if (((SIZE_T)Segment->Entry.Size << HEAP_ENTRY_SHIFT) < SegmentCommit)
1056  {
1057  PHEAP_ENTRY FreeEntry = NULL;
1058 
1059  if (Segment->NumberOfUnCommittedPages != 0)
1060  {
1061  /* Ensure we put our guard entry at the end of the last committed page */
1062  PHEAP_ENTRY GuardEntry = &Segment->Entry + (SegmentCommit >> HEAP_ENTRY_SHIFT) - 1;
1063 
1064  ASSERT(GuardEntry > &Segment->Entry);
1065  GuardEntry->Size = 1;
1066  GuardEntry->Flags = HEAP_ENTRY_BUSY | HEAP_ENTRY_LAST_ENTRY;
1067  GuardEntry->SegmentOffset = SegmentIndex;
1068  GuardEntry->PreviousSize = GuardEntry - Segment->FirstEntry;
1069 
1070  /* Chack what is left behind us */
1071  switch (GuardEntry->PreviousSize)
1072  {
1073  case 1:
1074  /* There is not enough space for a free entry. Double the guard entry */
1075  GuardEntry--;
1076  GuardEntry->Size = 1;
1077  GuardEntry->Flags = HEAP_ENTRY_BUSY | HEAP_ENTRY_LAST_ENTRY;
1078  GuardEntry->SegmentOffset = SegmentIndex;
1079  DPRINT1("Setting %p as UCR guard entry.\n", GuardEntry);
1080  /* Fall through */
1081  case 0:
1082  ASSERT(GuardEntry == Segment->FirstEntry);
1083  GuardEntry->PreviousSize = Segment->Entry.Size;
1084  break;
1085  default:
1086  /* There will be a free entry between the segment and the guard entry */
1087  FreeEntry = Segment->FirstEntry;
1088  FreeEntry->PreviousSize = Segment->Entry.Size;
1089  FreeEntry->SegmentOffset = SegmentIndex;
1090  FreeEntry->Size = GuardEntry->PreviousSize;
1091  FreeEntry->Flags = 0;
1092  break;
1093  }
1094  }
1095  else
1096  {
1097  /* Prepare a Free Heap Entry header */
1098  FreeEntry = Segment->FirstEntry;
1099  FreeEntry->PreviousSize = Segment->Entry.Size;
1100  FreeEntry->SegmentOffset = SegmentIndex;
1101  FreeEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
1102  FreeEntry->Size = (SegmentCommit >> HEAP_ENTRY_SHIFT) - Segment->Entry.Size;
1103  }
1104 
1105  /* Register the Free Heap Entry */
1106  if (FreeEntry)
1107  RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY)FreeEntry, FreeEntry->Size);
1108  }
1109 
1110  /* Register the UnCommitted Range of the Heap Segment */
1111  if (Segment->NumberOfUnCommittedPages != 0)
1112  RtlpInsertUnCommittedPages(Segment, (ULONG_PTR) (Segment) + SegmentCommit, SegmentReserve - SegmentCommit);
1113 
1114  return STATUS_SUCCESS;
1115 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
uint32_t ULONG_PTR
Definition: typedefs.h:65
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:357
Definition: heap.h:129
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
#define HEAP_ENTRY_SHIFT
Definition: heap.h:21
#define HEAP_SEGMENT_SIGNATURE
Definition: heap.h:52
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
#define ASSERT(a)
Definition: mode.c:44
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
ULONG_PTR SIZE_T
Definition: typedefs.h:80
VOID NTAPI RtlpInsertUnCommittedPages(PHEAP_SEGMENT Segment, ULONG_PTR Address, SIZE_T Size)
Definition: heap.c:620
Definition: heap.h:135
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define NULL
Definition: types.h:112
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44
#define DPRINT1
Definition: precomp.h:8
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71

Referenced by RtlCreateHeap(), and RtlpExtendHeap().

◆ RtlpInsertFreeBlock()

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

Definition at line 357 of file heap.c.

360 {
361  USHORT Size, PreviousSize;
362  UCHAR SegmentOffset, Flags;
364 
365  DPRINT("RtlpInsertFreeBlock(%p %p %x)\n", Heap, FreeEntry, BlockSize);
366 
367  /* Increase the free size counter */
368  Heap->TotalFreeSize += BlockSize;
369 
370  /* Remember certain values */
371  Flags = FreeEntry->Flags;
372  PreviousSize = FreeEntry->PreviousSize;
373  SegmentOffset = FreeEntry->SegmentOffset;
374  Segment = Heap->Segments[SegmentOffset];
375 
376  /* Process it */
377  while (BlockSize)
378  {
379  /* Check for the max size */
380  if (BlockSize > HEAP_MAX_BLOCK_SIZE)
381  {
383 
384  /* Special compensation if it goes above limit just by 1 */
385  if (BlockSize == (HEAP_MAX_BLOCK_SIZE + 1))
386  Size -= 16;
387 
388  FreeEntry->Flags = 0;
389  }
390  else
391  {
392  Size = (USHORT)BlockSize;
393  FreeEntry->Flags = Flags;
394  }
395 
396  /* Change its size and insert it into a free list */
397  FreeEntry->Size = Size;
398  FreeEntry->PreviousSize = PreviousSize;
399  FreeEntry->SegmentOffset = SegmentOffset;
400 
401  /* Call a helper to actually insert the block */
402  RtlpInsertFreeBlockHelper(Heap, FreeEntry, Size, FALSE);
403 
404  /* Update sizes */
405  PreviousSize = Size;
406  BlockSize -= Size;
407 
408  /* Go to the next entry */
409  FreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + Size);
410 
411  /* Check if that's all */
412  if ((PHEAP_ENTRY)FreeEntry >= Segment->LastValidEntry) return;
413  }
414 
415  /* Update previous size if needed */
416  if (!(Flags & HEAP_ENTRY_LAST_ENTRY))
417  FreeEntry->PreviousSize = PreviousSize;
418 }
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:238
SIZE_T TotalFreeSize
Definition: heap.h:239
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:23
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:253
#define FALSE
Definition: types.h:117
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
Definition: heap.h:135
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44
#define DPRINT
Definition: sndvol32.h:71

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

242 {
243  ULONG HintIndex, NextHintIndex;
244 
245  ASSERT(FreeEntry->Size == BlockSize);
246 
247  /* Fill if it's not denied */
248  if (!NoFill)
249  {
250  FreeEntry->Flags &= ~(HEAP_ENTRY_FILL_PATTERN |
253 
254  if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED)
255  {
256  RtlFillMemoryUlong((PCHAR)(FreeEntry + 1),
257  (BlockSize << HEAP_ENTRY_SHIFT) - sizeof(*FreeEntry),
259 
260  FreeEntry->Flags |= HEAP_ENTRY_FILL_PATTERN;
261  }
262  }
263  else
264  {
265  /* Clear out all flags except the last entry one */
266  FreeEntry->Flags &= HEAP_ENTRY_LAST_ENTRY;
267  }
268 
269  /* See if this should go to the dedicated list */
270  if (BlockSize > Heap->DeCommitFreeBlockThreshold)
271  {
272  PLIST_ENTRY ListEntry = Heap->FreeHints[0];
273 
274  /* Check if we have a hint there */
275  if (ListEntry == NULL)
276  {
277  ASSERT(!RtlTestBit(&Heap->FreeHintBitmap, 0));
278  Heap->FreeHints[0] = &FreeEntry->FreeList;
279  RtlSetBit(&Heap->FreeHintBitmap, 0);
280  InsertTailList(&Heap->FreeLists, &FreeEntry->FreeList);
281  return;
282  }
283 
284  ASSERT(RtlTestBit(&Heap->FreeHintBitmap, 0));
285 
286  while (ListEntry != &Heap->FreeLists)
287  {
288  PHEAP_FREE_ENTRY PreviousEntry = CONTAINING_RECORD(ListEntry,
290  FreeList);
291  if (PreviousEntry->Size >= BlockSize)
292  {
293  DPRINT("Inserting size %lu before %lu.\n", BlockSize, PreviousEntry->Size);
294  break;
295  }
296 
297  ListEntry = ListEntry->Flink;
298  }
299 
300  InsertTailList(ListEntry, &FreeEntry->FreeList);
301 
302  /* Update our hint if needed */
303  if (Heap->FreeHints[0] == ListEntry)
304  Heap->FreeHints[0] = &FreeEntry->FreeList;
305 
306  return;
307  }
308 
309  ASSERT(BlockSize >= 2);
310  HintIndex = BlockSize - 1;
311 
312  if (Heap->FreeHints[HintIndex] != NULL)
313  {
315 
316  /* Insert it after our hint. */
317  InsertHeadList(Heap->FreeHints[HintIndex], &FreeEntry->FreeList);
318 
319  return;
320  }
321 
322  /* This is the first time we insert such an entry in the list. */
324  if (IsListEmpty(&Heap->FreeLists))
325  {
326  /* First entry inserted in this list ever */
327  InsertHeadList(&Heap->FreeLists, &FreeEntry->FreeList);
329  Heap->FreeHints[HintIndex] = &FreeEntry->FreeList;
330  return;
331  }
332 
333  /* Find the closest one */
334  NextHintIndex = RtlFindSetBits(&Heap->FreeHintBitmap, 1, HintIndex);
335  ASSERT(NextHintIndex != 0xFFFFFFFF);
336  if ((NextHintIndex == 0) || (NextHintIndex > HintIndex))
337  {
338  /*
339  * We found a larger entry. Insert this one before.
340  * It is guaranteed to be our successor in the list.
341  */
342  InsertTailList(Heap->FreeHints[NextHintIndex], &FreeEntry->FreeList);
343  }
344  else
345  {
346  /* We only found an entry smaller than us. Then we will be the largest one. */
347  ASSERT(CONTAINING_RECORD(Heap->FreeLists.Blink, HEAP_FREE_ENTRY, FreeList)->Size < BlockSize);
348  InsertTailList(&Heap->FreeLists, &FreeEntry->FreeList);
349  }
350 
351  /* Setup our hint */
353  Heap->FreeHints[HintIndex] = &FreeEntry->FreeList;
354 }
signed char * PCHAR
Definition: retypes.h:7
#define ARENA_FREE_FILLER
Definition: jsutils.c:64
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LIST_ENTRY FreeLists
Definition: heap.h:259
NTSYSAPI VOID NTAPI RtlSetBit(_In_ PRTL_BITMAP BitMapHeader, _In_range_(<, BitMapHeader->SizeOfBitMap) ULONG BitNumber)
Definition: bitmap.c:304
LIST_ENTRY FreeList
Definition: heap.h:131
NTSYSAPI ULONG WINAPI RtlFindSetBits(PCRTL_BITMAP, ULONG, ULONG)
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
_In_ ULONG _In_ ULONG HintIndex
Definition: rtlfuncs.h:609
PLIST_ENTRY FreeHints[ANYSIZE_ARRAY]
Definition: heap.h:268
Definition: heap.h:129
RTL_BITMAP FreeHintBitmap
Definition: heap.h:267
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
#define HEAP_ENTRY_SHIFT
Definition: heap.h:21
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ASSERT(a)
Definition: mode.c:44
_Must_inspect_result_ NTSYSAPI BOOLEAN NTAPI RtlTestBit(_In_ PRTL_BITMAP BitMapHeader, _In_range_(<, BitMapHeader->SizeOfBitMap) ULONG BitNumber)
Definition: bitmap.c:434
Definition: typedefs.h:119
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:42
ULONG Flags
Definition: heap.h:226
#define NULL
Definition: types.h:112
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44
SIZE_T DeCommitFreeBlockThreshold
Definition: heap.h:237
unsigned int ULONG
Definition: retypes.h:1
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:41
#define DPRINT
Definition: sndvol32.h:71

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

◆ RtlpInsertUnCommittedPages()

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

Definition at line 620 of file heap.c.

623 {
624  PLIST_ENTRY Current;
625  PHEAP_UCR_DESCRIPTOR UcrDescriptor;
626 
627  DPRINT("RtlpInsertUnCommittedPages(%p %08Ix %Ix)\n", Segment, Address, Size);
628 
629  /* Go through the list of UCR descriptors, they are sorted from lowest address
630  to the highest */
631  Current = Segment->UCRSegmentList.Flink;
632  while (Current != &Segment->UCRSegmentList)
633  {
634  UcrDescriptor = CONTAINING_RECORD(Current, HEAP_UCR_DESCRIPTOR, SegmentEntry);
635 
636  if ((ULONG_PTR)UcrDescriptor->Address > Address)
637  {
638  /* Check for a really lucky case */
639  if ((Address + Size) == (ULONG_PTR)UcrDescriptor->Address)
640  {
641  /* Exact match */
642  UcrDescriptor->Address = (PVOID)Address;
643  UcrDescriptor->Size += Size;
644  return;
645  }
646 
647  /* We found the block before which the new one should go */
648  break;
649  }
650  else if (((ULONG_PTR)UcrDescriptor->Address + UcrDescriptor->Size) == Address)
651  {
652  /* Modify this entry */
653  Address = (ULONG_PTR)UcrDescriptor->Address;
654  Size += UcrDescriptor->Size;
655 
656  /* Advance to the next descriptor */
657  Current = Current->Flink;
658 
659  /* Remove the current descriptor from the list and destroy it */
660  RemoveEntryList(&UcrDescriptor->SegmentEntry);
661  RtlpDestroyUnCommittedRange(Segment, UcrDescriptor);
662 
663  Segment->NumberOfUnCommittedRanges--;
664  }
665  else
666  {
667  /* Advance to the next descriptor */
668  Current = Current->Flink;
669  }
670  }
671 
672  /* Create a new UCR descriptor */
673  UcrDescriptor = RtlpCreateUnCommittedRange(Segment);
674  if (!UcrDescriptor) return;
675 
676  UcrDescriptor->Address = (PVOID)Address;
677  UcrDescriptor->Size = Size;
678 
679  /* "Current" is the descriptor before which our one should go */
680  InsertTailList(Current, &UcrDescriptor->SegmentEntry);
681 
682  DPRINT("Added segment UCR with base %08Ix, size 0x%x\n", Address, Size);
683 
684  /* Increase counters */
685  Segment->NumberOfUnCommittedRanges++;
686 }
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
static PVOID
Definition: heap.c:41
#define InsertTailList(ListHead, Entry)
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
static WCHAR Address[46]
Definition: ping.c:68
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
VOID NTAPI RtlpDestroyUnCommittedRange(PHEAP_SEGMENT Segment, PHEAP_UCR_DESCRIPTOR UcrDescriptor)
Definition: heap.c:608
LIST_ENTRY SegmentEntry
Definition: heap.h:279
Definition: typedefs.h:119
PHEAP_UCR_DESCRIPTOR NTAPI RtlpCreateUnCommittedRange(PHEAP_SEGMENT Segment)
Definition: heap.c:513
#define ULONG_PTR
Definition: config.h:101
#define DPRINT
Definition: sndvol32.h:71

Referenced by RtlpDeCommitFreeBlock(), and RtlpInitializeHeapSegment().

◆ RtlpIsLastCommittedEntry()

static BOOLEAN RtlpIsLastCommittedEntry ( PHEAP_ENTRY  Entry)
static

Definition at line 86 of file heap.c.

87 {
88  if (Entry->Flags & HEAP_ENTRY_LAST_ENTRY)
89  return TRUE;
90 
91  Entry = Entry + Entry->Size;
92 
93  /* 1-sized busy last entry are the committed range guard entries */
94  if ((Entry->Flags != (HEAP_ENTRY_BUSY | HEAP_ENTRY_LAST_ENTRY)) || (Entry->Size != 1))
95  return FALSE;
96 
97  /* This must be the last or the penultimate entry in the page */
98  ASSERT(((PVOID)PAGE_ROUND_UP(Entry) == (Entry + 1)) ||
99  ((PVOID)PAGE_ROUND_UP(Entry)== (Entry + 2)));
100  return TRUE;
101 }
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
#define ASSERT(a)
Definition: mode.c:44
#define PAGE_ROUND_UP(x)
Definition: mmtypes.h:38
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44
base of all file and directory entries
Definition: entries.h:82

Referenced by RtlpDeCommitFreeBlock(), and RtlpGrowBlockInPlace().

◆ RtlpRemoveFreeBlock()

static VOID RtlpRemoveFreeBlock ( PHEAP  Heap,
PHEAP_FREE_ENTRY  FreeEntry,
BOOLEAN  NoFill 
)
static

Definition at line 422 of file heap.c.

425 {
426  SIZE_T Result, RealSize;
428 
429  /* Remove the free block */
430  if (FreeEntry->Size > Heap->DeCommitFreeBlockThreshold)
431  HintIndex = 0;
432  else
433  HintIndex = FreeEntry->Size - 1;
434 
436 
437  /* Are we removing the hint entry for this size ? */
438  if (Heap->FreeHints[HintIndex] == &FreeEntry->FreeList)
439  {
440  PHEAP_FREE_ENTRY NewHintEntry = NULL;
441  if (FreeEntry->FreeList.Flink != &Heap->FreeLists)
442  {
443  NewHintEntry = CONTAINING_RECORD(FreeEntry->FreeList.Flink,
445  FreeList);
446  /*
447  * In non-dedicated list, we just put the next entry as hint.
448  * For the dedicated ones, we take care of putting entries of the right size hint.
449  */
450  if ((HintIndex != 0) && (NewHintEntry->Size != FreeEntry->Size))
451  {
452  /* Of course this must be a larger one after us */
453  ASSERT(NewHintEntry->Size > FreeEntry->Size);
454  NewHintEntry = NULL;
455  }
456  }
457 
458  /* Replace the hint, if we can */
459  if (NewHintEntry != NULL)
460  {
461  Heap->FreeHints[HintIndex] = &NewHintEntry->FreeList;
462  }
463  else
464  {
465  Heap->FreeHints[HintIndex] = NULL;
467  }
468  }
469 
470  RemoveEntryList(&FreeEntry->FreeList);
471 
472  /* Fill with pattern if necessary */
473  if (!NoFill &&
474  (FreeEntry->Flags & HEAP_ENTRY_FILL_PATTERN))
475  {
476  RealSize = (FreeEntry->Size << HEAP_ENTRY_SHIFT) - sizeof(*FreeEntry);
477 
478  /* Deduct extra stuff from block's real size */
479  if (FreeEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT &&
480  RealSize > sizeof(HEAP_FREE_ENTRY_EXTRA))
481  {
482  RealSize -= sizeof(HEAP_FREE_ENTRY_EXTRA);
483  }
484 
485  /* Check if the free filler is intact */
486  Result = RtlCompareMemoryUlong((PCHAR)(FreeEntry + 1),
487  RealSize,
489 
490  if (Result != RealSize)
491  {
492  DPRINT1("Free heap block %p modified at %p after it was freed\n",
493  FreeEntry,
494  (PCHAR)(FreeEntry + 1) + Result);
495  }
496  }
497 }
signed char * PCHAR
Definition: retypes.h:7
_Must_inspect_result_ NTSYSAPI SIZE_T NTAPI RtlCompareMemoryUlong(_In_reads_bytes_(Length) PVOID Source, _In_ SIZE_T Length, _In_ ULONG Pattern)
#define ARENA_FREE_FILLER
Definition: jsutils.c:64
LIST_ENTRY FreeLists
Definition: heap.h:259
LIST_ENTRY FreeList
Definition: heap.h:131
_In_ ULONG _In_ ULONG HintIndex
Definition: rtlfuncs.h:609
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
Definition: heap.h:291
PLIST_ENTRY FreeHints[ANYSIZE_ARRAY]
Definition: heap.h:268
Definition: heap.h:129
RTL_BITMAP FreeHintBitmap
Definition: heap.h:267
_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:21
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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ASSERT(a)
Definition: mode.c:44
VOID NTAPI RtlClearBit(_In_ PRTL_BITMAP BitMapHeader, _In_ BITMAP_INDEX BitNumber)
Definition: bitmap.c:294
_Must_inspect_result_ NTSYSAPI BOOLEAN NTAPI RtlTestBit(_In_ PRTL_BITMAP BitMapHeader, _In_range_(<, BitMapHeader->SizeOfBitMap) ULONG BitNumber)
Definition: bitmap.c:434
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:42
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
SIZE_T DeCommitFreeBlockThreshold
Definition: heap.h:237
unsigned int ULONG
Definition: retypes.h:1
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:41
HEAP_ENTRY_EXTRA HEAP_FREE_ENTRY_EXTRA
Definition: heap.h:305

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

◆ RtlProtectHeap()

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

Definition at line 4052 of file heap.c.

4054 {
4055  UNIMPLEMENTED;
4056  return NULL;
4057 }
#define NULL
Definition: types.h:112
#define UNIMPLEMENTED
Definition: debug.h:115

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

1823 {
1824  PHEAP_FREE_ENTRY SplitBlock, SplitBlock2;
1825  UCHAR FreeFlags, EntryFlags = HEAP_ENTRY_BUSY;
1826  PHEAP_ENTRY InUseEntry;
1827  SIZE_T FreeSize;
1828  UCHAR SegmentOffset;
1829 
1830  /* Add extra flags in case of settable user value feature is requested,
1831  or there is a tag (small or normal) or there is a request to
1832  capture stack backtraces */
1833  if ((Flags & HEAP_EXTRA_FLAGS_MASK) ||
1834  Heap->PseudoTagEntries)
1835  {
1836  /* Add flag which means that the entry will have extra stuff attached */
1837  EntryFlags |= HEAP_ENTRY_EXTRA_PRESENT;
1838 
1839  /* NB! AllocationSize is already adjusted by RtlAllocateHeap */
1840  }
1841 
1842  /* Add settable user flags, if any */
1843  EntryFlags |= (Flags & HEAP_SETTABLE_USER_FLAGS) >> 4;
1844 
1845  /* Save flags, update total free size */
1846  FreeFlags = FreeBlock->Flags;
1847  Heap->TotalFreeSize -= FreeBlock->Size;
1848 
1849  /* Make this block an in-use one */
1850  InUseEntry = (PHEAP_ENTRY)FreeBlock;
1851  InUseEntry->Flags = EntryFlags;
1852  InUseEntry->SmallTagIndex = 0;
1853 
1854  /* Calculate the extra amount */
1855  FreeSize = InUseEntry->Size - Index;
1856 
1857  /* Update it's size fields (we don't need their data anymore) */
1858  InUseEntry->Size = (USHORT)Index;
1859  InUseEntry->UnusedBytes = (UCHAR)(AllocationSize - Size);
1860 
1861  /* If there is something to split - do the split */
1862  if (FreeSize != 0)
1863  {
1864  /* Don't split if resulting entry can't contain any payload data
1865  (i.e. being just HEAP_ENTRY_SIZE) */
1866  if (FreeSize == 1)
1867  {
1868  /* Increase sizes of the in-use entry */
1869  InUseEntry->Size++;
1870  InUseEntry->UnusedBytes += sizeof(HEAP_ENTRY);
1871  }
1872  else
1873  {
1874  /* Calculate a pointer to the new entry */
1875  SplitBlock = (PHEAP_FREE_ENTRY)(InUseEntry + Index);
1876 
1877  /* Initialize it */
1878  SplitBlock->Flags = FreeFlags;
1879  SplitBlock->SegmentOffset = InUseEntry->SegmentOffset;
1880  SplitBlock->Size = (USHORT)FreeSize;
1881  SplitBlock->PreviousSize = (USHORT)Index;
1882 
1883  /* Check if it's the last entry */
1884  if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
1885  {
1886  /* Insert it to the free list if it's the last entry */
1887  RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
1888  Heap->TotalFreeSize += FreeSize;
1889  }
1890  else
1891  {
1892  /* Not so easy - need to update next's previous size too */
1893  SplitBlock2 = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize);
1894 
1895  if (SplitBlock2->Flags & HEAP_ENTRY_BUSY)
1896  {
1897  SplitBlock2->PreviousSize = (USHORT)FreeSize;
1898  RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
1899  Heap->TotalFreeSize += FreeSize;
1900  }
1901  else
1902  {
1903  /* Even more complex - the next entry is free, so we can merge them into one! */
1904  SplitBlock->Flags = SplitBlock2->Flags;
1905 
1906  /* Remove that next entry */
1907  RtlpRemoveFreeBlock(Heap, SplitBlock2, FALSE);
1908 
1909  /* Update sizes */
1910  FreeSize += SplitBlock2->Size;
1911  Heap->TotalFreeSize -= SplitBlock2->Size;
1912 
1913  if (FreeSize <= HEAP_MAX_BLOCK_SIZE)
1914  {
1915  /* Insert it back */
1916  SplitBlock->Size = (USHORT)FreeSize;
1917 
1918  /* Don't forget to update previous size of the next entry! */
1919  if (!(SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY))
1920  {
1921  ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize))->PreviousSize = (USHORT)FreeSize;
1922  }
1923 
1924  /* Actually insert it */
1925  RtlpInsertFreeBlockHelper(Heap, SplitBlock, (USHORT)FreeSize, FALSE);
1926 
1927  /* Update total size */
1928  Heap->TotalFreeSize += FreeSize;
1929  }
1930  else
1931  {
1932  /* Resulting block is quite big */
1933  RtlpInsertFreeBlock(Heap, SplitBlock, FreeSize);
1934  }
1935  }
1936  }
1937 
1938  /* Reset flags of the free entry */
1939  FreeFlags = 0;
1940  if (SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY)
1941  {
1942  SegmentOffset = SplitBlock->SegmentOffset;
1943  ASSERT(SegmentOffset < HEAP_SEGMENTS);
1944  }
1945  }
1946  }
1947 
1948  /* Set last entry flag */
1949  if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
1950  InUseEntry->Flags |= HEAP_ENTRY_LAST_ENTRY;
1951 
1952  return InUseEntry;
1953 }
VOID NTAPI RtlpInsertFreeBlockHelper(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize, BOOLEAN NoFill)
Definition: heap.c:238
SIZE_T TotalFreeSize
Definition: heap.h:239
#define HEAP_SEGMENTS
Definition: heap.h:15
static VOID RtlpRemoveFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, BOOLEAN NoFill)
Definition: heap.c:422
#define HEAP_MAX_BLOCK_SIZE
Definition: heap.h:23
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define HEAP_EXTRA_FLAGS_MASK
Definition: heap.h:35
#define FALSE
Definition: types.h:117
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries
Definition: heap.h:258
VOID NTAPI RtlpInsertFreeBlock(PHEAP Heap, PHEAP_FREE_ENTRY FreeEntry, SIZE_T BlockSize)
Definition: heap.c:357
Definition: heap.h:129
struct _HEAP_ENTRY * PHEAP_ENTRY
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ASSERT(a)
Definition: mode.c:44
_In_ WDFCOLLECTION _In_ ULONG Index
#define HEAP_SETTABLE_USER_FLAGS
Definition: nt_native.h:1708
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _HEAP_FREE_ENTRY * PHEAP_FREE_ENTRY
struct _HEAP_ENTRY HEAP_ENTRY
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:319
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: heap.h:135
unsigned short USHORT
Definition: pedump.c:61
#define HEAP_ENTRY_LAST_ENTRY
Definition: heap.h:44
#define HEAP_ENTRY_EXTRA_PRESENT
Definition: heap.h:41

Referenced by RtlAllocateHeap(), and RtlpAllocateNonDedicated().

◆ RtlpValidateHeap()

BOOLEAN NTAPI RtlpValidateHeap ( PHEAP  Heap,
BOOLEAN  ForceValidation 
)

Definition at line 3513 of file heap.c.

3515 {
3516  UCHAR SegmentOffset;
3517  SIZE_T TotalFreeSize;
3518  PLIST_ENTRY ListHead, NextEntry;
3519  ULONG FreeBlocksCount, FreeListEntriesCount;
3520  ULONG HintIndex;
3521 
3522  /* Check headers */
3523  if (!RtlpValidateHeapHeaders(Heap, FALSE))
3524  return FALSE;
3525 
3526  /* Skip validation if it's not needed */
3527  if (!ForceValidation && !(Heap->Flags & HEAP_VALIDATE_ALL_ENABLED))
3528  return TRUE;
3529 
3530  /* Check free list */
3531  FreeListEntriesCount = 0;
3532  ListHead = &Heap->FreeLists;
3533  NextEntry = ListHead->Flink;
3534 
3535  while (NextEntry != ListHead)
3536  {
3537  PHEAP_FREE_ENTRY FreeEntry = CONTAINING_RECORD(NextEntry, HEAP_FREE_ENTRY, FreeList);
3538 
3539  NextEntry = NextEntry->Flink;
3540 
3541  if (NextEntry != ListHead)
3542  {
3543  PHEAP_FREE_ENTRY NextFreeEntry = CONTAINING_RECORD(NextEntry, HEAP_FREE_ENTRY, FreeList);
3544  /* Free entries must be sorted */
3545  if (FreeEntry->Size > NextFreeEntry->Size)
3546  {
3547  DPRINT1("Dedicated free entry %p of size %ld is not put in order.\n", FreeEntry, FreeEntry->Size);
3548  }
3549  }
3550 
3551  /* Check that the hint is there */
3552  if (FreeEntry->Size > Heap->DeCommitFreeBlockThreshold)
3553  {
3554  if (Heap->FreeHints[0] == NULL)
3555  {
3556  DPRINT1("No hint pointing to the non-dedicated list although there is a free entry %p of size %ld.\n",
3557  FreeEntry, FreeEntry->Size);
3558  }
3559  if (!RtlTestBit(&Heap->FreeHintBitmap, 0))
3560  {
3561  DPRINT1("Hint bit 0 is not set although there is a free entry %p of size %ld.\n",
3562  FreeEntry, FreeEntry->Size);
3563  }
3564  }
3565  else
3566  {
3567  if (Heap->FreeHints[FreeEntry->Size - 1] == NULL)
3568  {
3569  DPRINT1("No hint pointing to the dedicated list although there is a free entry %p of size %ld.\n",
3570  FreeEntry, FreeEntry->Size);
3571  }
3572  if (!RtlTestBit(&Heap->FreeHintBitmap, FreeEntry->Size - 1))
3573  {
3574  DPRINT1("Hint bit 0 is not set although there is a free entry %p of size %ld.\n",
3575  FreeEntry, FreeEntry->Size);
3576  }
3577  }
3578 
3579  /* If there is an in-use entry in a free list - that's quite a big problem */
3580  if (FreeEntry->Flags & HEAP_ENTRY_BUSY)
3581  {
3582  DPRINT1("HEAP: Free element %p is marked in-use\n", FreeEntry);
3583  return FALSE;
3584  }
3585 
3586  /* Add up to the total amount of free entries */
3587  FreeListEntriesCount++;
3588  }
3589 
3590  /* Check free list hints */
3592  {
3593  if (Heap->FreeHints[HintIndex] != NULL)
3594  {
3595  PHEAP_FREE_ENTRY FreeEntry = CONTAINING_RECORD(Heap->FreeHints[HintIndex], HEAP_FREE_ENTRY, FreeList);
3596 
3597  if (!RtlTestBit(&Heap->FreeHintBitmap, HintIndex))
3598  {
3599  DPRINT1("Hint bitmap bit at %u is not set, but there is a hint entry.\n", HintIndex);
3600  }
3601 
3602  if (HintIndex == 0)
3603  {
3604  if (FreeEntry->Size <= Heap->DeCommitFreeBlockThreshold)
3605  {
3606  DPRINT1("There is an entry %p of size %lu, smaller than the decommit threshold %lu in the non-dedicated free list hint.\n",
3607  FreeEntry, FreeEntry->Size, Heap->DeCommitFreeBlockThreshold);
3608  }
3609  }
3610  else
3611  {
3612  if (HintIndex != FreeEntry->Size - 1)
3613  {
3614  DPRINT1("There is an entry %p of size %lu at the position %u in the free entry hint array.\n",
3615  FreeEntry, FreeEntry->Size, HintIndex);
3616  }
3617 
3618  if (FreeEntry->FreeList.Blink != &Heap->FreeLists)
3619  {
3620  /* The entry right before the hint must be smaller. */
3621  PHEAP_FREE_ENTRY PreviousFreeEntry = CONTAINING_RECORD(FreeEntry->FreeList.Blink,
3623  FreeList);
3624  if (PreviousFreeEntry->Size >= FreeEntry->Size)
3625  {
3626  DPRINT1("Free entry hint %p of size %lu is larger than the entry before it %p, which is of size %lu.\n",
3627  FreeEntry, FreeEntry->Size, PreviousFreeEntry, PreviousFreeEntry->Size);
3628  }
3629  }
3630  }
3631  }
3632  else if (RtlTestBit(&Heap->FreeHintBitmap, HintIndex))
3633  {
3634  DPRINT1("Hint bitmap bit at %u is set, but there is no hint entry.\n", HintIndex);
3635  }
3636  }
3637 
3638  /* Check big allocations */
3639  ListHead = &Heap->VirtualAllocdBlocks;
3640  NextEntry = ListHead->Flink;
3641 
3642  while (ListHead != NextEntry)
3643  {
3645 
3646  /* We can only check the fill pattern */
3647  if (VirtualAllocBlock->BusyBlock.Flags & HEAP_ENTRY_FILL_PATTERN)
3648  {
3649  if (!RtlpCheckInUsePattern(&VirtualAllocBlock->BusyBlock))
3650  return FALSE;
3651  }
3652 
3653  NextEntry = NextEntry->Flink;
3654  }
3655 
3656  /* Check all segments */
3657  FreeBlocksCount = 0;
3658  TotalFreeSize = 0;
3659 
3660  for (SegmentOffset = 0; SegmentOffset < HEAP_SEGMENTS; SegmentOffset++)
3661  {
3662  PHEAP_SEGMENT Segment = Heap->Segments[SegmentOffset];
3663 
3664  /* Go to the next one if there is no segment */
3665  if (!Segment) continue;
3666 
3667  if (!RtlpValidateHeapSegment(Heap,
3668  Segment,
3669  SegmentOffset,
3670  &FreeBlocksCount,
3671  &TotalFreeSize,
3672  NULL,
3673  NULL))
3674  {
3675  return FALSE;
3676  }
3677  }
3678 
3679  if (FreeListEntriesCount != FreeBlocksCount)
3680  {
3681  DPRINT1("HEAP: Free blocks count in arena (%lu) does not match free blocks number in the free lists (%lu)\n", FreeBlocksCount, FreeListEntriesCount);
3682  return FALSE;
3683  }
3684 
3685  if (Heap->TotalFreeSize != TotalFreeSize)
3686  {
3687  DPRINT1("HEAP: Total size of free blocks in arena (%Iu) does not equal to the one in heap header (%Iu)\n", TotalFreeSize, Heap->TotalFreeSize);
3688  return FALSE;
3689  }
3690 
3691  return TRUE;
3692 }
Definition: heap.h:307
SIZE_T TotalFreeSize
Definition: heap.h:239
#define HEAP_SEGMENTS
Definition: heap.h:15
#define TRUE
Definition: types.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
LIST_ENTRY FreeLists
Definition: heap.h:259
LIST_ENTRY FreeList
Definition: heap.h:131
BOOLEAN NTAPI RtlpValidateHeapHeaders(PHEAP Heap, BOOLEAN Recalculate)
Definition: heap.c:3260
_In_ ULONG _In_ ULONG HintIndex
Definition: rtlfuncs.h:609
struct _HEAP_SEGMENT * Segments[HEAP_SEGMENTS]
Definition: heap.h:253
#define FALSE
Definition: types.h:117
PLIST_ENTRY FreeHints[ANYSIZE_ARRAY]
Definition: heap.h:268
Definition: heap.h:129
RTL_BITMAP FreeHintBitmap
Definition: heap.h:267
#define HEAP_ENTRY_BUSY
Definition: heap.h:40
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define HEAP_VALIDATE_ALL_ENABLED
Definition: rtltypes.h:166
LIST_ENTRY VirtualAllocdBlocks
Definition: heap.h:251
_Must_inspect_result_ NTSYSAPI BOOLEAN NTAPI RtlTestBit(_In_ PRTL_BITMAP BitMapHeader, _In_range_(<, BitMapHeader->SizeOfBitMap) ULONG BitNumber)
Definition: bitmap.c:434
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN NTAPI RtlpCheckInUsePattern(PHEAP_ENTRY HeapEntry)
Definition: heap.c:3230
Definition: typedefs.h:119
#define HEAP_ENTRY_FILL_PATTERN
Definition: heap.h:42
ULONG_PTR SIZE_T
Definition: typedefs.h:80
ULONG Flags
Definition: heap.h:226
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
SIZE_T DeCommitFreeBlockThreshold
Definition: heap.h:237
unsigned int ULONG
Definition: retypes.h:1
HEAP_ENTRY BusyBlock
Definition: heap.h:313
BOOLEAN NTAPI RtlpValidateHeapSegment(PHEAP Heap, PHEAP_SEGMENT Segment, UCHAR SegmentOffset, PULONG FreeEntriesCount, PSIZE_T TotalFreeSize, PSIZE_T TagEntries, PSIZE_T PseudoTagEntries)
Definition: heap.c:3326
base of all file and directory entries
Definition: entries.h:82

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

◆ RtlpValidateHeapEntry()

BOOLEAN NTAPI RtlpValidateHeapEntry ( PHEAP  Heap,
PHEAP_ENTRY  HeapEntry 
)

Definition at line 3269 of file heap.c.

3272 {
3273  BOOLEAN BigAllocation, EntryFound = FALSE;
3275  ULONG SegmentOffset;
3276 
3277  /* Perform various consistency checks of this entry */
3278  if (!HeapEntry) goto invalid_entry;
3279  if ((ULONG_PTR)HeapEntry & (HEAP_ENTRY_SIZE - 1)) goto invalid_entry;
3280  if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY)) goto