ReactOS  0.4.15-dev-5606-gf34e425
heappage.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS system libraries
4  * FILE: lib/rtl/heappage.c
5  * PURPOSE: RTL Page Heap implementation
6  * PROGRAMMERS: Copyright 2011 Aleksey Bragin
7  */
8 
9 /* Useful references:
10  http://msdn.microsoft.com/en-us/library/ms220938(VS.80).aspx
11  http://blogs.msdn.com/b/jiangyue/archive/2010/03/16/windows-heap-overrun-monitoring.aspx
12 */
13 
14 /* INCLUDES *****************************************************************/
15 
16 #include <rtl.h>
17 #include <heap.h>
18 #include <reactos/verifier.h>
19 
20 #define NDEBUG
21 #include <debug.h>
22 
23 /* TYPES **********************************************************************/
24 
25 typedef struct _DPH_BLOCK_INFORMATION
26 {
31  union
32  {
36  };
40 
41 typedef struct _DPH_HEAP_BLOCK
42 {
43  union
44  {
48  };
61 
62 typedef struct _DPH_HEAP_ROOT
63 {
68 
73 
78 
83 
87 
96 
104 
105 /* GLOBALS ********************************************************************/
106 
112 
119 
126 
127 /* Counters */
133 
134 #define DPH_RESERVE_SIZE 0x100000
135 #define DPH_POOL_SIZE 0x4000
136 #define DPH_FREE_LIST_MINIMUM 8
137 
138 /* RtlpDphBreakOptions */
139 #define DPH_BREAK_ON_RESERVE_FAIL 0x01
140 #define DPH_BREAK_ON_COMMIT_FAIL 0x02
141 #define DPH_BREAK_ON_RELEASE_FAIL 0x04
142 #define DPH_BREAK_ON_FREE_FAIL 0x08
143 #define DPH_BREAK_ON_PROTECT_FAIL 0x10
144 #define DPH_BREAK_ON_NULL_FREE 0x80
145 
146 /* RtlpDphDebugOptions */
147 #define DPH_DEBUG_INTERNAL_VALIDATE 0x01
148 #define DPH_DEBUG_VERBOSE 0x04
149 
150 /* DPH ExtraFlags */
151 #define DPH_EXTRA_LOG_STACK_TRACES 0x02
152 #define DPH_EXTRA_CHECK_UNDERRUN 0x10
153 
154 /* Fillers */
155 #define DPH_FILL 0xEEEEEEEE
156 #define DPH_FILL_START_STAMP_1 0xABCDBBBB
157 #define DPH_FILL_START_STAMP_2 0xABCDBBBA
158 #define DPH_FILL_END_STAMP_1 0xDCBABBBB
159 #define DPH_FILL_END_STAMP_2 0xDCBABBBA
160 #define DPH_FILL_SUFFIX 0xD0
161 #define DPH_FILL_INFIX 0xC0
162 
163 /* Validation info flags */
164 #define DPH_VALINFO_BAD_START_STAMP 0x01
165 #define DPH_VALINFO_BAD_END_STAMP 0x02
166 #define DPH_VALINFO_BAD_POINTER 0x04
167 #define DPH_VALINFO_BAD_PREFIX_PATTERN 0x08
168 #define DPH_VALINFO_BAD_SUFFIX_PATTERN 0x10
169 #define DPH_VALINFO_EXCEPTION 0x20
170 #define DPH_VALINFO_1 0x40
171 #define DPH_VALINFO_BAD_INFIX_PATTERN 0x80
172 #define DPH_VALINFO_ALREADY_FREED 0x100
173 #define DPH_VALINFO_CORRUPTED_AFTER_FREE 0x200
174 
175 /* Signatures */
176 #define DPH_SIGNATURE 0xFFEEDDCC
177 
178 /* Biased pointer macros */
179 #define IS_BIASED_POINTER(ptr) ((ULONG_PTR)(ptr) & 1)
180 #define POINTER_REMOVE_BIAS(ptr) ((ULONG_PTR)(ptr) & ~(ULONG_PTR)1)
181 #define POINTER_ADD_BIAS(ptr) ((ULONG_PTR)(ptr) | 1)
182 
183 
184 ULONG RtlpDphBreakOptions = 0;//0xFFFFFFFF;
186 
187 /* FUNCTIONS ******************************************************************/
188 
191 
193 RtlpDphIsNormalFreeHeapBlock(PVOID Block, PULONG ValidationInformation, BOOLEAN CheckFillers);
194 
195 VOID NTAPI
197  _In_ PDPH_HEAP_ROOT DphRoot,
199  _In_ PVOID Block,
200  _In_ ULONG ValidationInfo);
201 
204 
205 
206 VOID NTAPI
208 {
209  EXCEPTION_RECORD Exception;
210 
211  /* Initialize exception record */
212  Exception.ExceptionCode = Status;
214  Exception.ExceptionFlags = 0;
215  Exception.ExceptionRecord = NULL;
216  Exception.NumberParameters = 0;
217 
218  /* Raise the exception */
219  RtlRaiseException(&Exception);
220 }
221 
222 PVOID NTAPI
224 {
225  PHEAP NormalHeap = (PHEAP)Handle;
227 
228  if (NormalHeap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
229  {
230  if (DphHeap->Signature == DPH_SIGNATURE)
231  return DphHeap;
232  }
233 
234  DPRINT1("heap handle with incorrect signature\n");
235  DbgBreakPoint();
236  return NULL;
237 }
238 
239 PVOID NTAPI
241 {
242  return ((PUCHAR)DphHeap) - PAGE_SIZE;
243 }
244 
245 ULONG NTAPI
247 {
248  PDPH_BLOCK_INFORMATION BlockInfo;
249  BlockInfo = (PDPH_BLOCK_INFORMATION)Block - 1;
250 
251  /* Check stamps */
252  if (BlockInfo->StartStamp != DPH_FILL_START_STAMP_1 && BlockInfo->StartStamp != DPH_FILL_START_STAMP_2)
253  {
254  return 0;
255  }
256 
257  return BlockInfo->RequestedSize;
258 }
259 
260 VOID NTAPI
262 {
263  if (Flags & HEAP_NO_SERIALIZE)
264  {
265  /* More complex scenario */
266  if (!RtlTryEnterHeapLock(DphRoot->HeapCritSect, TRUE))
267  {
268  if (!DphRoot->nRemoteLockAcquired)
269  {
270  DPRINT1("multithreaded access in HEAP_NO_SERIALIZE heap\n");
271  DbgBreakPoint();
272 
273  /* Clear out the no serialize flag */
274  DphRoot->HeapFlags &= ~HEAP_NO_SERIALIZE;
275  }
276 
277  /* Enter the heap's critical section */
279  }
280  }
281  else
282  {
283  /* Just enter the heap's critical section */
285  }
286 }
287 
288 VOID NTAPI
290 {
291  /* Just leave the heap's critical section */
292  RtlLeaveHeapLock(DphRoot->HeapCritSect);
293 }
294 
295 
296 VOID NTAPI
298 {
300 
301  /* FIXME: Validate integrity, internal lists if necessary */
302 }
303 
304 VOID NTAPI
306 {
307  if (!DphRoot) return;
308 
310  {
311  /* FIXME: Validate integrity, internal lists if necessary */
312  }
313 
314  /* Release the lock */
316 }
317 
320 {
322  //PVOID *SavedBase = Base;
323  //PSIZE_T SavedSize = Size;
324 
325  /* Free the memory */
326  Status = ZwFreeVirtualMemory(Process, Base, Size, Type);
327 
328  /* Flush secure memory cache if needed and retry freeing */
329 #if 0
331  Process == NtCurrentProcess() &&
332  RtlFlushSecureMemoryCache(*SavedBase, *SavedSize))
333  {
334  Status = ZwFreeVirtualMemory(NtCurrentProcess(), SavedBase, SavedSize, Type);
335  }
336 #endif
337 
338  return Status;
339 }
340 
343 {
345  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
346  Base,
347  0,
348  &Size,
349  Type,
350  Protection);
351  DPRINT("Page heap: AllocVm (%p, %Ix, %lx) status %lx\n", Base, Size, Type, Status);
352  /* Check for failures */
353  if (!NT_SUCCESS(Status))
354  {
355  if (Type == MEM_RESERVE)
356  {
359  {
360  DPRINT1("Page heap: AllocVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
361  DbgBreakPoint();
362  return Status;
363  }
364  }
365  else
366  {
369  {
370  DPRINT1("Page heap: AllocVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
371  DbgBreakPoint();
372  return Status;
373  }
374  }
375  }
376 
377  return Status;
378 }
379 
382 {
384 
385  /* Free the memory */
387  DPRINT("Page heap: FreeVm (%p, %Ix, %lx) status %lx\n", Base, Size, Type, Status);
388  /* Log/report failures */
389  if (!NT_SUCCESS(Status))
390  {
391  if (Type == MEM_RELEASE)
392  {
395  {
396  DPRINT1("Page heap: FreeVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
397  DbgBreakPoint();
398  return Status;
399  }
400  }
401  else
402  {
405  {
406  DPRINT1("Page heap: FreeVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Type, Status);
407  DbgBreakPoint();
408  return Status;
409  }
410  }
411  }
412 
413  return Status;
414 }
415 
418 {
420  ULONG OldProtection;
421 
422  /* Change protection */
423  Status = ZwProtectVirtualMemory(NtCurrentProcess(), &Base, &Size, Protection, &OldProtection);
424 
425  /* Log/report failures */
426  if (!NT_SUCCESS(Status))
427  {
430  {
431  DPRINT1("Page heap: ProtectVm (%p, %Ix, %lx) failed with %lx\n", Base, Size, Protection, Status);
432  DbgBreakPoint();
433  return Status;
434  }
435  }
436 
437  return Status;
438 }
439 
442 {
443  PDPH_BLOCK_INFORMATION BlockInfo;
444  PUCHAR FillPtr;
445 
446  /* Get pointer to the block info structure */
447  BlockInfo = (PDPH_BLOCK_INFORMATION)UserAllocation - 1;
448 
449  /* Set up basic fields */
450  BlockInfo->Heap = DphRoot;
451  BlockInfo->ActualSize = UserSize;
452  BlockInfo->RequestedSize = Size;
453  BlockInfo->StartStamp = DPH_FILL_START_STAMP_1;
454  BlockInfo->EndStamp = DPH_FILL_END_STAMP_1;
455 
456  /* Fill with a pattern */
457  FillPtr = (PUCHAR)UserAllocation + Size;
458  RtlFillMemory(FillPtr, ROUND_UP(FillPtr, PAGE_SIZE) - (ULONG_PTR)FillPtr, DPH_FILL_SUFFIX);
459 
460  /* FIXME: Check if logging stack traces is turned on */
461  //if (DphRoot->ExtraFlags &
462 
463  return TRUE;
464 }
465 
466 VOID NTAPI
468 {
469  BOOLEAN NewElement;
470  PVOID AddressUserData;
471 
472  DPRINT("RtlpDphPlaceOnBusyList(%p %p)\n", DphRoot, DphNode);
473 
474  /* Add it to the AVL busy nodes table */
475  DphRoot->NodeToAllocate = DphNode;
476  AddressUserData = RtlInsertElementGenericTableAvl(&DphRoot->BusyNodesTable,
477  &DphNode->pUserAllocation,
478  sizeof(ULONG_PTR),
479  &NewElement);
480 
481  ASSERT(AddressUserData == &DphNode->pUserAllocation);
482  ASSERT(NewElement == TRUE);
483 
484  /* Update heap counters */
485  DphRoot->nBusyAllocations++;
488 }
489 
490 VOID NTAPI
492 {
493  DPRINT("RtlpDphPlaceOnFreeList(%p %p)\n", DphRoot, Node);
494 
495  /* Node is being added to the tail of the list */
496  Node->pNextAlloc = NULL;
497 
498  /* Add it to the tail of the linked list */
499  if (DphRoot->pFreeAllocationListTail)
501  else
502  DphRoot->pFreeAllocationListHead = Node;
503  DphRoot->pFreeAllocationListTail = Node;
504 
505  /* Update byte counts taking in account this new node */
506  DphRoot->nFreeAllocations++;
507  DphRoot->nFreeAllocationBytesCommitted += Node->nVirtualBlockSize;
508 }
509 
510 VOID NTAPI
512 {
513  DPRINT("RtlpDphPlaceOnPoolList(%p %p)\n", DphRoot, Node);
514 
515  /* Node is being added to the tail of the list */
516  Node->pNextAlloc = NULL;
517 
518  /* Add it to the tail of the linked list */
519  if (DphRoot->pNodePoolListTail)
520  DphRoot->pNodePoolListTail->pNextAlloc = Node;
521  else
522  DphRoot->pNodePoolListHead = Node;
523  DphRoot->pNodePoolListTail = Node;
524 
525  /* Update byte counts taking in account this new node */
526  DphRoot->nNodePools++;
527  DphRoot->nNodePoolBytes += Node->nVirtualBlockSize;
528 }
529 
530 VOID NTAPI
532 {
533  DPRINT("RtlpDphPlaceOnVirtualList(%p %p)\n", DphRoot, Node);
534 
535  /* Add it to the head of the virtual list */
536  Node->pNextAlloc = DphRoot->pVirtualStorageListHead;
537  if (!DphRoot->pVirtualStorageListHead)
538  DphRoot->pVirtualStorageListTail = Node;
539  DphRoot->pVirtualStorageListHead = Node;
540 
541  /* Update byte counts taking in account this new node */
542  DphRoot->nVirtualStorageRanges++;
543  DphRoot->nVirtualStorageBytes += Node->nVirtualBlockSize;
544 }
545 
548 {
550  PDPH_HEAP_BLOCK Next;
551 
552  DPRINT("RtlpDphTakeNodeFromUnusedList(%p), ret %p\n", DphRoot, Node);
553 
554  /* Take the first entry */
555  if (!Node) return NULL;
556 
557  /* Remove that entry (Node) from the list */
558  Next = Node->pNextAlloc;
559  if (DphRoot->pUnusedNodeListHead == Node) DphRoot->pUnusedNodeListHead = Next;
560  if (DphRoot->pUnusedNodeListTail == Node) DphRoot->pUnusedNodeListTail = NULL;
561 
562  /* Decrease amount of unused nodes */
563  DphRoot->nUnusedNodes--;
564 
565  return Node;
566 }
567 
568 VOID NTAPI
571 {
572  DPRINT("RtlpDphReturnNodeToUnusedList(%p, %p)\n", DphRoot, Node);
573 
574  /* Add it back to the head of the unused list */
575  Node->pNextAlloc = DphRoot->pUnusedNodeListHead;
576  if (!DphRoot->pUnusedNodeListHead)
577  DphRoot->pUnusedNodeListTail = Node;
578  DphRoot->pUnusedNodeListHead = Node;
579 
580  /* Increase amount of unused nodes */
581  DphRoot->nUnusedNodes++;
582 }
583 
584 VOID NTAPI
587 {
588  /* Make sure Adjacency list pointers are biased */
589  //ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Flink));
590  //ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Blink));
591 
592  DPRINT("RtlpDphRemoveFromAvailableList(%p %p)\n", DphRoot, Node);
593 
594  /* Check if it is in the list */
595 #if 0
596  {
597  PLIST_ENTRY CurEntry;
598  PDPH_HEAP_BLOCK NodeEntry;
599  BOOLEAN Found = FALSE;
600 
601  /* Find where to put this node according to its virtual address */
602  CurEntry = DphRoot->AvailableAllocationHead.Flink;
603 
604  while (CurEntry != &DphRoot->AvailableAllocationHead)
605  {
606  NodeEntry = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
607 
608  if (NodeEntry == Node)
609  {
610  Found = TRUE;
611  break;
612  }
613 
614  CurEntry = CurEntry->Flink;
615  }
616 
617  if (!Found)
618  {
619  DPRINT1("Trying to remove non-existing in availlist node!\n");
620  DbgBreakPoint();
621  }
622  }
623 #endif
624 
625  /* Remove it from the list */
626  RemoveEntryList(&Node->AvailableEntry);
627 
628  /* Decrease heap counters */
629  DphRoot->nAvailableAllocations--;
630  DphRoot->nAvailableAllocationBytesCommitted -= Node->nVirtualBlockSize;
631 
632  /* Remove bias from the AdjacencyEntry pointer */
633  Node->AdjacencyEntry.Flink = (PLIST_ENTRY)POINTER_REMOVE_BIAS(Node->AdjacencyEntry.Flink);
634  Node->AdjacencyEntry.Blink = (PLIST_ENTRY)POINTER_REMOVE_BIAS(Node->AdjacencyEntry.Blink);
635 }
636 
637 VOID NTAPI
640 {
641  BOOLEAN ElementPresent;
642 
643  DPRINT("RtlpDphRemoveFromBusyList(%p %p)\n", DphRoot, Node);
644 
645  /* Delete it from busy nodes table */
646  ElementPresent = RtlDeleteElementGenericTableAvl(&DphRoot->BusyNodesTable, &Node->pUserAllocation);
647  ASSERT(ElementPresent == TRUE);
648 
649  /* Update counters */
650  DphRoot->nBusyAllocations--;
651  DphRoot->nBusyAllocationBytesCommitted -= Node->nVirtualBlockSize;
652  DphRoot->nBusyAllocationBytesAccessible -= Node->nVirtualAccessSize;
653 }
654 
655 VOID NTAPI
658  PDPH_HEAP_BLOCK Prev)
659 {
660  PDPH_HEAP_BLOCK Next;
661 
662  DPRINT("RtlpDphRemoveFromFreeList(%p %p %p)\n", DphRoot, Node, Prev);
663 
664  /* Detach it from the list */
665  Next = Node->pNextAlloc;
666  if (DphRoot->pFreeAllocationListHead == Node)
667  DphRoot->pFreeAllocationListHead = Next;
668  if (DphRoot->pFreeAllocationListTail == Node)
669  DphRoot->pFreeAllocationListTail = Prev;
670  if (Prev) Prev->pNextAlloc = Next;
671 
672  /* Decrease heap counters */
673  DphRoot->nFreeAllocations--;
674  DphRoot->nFreeAllocationBytesCommitted -= Node->nVirtualBlockSize;
675 
676  Node->StackTrace = NULL;
677 }
678 
679 VOID NTAPI
682 {
683  PDPH_HEAP_BLOCK NodeEntry, PrevNode = NULL, NextNode;
684  PLIST_ENTRY AvailListHead;
685  PLIST_ENTRY CurEntry;
686 
687  DPRINT("RtlpDphCoalesceNodeIntoAvailable(%p %p)\n", DphRoot, Node);
688 
689  /* Update heap counters */
690  DphRoot->nAvailableAllocationBytesCommitted += Node->nVirtualBlockSize;
691  DphRoot->nAvailableAllocations++;
692 
693  /* Find where to put this node according to its virtual address */
694  AvailListHead = &DphRoot->AvailableAllocationHead;
695 
696  /* Find a point where to insert an available node */
697  CurEntry = AvailListHead->Flink;
698 
699  while (CurEntry != AvailListHead)
700  {
701  NodeEntry = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
702  if (NodeEntry->pVirtualBlock >= Node->pVirtualBlock)
703  {
704  PrevNode = NodeEntry;
705  break;
706  }
707  CurEntry = CurEntry->Flink;
708  }
709 
710  if (!PrevNode)
711  {
712  /* That means either this list is empty, or we should add to the head of it */
713  InsertHeadList(AvailListHead, &Node->AvailableEntry);
714  }
715  else
716  {
717  /* Check the previous node and merge if possible */
718  if (PrevNode->pVirtualBlock + PrevNode->nVirtualBlockSize == Node->pVirtualBlock)
719  {
720  /* Check they actually belong to the same virtual memory block */
722  MEMORY_BASIC_INFORMATION MemoryBasicInfo;
723 
726  Node->pVirtualBlock,
728  &MemoryBasicInfo,
729  sizeof(MemoryBasicInfo),
730  NULL);
731 
732  /* There is no way this can fail, we committed this memory! */
734 
735  if ((PUCHAR)MemoryBasicInfo.AllocationBase <= PrevNode->pVirtualBlock)
736  {
737  /* They are adjacent, and from the same VM region. - merge! */
738  PrevNode->nVirtualBlockSize += Node->nVirtualBlockSize;
740  DphRoot->nAvailableAllocations--;
741 
742  Node = PrevNode;
743  }
744  else
745  {
746  /* Insert after PrevNode */
747  InsertTailList(&PrevNode->AvailableEntry, &Node->AvailableEntry);
748  }
749  }
750  else
751  {
752  /* Insert after PrevNode */
753  InsertTailList(&PrevNode->AvailableEntry, &Node->AvailableEntry);
754  }
755 
756  /* Now check the next entry after our one */
757  if (Node->AvailableEntry.Flink != AvailListHead)
758  {
759  NextNode = CONTAINING_RECORD(Node->AvailableEntry.Flink, DPH_HEAP_BLOCK, AvailableEntry);
760  /* Node is not at the tail of the list, check if it's adjacent */
761  if (Node->pVirtualBlock + Node->nVirtualBlockSize == NextNode->pVirtualBlock)
762  {
763  /* Check they actually belong to the same virtual memory block */
765  MEMORY_BASIC_INFORMATION MemoryBasicInfo;
766 
769  NextNode->pVirtualBlock,
771  &MemoryBasicInfo,
772  sizeof(MemoryBasicInfo),
773  NULL);
774 
775  /* There is no way this can fail, we committed this memory! */
777 
778  if ((PUCHAR)MemoryBasicInfo.AllocationBase <= Node->pVirtualBlock)
779  {
780  /* They are adjacent - merge! */
781  Node->nVirtualBlockSize += NextNode->nVirtualBlockSize;
782 
783  /* Remove next entry from the list and put it into unused entries list */
784  RemoveEntryList(&NextNode->AvailableEntry);
785  RtlpDphReturnNodeToUnusedList(DphRoot, NextNode);
786  DphRoot->nAvailableAllocations--;
787  }
788  }
789  }
790  }
791 }
792 
793 VOID NTAPI
795  ULONG LeaveOnFreeList)
796 {
798  SIZE_T FreeAllocations = DphRoot->nFreeAllocations;
799 
800  /* Make sure requested size is not too big */
801  ASSERT(FreeAllocations >= LeaveOnFreeList);
802 
803  DPRINT("RtlpDphCoalesceFreeIntoAvailable(%p %lu)\n", DphRoot, LeaveOnFreeList);
804 
805  while (Node)
806  {
807  FreeAllocations--;
808  if (FreeAllocations < LeaveOnFreeList) break;
809 
810  /* Get the next pointer, because it may be changed after following two calls */
811  Next = Node->pNextAlloc;
812 
813  /* Remove it from the free list */
815 
816  /* And put into the available */
818 
819  /* Go to the next node */
820  Node = Next;
821  }
822 }
823 
824 VOID NTAPI
825 RtlpDphAddNewPool(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK NodeBlock, PVOID Virtual, SIZE_T Size, BOOLEAN PlaceOnPool)
826 {
827  PDPH_HEAP_BLOCK DphNode, DphStartNode;
828  ULONG NodeCount, i;
829 
830  //NodeCount = (Size >> 6) - 1;
831  NodeCount = (ULONG)(Size / sizeof(DPH_HEAP_BLOCK));
832  DphStartNode = Virtual;
833 
834  /* Set pNextAlloc for all blocks */
835  for (DphNode = Virtual, i=NodeCount-1; i > 0; i--)
836  {
837  DphNode->pNextAlloc = DphNode + 1;
838  DphNode = DphNode->pNextAlloc;
839  }
840 
841  /* and the last one */
842  DphNode->pNextAlloc = NULL;
843 
844  /* Add it to the tail of unused node list */
845  if (DphRoot->pUnusedNodeListTail)
846  DphRoot->pUnusedNodeListTail->pNextAlloc = DphStartNode;
847  else
848  DphRoot->pUnusedNodeListHead = DphStartNode;
849 
850  DphRoot->pUnusedNodeListTail = DphNode;
851 
852  /* Increase counters */
853  DphRoot->nUnusedNodes += NodeCount;
854 
855  /* Check if we need to place it on the pool list */
856  if (PlaceOnPool)
857  {
858  /* Get a node from the unused list */
859  DphNode = RtlpDphTakeNodeFromUnusedList(DphRoot);
860  ASSERT(DphNode);
861 
862  /* Set its virtual block values */
863  DphNode->pVirtualBlock = Virtual;
864  DphNode->nVirtualBlockSize = Size;
865 
866  /* Place it on the pool list */
867  RtlpDphPlaceOnPoolList(DphRoot, DphNode);
868  }
869 }
870 
873  SIZE_T Size)
874 {
875  PLIST_ENTRY CurEntry;
876  PDPH_HEAP_BLOCK Node, NodeFound = NULL;
877 
878  CurEntry = DphRoot->AvailableAllocationHead.Flink;
879 
880  while (CurEntry != &DphRoot->AvailableAllocationHead)
881  {
882  /* Get the current available node */
883  Node = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
884 
885  /* Check its size */
886  if (Node->nVirtualBlockSize >= Size)
887  {
888  NodeFound = Node;
889  break;
890  }
891 
892  /* Move to the next available entry */
893  CurEntry = CurEntry->Flink;
894  }
895 
896  /* Make sure Adjacency list pointers are biased */
897  //ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Flink));
898  //ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Blink));
899 
900  return NodeFound;
901 }
902 
905  SIZE_T Size,
906  BOOLEAN Grow)
907 {
909  ULONG NewSize;
910 
911  /* Find an available best fitting node */
913 
914  /* If that didn't work, try to search a smaller one in the loop */
915  while (!Node)
916  {
917  /* Break if the free list becomes too small */
918  if (DphRoot->nFreeAllocations <= DPH_FREE_LIST_MINIMUM) break;
919 
920  /* Calculate a new free list size */
921  NewSize = DphRoot->nFreeAllocations >> 2;
923 
924  /* Coalesce free into available */
926 
927  /* Try to find an available best fitting node again */
929  }
930 
931  /* If Node is NULL, then we could fix the situation only by
932  growing the available VM size */
933  if (!Node && Grow)
934  {
935  /* Grow VM size, if it fails - return failure directly */
936  if (!RtlpDphGrowVirtual(DphRoot, Size)) return NULL;
937 
938  /* Try to find an available best fitting node again */
940 
941  if (!Node)
942  {
943  /* Do the last attempt: coalesce all free into available (if Size fits there) */
945  {
946  /* Coalesce free into available */
948 
949  /* Try to find an available best fitting node again */
951  }
952  }
953  }
954 
955  /* Return node we found */
956  return Node;
957 }
958 
961  PVOID pUserMem)
962 {
964  PVOID Ptr;
965 
966  /* Lookup busy block in AVL */
967  Ptr = RtlLookupElementGenericTableAvl(&DphRoot->BusyNodesTable, &pUserMem);
968  if (!Ptr) return NULL;
969 
970  /* Restore pointer to the heap block */
971  Node = CONTAINING_RECORD(Ptr, DPH_HEAP_BLOCK, pUserAllocation);
972  ASSERT(Node->pUserAllocation == pUserMem);
973  return Node;
974 }
975 
978 {
979  ULONG Protection;
980  PVOID Base;
981 
982  if (DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN)
983  {
984  Base = VirtualBlock + PAGE_SIZE;
985  }
986  else
987  {
988  Base = VirtualBlock;
989  }
990 
991  // FIXME: It should be different, but for now it's fine
992  Protection = PAGE_READWRITE;
993 
994  return RtlpDphProtectVm(Base, UserSize, Protection);
995 }
996 
999 {
1000  ASSERT((Node->nVirtualAccessSize + PAGE_SIZE) <= Node->nVirtualBlockSize);
1001 
1002  // FIXME: Bring stuff here
1003  if (DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN)
1004  {
1005  }
1006  else
1007  {
1008  }
1009 
1010  return STATUS_SUCCESS;
1011 }
1012 
1015 {
1017  NTSTATUS Status;
1018  SIZE_T Size = DPH_POOL_SIZE, SizeVirtual;
1019  PVOID Ptr = NULL;
1020 
1021  /* Check for the easy case */
1022  if (DphRoot->pUnusedNodeListHead)
1023  {
1024  /* Just take a node from this list */
1026  ASSERT(Node);
1027  return Node;
1028  }
1029 
1030  /* There is a need to make free space */
1032 
1033  if (!DphRoot->pUnusedNodeListHead && !Node)
1034  {
1035  /* Retry with a smaller request */
1036  Size = PAGE_SIZE;
1038  }
1039 
1040  if (!DphRoot->pUnusedNodeListHead)
1041  {
1042  if (Node)
1043  {
1045  Ptr = Node->pVirtualBlock;
1046  SizeVirtual = Node->nVirtualBlockSize;
1047  }
1048  else
1049  {
1050  /* No free space, need to alloc a new VM block */
1051  Size = DPH_POOL_SIZE;
1052  SizeVirtual = DPH_RESERVE_SIZE;
1054 
1055  if (!NT_SUCCESS(Status))
1056  {
1057  /* Retry with a smaller size */
1058  SizeVirtual = 0x10000;
1060  if (!NT_SUCCESS(Status)) return NULL;
1061  }
1062  }
1063 
1064  /* VM is allocated at this point, set protection */
1066  if (!NT_SUCCESS(Status))
1067  {
1068  if (Node)
1069  {
1071  }
1072  else
1073  {
1074  //RtlpDphFreeVm();
1075  ASSERT(FALSE);
1076  }
1077 
1078  return NULL;
1079  }
1080 
1081  /* Zero the memory */
1082  if (Node) RtlZeroMemory(Ptr, Size);
1083 
1084  /* Add a new pool based on this VM */
1085  RtlpDphAddNewPool(DphRoot, Node, Ptr, Size, TRUE);
1086 
1087  if (Node)
1088  {
1089  if (Node->nVirtualBlockSize > Size)
1090  {
1091  Node->pVirtualBlock += Size;
1092  Node->nVirtualBlockSize -= Size;
1093 
1095  }
1096  else
1097  {
1099  }
1100  }
1101  else
1102  {
1103  /* The new VM block was just allocated a few code lines ago,
1104  so initialize it */
1106  Node->pVirtualBlock = Ptr;
1107  Node->nVirtualBlockSize = SizeVirtual;
1108  RtlpDphPlaceOnVirtualList(DphRoot, Node);
1109 
1111  Node->pVirtualBlock = (PUCHAR)Ptr + Size;
1112  Node->nVirtualBlockSize = SizeVirtual - Size;
1113  RtlpDphPlaceOnVirtualList(DphRoot, Node);
1114 
1115  /* Coalesce them into available list */
1117  }
1118  }
1119 
1120  return RtlpDphTakeNodeFromUnusedList(DphRoot);
1121 }
1122 
1123 BOOLEAN NTAPI
1125  SIZE_T Size)
1126 {
1127  PDPH_HEAP_BLOCK Node, AvailableNode;
1128  PVOID Base = NULL;
1129  SIZE_T VirtualSize;
1130  NTSTATUS Status;
1131 
1132  /* Start with allocating a couple of nodes */
1133  Node = RtlpDphAllocateNode(DphRoot);
1134  if (!Node) return FALSE;
1135 
1136  AvailableNode = RtlpDphAllocateNode(DphRoot);
1137  if (!AvailableNode)
1138  {
1139  /* Free the allocated node and return failure */
1141  return FALSE;
1142  }
1143 
1144  /* Calculate size of VM to allocate by rounding it up */
1145  Size = ROUND_UP(Size, 0xFFFF);
1146  VirtualSize = Size;
1147  if (Size < DPH_RESERVE_SIZE)
1148  VirtualSize = DPH_RESERVE_SIZE;
1149 
1150  /* Allocate the virtual memory */
1151  // FIXME: Shouldn't it be MEM_RESERVE with later committing?
1153  if (!NT_SUCCESS(Status))
1154  {
1155  /* Retry again with a smaller size */
1156  VirtualSize = Size;
1158  if (!NT_SUCCESS(Status))
1159  {
1160  /* Free the allocated node and return failure */
1162  RtlpDphReturnNodeToUnusedList(DphRoot, AvailableNode);
1163  return FALSE;
1164  }
1165  }
1166 
1167  /* Set up our two nodes describing this VM */
1168  Node->pVirtualBlock = Base;
1169  Node->nVirtualBlockSize = VirtualSize;
1170  AvailableNode->pVirtualBlock = Base;
1171  AvailableNode->nVirtualBlockSize = VirtualSize;
1172 
1173  /* Add them to virtual and available lists respectively */
1174  RtlpDphPlaceOnVirtualList(DphRoot, Node);
1175  RtlpDphCoalesceNodeIntoAvailable(DphRoot, AvailableNode);
1176 
1177  /* Return success */
1178  return TRUE;
1179 }
1180 
1182 NTAPI
1186 {
1187  ULONG_PTR FirstBlock, SecondBlock;
1188 
1189  FirstBlock = *((ULONG_PTR *)FirstStruct);
1190  SecondBlock = *((ULONG_PTR *)SecondStruct);
1191 
1192  if (FirstBlock < SecondBlock)
1193  return GenericLessThan;
1194  else if (FirstBlock > SecondBlock)
1195  return GenericGreaterThan;
1196 
1197  return GenericEqual;
1198 }
1199 
1200 PVOID
1201 NTAPI
1203  IN CLONG ByteSize)
1204 {
1205  PDPH_HEAP_BLOCK pBlock;
1206  PDPH_HEAP_ROOT DphRoot;
1207 
1208  /* This mega-assert comes from a text search over Windows 2003 checked binary of ntdll.dll */
1209  ASSERT((ULONG_PTR)(((PRTL_BALANCED_LINKS)0)+1) + sizeof(PUCHAR) == ByteSize);
1210 
1211  /* Get pointer to the containing heap root record */
1212  DphRoot = CONTAINING_RECORD(Table, DPH_HEAP_ROOT, BusyNodesTable);
1213  pBlock = DphRoot->NodeToAllocate;
1214 
1215  DphRoot->NodeToAllocate = NULL;
1216  ASSERT(pBlock);
1217 
1218  return &(pBlock->TableLinks);
1219 }
1220 
1221 VOID
1222 NTAPI
1224  IN PVOID Buffer)
1225 {
1226  /* Nothing */
1227 }
1228 
1231 {
1232  NTSTATUS Status;
1233 
1235  if (!NT_SUCCESS(Status))
1236  {
1237  // TODO: Log this error!
1238  DPRINT1("Failure initializing delayed free queue critical section\n");
1239  return Status;
1240  }
1241 
1242  /* Initialize lists */
1245 
1246  /* Reset counters */
1249 
1250  return Status;
1251 }
1252 
1253 VOID NTAPI
1255  PHEAP NormalHeap)
1256 {
1257  PLIST_ENTRY Current, Next;
1258  PDPH_BLOCK_INFORMATION BlockInfo;
1259  ULONG ValidationInfo;
1260 
1261  /* The original routine seems to use a temporary SList to put blocks to be freed,
1262  then it releases the lock and frees the blocks. But let's make it simple for now */
1263 
1264  /* Acquire the delayed free queue lock */
1266 
1267  /* Traverse the list */
1268  Current = RtlpDphDelayedFreeQueue.Flink;
1269  while (Current != &RtlpDphDelayedFreeQueue)
1270  {
1271  /* Get the next entry pointer */
1272  Next = Current->Flink;
1273 
1274  BlockInfo = CONTAINING_RECORD(Current, DPH_BLOCK_INFORMATION, FreeQueue);
1275 
1276  /* Check if it belongs to the same heap */
1277  if (BlockInfo->Heap == DphRoot)
1278  {
1279  /* Remove it from the list */
1280  RemoveEntryList(Current);
1281 
1282  /* Reset its heap to NULL */
1283  BlockInfo->Heap = NULL;
1284 
1285  if (!RtlpDphIsNormalFreeHeapBlock(BlockInfo + 1, &ValidationInfo, TRUE))
1286  {
1287  RtlpDphReportCorruptedBlock(DphRoot, 10, BlockInfo + 1, ValidationInfo);
1288  }
1289 
1290  /* Decrement counters */
1293 
1294  /* Free the normal heap */
1295  RtlFreeHeap(NormalHeap, 0, BlockInfo);
1296  }
1297 
1298  /* Move to the next one */
1299  Current = Next;
1300  }
1301 
1302  /* Release the delayed free queue lock */
1304 }
1305 
1308 {
1309  UNIMPLEMENTED;
1310  return STATUS_SUCCESS;
1311 }
1312 
1313 VOID NTAPI
1315 {
1316  UNIMPLEMENTED;
1317 }
1318 
1319 VOID NTAPI
1321 {
1322  UNIMPLEMENTED;
1323 }
1324 
1325 VOID NTAPI
1327  _In_ PDPH_HEAP_ROOT DphRoot,
1329  _In_ PVOID Block,
1330  _In_ ULONG ValidationInfo)
1331 {
1333  DPH_BLOCK_INFORMATION SafeInfo = {0};
1334 
1335  DPRINT1("Corrupted heap block %p\n", Block);
1336 
1337  _SEH2_TRY
1338  {
1339  PDPH_BLOCK_INFORMATION BlockInfo = (PDPH_BLOCK_INFORMATION)Block - 1;
1340  RtlCopyMemory(&SafeInfo, BlockInfo, sizeof(SafeInfo));
1341  }
1343  {
1344  DPRINT1("ERROR: Could not read DPH_BLOCK_INFORMATION\n");
1345  RtlZeroMemory(&SafeInfo, sizeof(SafeInfo));
1346  }
1347  _SEH2_END;
1348 
1349  if (ValidationInfo & DPH_VALINFO_CORRUPTED_AFTER_FREE)
1350  {
1352  APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_AFTER_FREE, "block corrupted after having been freed",
1353  RtlpDphHeapFromPointer(DphRoot), "Heap handle", Block, "Heap block", (PVOID)Size, "Block size", 0, "");
1354  }
1355 
1356  if (ValidationInfo & DPH_VALINFO_ALREADY_FREED)
1357  {
1359  APPLICATION_VERIFIER_DOUBLE_FREE, "block already freed", RtlpDphHeapFromPointer(DphRoot), "Heap handle",
1360  Block, "Heap block", Size, "Block size", 0, "");
1361  }
1362 
1363  if (ValidationInfo & DPH_VALINFO_BAD_INFIX_PATTERN)
1364  {
1366  APPLICATION_VERIFIER_CORRUPTED_INFIX_PATTERN, "corrupted infix pattern for freed block",
1367  RtlpDphHeapFromPointer(DphRoot), "Heap handle", Block, "Heap block", Size, "Block size", 0, "");
1368  }
1369 
1370  if (ValidationInfo & DPH_VALINFO_BAD_POINTER)
1371  {
1373  APPLICATION_VERIFIER_CORRUPT_HEAP_POINTER, "corrupted heap pointer or using wrong heap",
1374  RtlpDphHeapFromPointer(DphRoot), "Heap handle used", Block, "Heap block", Size, "Block size",
1375  SafeInfo.Heap, "Actual heap handle");
1376  }
1377 
1378  if (ValidationInfo & DPH_VALINFO_BAD_SUFFIX_PATTERN)
1379  {
1381  APPLICATION_VERIFIER_CORRUPTED_SUFFIX_PATTERN, "corrupted suffix pattern", RtlpDphHeapFromPointer(DphRoot),
1382  "Heap handle used", Block, "Heap block", Size, "Block size", 0, "");
1383  }
1384 
1385  if (ValidationInfo & DPH_VALINFO_BAD_PREFIX_PATTERN)
1386  {
1388  APPLICATION_VERIFIER_CORRUPTED_PREFIX_PATTERN, "corrupted prefix pattern", RtlpDphHeapFromPointer(DphRoot),
1389  "Heap handle used", Block, "Heap block", Size, "Block size", 0, "");
1390  }
1391 
1392  if (ValidationInfo & DPH_VALINFO_BAD_START_STAMP)
1393  {
1395  APPLICATION_VERIFIER_CORRUPTED_START_STAMP, "corrupted start stamp", RtlpDphHeapFromPointer(DphRoot),
1396  "Heap handle used", Block, "Heap block", Size, "Block size", (PVOID)(ULONG_PTR)SafeInfo.StartStamp,
1397  "Corrupted start stamp");
1398  }
1399 
1400  if (ValidationInfo & DPH_VALINFO_BAD_END_STAMP)
1401  {
1403  APPLICATION_VERIFIER_CORRUPTED_END_STAMP, "corrupted end stamp", RtlpDphHeapFromPointer(DphRoot),
1404  "Heap handle used", Block, "Heap block", Size, "Block size", (PVOID)(ULONG_PTR)SafeInfo.EndStamp,
1405  "Corrupted end stamp");
1406  }
1407 
1408  if (ValidationInfo & DPH_VALINFO_EXCEPTION)
1409  {
1411  APPLICATION_VERIFIER_EXCEPTION_WHILE_VERIFYING_BLOCK_HEADER, "exception raised while verifying block",
1412  RtlpDphHeapFromPointer(DphRoot), "Heap handle used", Block, "Heap block", Size, "Block size", 0, "");
1413  }
1414 }
1415 
1416 BOOLEAN NTAPI
1418  PVOID Block,
1419  PULONG ValidationInformation,
1420  BOOLEAN CheckFillers)
1421 {
1422  PDPH_BLOCK_INFORMATION BlockInfo;
1423  BOOLEAN SomethingWrong = FALSE;
1424  PUCHAR Byte, Start, End;
1425 
1426  ASSERT(ValidationInformation != NULL);
1427  *ValidationInformation = 0;
1428 
1429  // _SEH2_TRY {
1430  BlockInfo = (PDPH_BLOCK_INFORMATION)Block - 1;
1431 
1432  /* Check stamps */
1433  if (BlockInfo->StartStamp != DPH_FILL_START_STAMP_1)
1434  {
1435  *ValidationInformation |= DPH_VALINFO_BAD_START_STAMP;
1436  SomethingWrong = TRUE;
1437 
1438  /* Check if it has an alloc/free mismatch */
1439  if (BlockInfo->StartStamp == DPH_FILL_START_STAMP_2)
1440  {
1441  /* Notify respectively */
1442  *ValidationInformation = 0x101;
1443  }
1444  }
1445 
1446  if (BlockInfo->EndStamp != DPH_FILL_END_STAMP_1)
1447  {
1448  *ValidationInformation |= DPH_VALINFO_BAD_END_STAMP;
1449  SomethingWrong = TRUE;
1450  }
1451 
1452  /* Check root heap pointer */
1453  if (BlockInfo->Heap != DphRoot)
1454  {
1455  *ValidationInformation |= DPH_VALINFO_BAD_POINTER;
1456  SomethingWrong = TRUE;
1457  }
1458 
1459  /* Check other fillers if requested */
1460  if (CheckFillers)
1461  {
1462  /* Check space after the block */
1463  Start = (PUCHAR)Block + BlockInfo->RequestedSize;
1464  End = (PUCHAR)ROUND_UP(Start, PAGE_SIZE);
1465  for (Byte = Start; Byte < End; Byte++)
1466  {
1467  if (*Byte != DPH_FILL_SUFFIX)
1468  {
1469  *ValidationInformation |= DPH_VALINFO_BAD_SUFFIX_PATTERN;
1470  SomethingWrong = TRUE;
1471  break;
1472  }
1473  }
1474  }
1475 
1476  return (SomethingWrong == FALSE);
1477 }
1478 
1479 BOOLEAN NTAPI
1481  PULONG ValidationInformation,
1482  BOOLEAN CheckFillers)
1483 {
1484  ASSERT(ValidationInformation != NULL);
1485 
1486  UNIMPLEMENTED;
1487  *ValidationInformation = 0;
1488  return TRUE;
1489 }
1490 
1493 {
1494  NTSTATUS Status;
1495  PTEB Teb = NtCurrentTeb();
1496 
1497  /* Initialize the DPH heap list and its critical section */
1500  if (!NT_SUCCESS(Status))
1501  {
1502  ASSERT(FALSE);
1503  return Status;
1504  }
1505 
1506  /* Initialize delayed-free queue */
1508  if (!NT_SUCCESS(Status)) return Status;
1509 
1510  /* Initialize the target dlls string */
1513 
1514  /* Per-process DPH init is done */
1516 
1517  DPRINT1("Page heap: pid 0x%p: page heap enabled with flags 0x%X.\n",
1519 
1520  return Status;
1521 }
1522 
1523 BOOLEAN NTAPI
1525  SIZE_T Size)
1526 {
1527  //UNIMPLEMENTED;
1528  /* Always use page heap for now */
1529  return TRUE;
1530 }
1531 
1532 HANDLE NTAPI
1534  PVOID Addr,
1535  SIZE_T TotalSize,
1537  PVOID Lock,
1539 {
1540  PVOID Base = NULL;
1541  PHEAP HeapPtr;
1542  PDPH_HEAP_ROOT DphRoot;
1543  PDPH_HEAP_BLOCK DphNode;
1544  ULONG MemSize;
1545  NTSTATUS Status;
1546  LARGE_INTEGER PerfCounter;
1547 
1548  /* Check for a DPH bypass flag */
1549  if ((ULONG_PTR)Parameters == -1) return NULL;
1550 
1551  /* Make sure no user-allocated stuff was provided */
1552  if (Addr || Lock) return NULL;
1553 
1554  /* Allocate minimum amount of virtual memory */
1555  MemSize = DPH_RESERVE_SIZE;
1557  if (!NT_SUCCESS(Status))
1558  {
1559  ASSERT(FALSE);
1560  return NULL;
1561  }
1562 
1563  /* Set protection */
1565  if (!NT_SUCCESS(Status))
1566  {
1567  //RtlpDphFreeVm(Base, 0, 0, 0);
1568  ASSERT(FALSE);
1569  return NULL;
1570  }
1571 
1572  /* Start preparing the 1st page. Fill it with the default filler */
1574 
1575  /* Set flags in the "HEAP" structure */
1576  HeapPtr = (PHEAP)Base;
1577  HeapPtr->Flags = Flags | HEAP_FLAG_PAGE_ALLOCS;
1578  HeapPtr->ForceFlags = Flags | HEAP_FLAG_PAGE_ALLOCS;
1579 
1580  /* Set 1st page to read only now */
1582  if (!NT_SUCCESS(Status))
1583  {
1584  ASSERT(FALSE);
1585  return NULL;
1586  }
1587 
1588  /* 2nd page is the real DPH root block */
1589  DphRoot = (PDPH_HEAP_ROOT)((PCHAR)Base + PAGE_SIZE);
1590 
1591  /* Initialize the DPH root */
1592  DphRoot->Signature = DPH_SIGNATURE;
1593  DphRoot->HeapFlags = Flags;
1594  DphRoot->HeapCritSect = (PHEAP_LOCK)((PCHAR)DphRoot + DPH_POOL_SIZE);
1595  DphRoot->ExtraFlags = RtlpDphGlobalFlags;
1596 
1597  ZwQueryPerformanceCounter(&PerfCounter, NULL);
1598  DphRoot->Seed = PerfCounter.LowPart;
1599 
1602 
1603  /* Create a normal heap for this paged heap */
1604  DphRoot->NormalHeap = RtlCreateHeap(Flags, NULL, TotalSize, CommitSize, NULL, (PRTL_HEAP_PARAMETERS)-1);
1605  if (!DphRoot->NormalHeap)
1606  {
1607  ASSERT(FALSE);
1608  return NULL;
1609  }
1610 
1611  /* 3rd page: a pool for DPH allocations */
1612  RtlpDphAddNewPool(DphRoot, NULL, DphRoot + 1, DPH_POOL_SIZE - sizeof(DPH_HEAP_ROOT), FALSE);
1613 
1614  /* Allocate internal heap blocks. For the root */
1615  DphNode = RtlpDphAllocateNode(DphRoot);
1616  ASSERT(DphNode != NULL);
1617  DphNode->pVirtualBlock = (PUCHAR)DphRoot;
1618  DphNode->nVirtualBlockSize = DPH_POOL_SIZE;
1619  RtlpDphPlaceOnPoolList(DphRoot, DphNode);
1620 
1621  /* For the memory we allocated as a whole */
1622  DphNode = RtlpDphAllocateNode(DphRoot);
1623  ASSERT(DphNode != NULL);
1624  DphNode->pVirtualBlock = Base;
1625  DphNode->nVirtualBlockSize = MemSize;
1626  RtlpDphPlaceOnVirtualList(DphRoot, DphNode);
1627 
1628  /* For the remaining part */
1629  DphNode = RtlpDphAllocateNode(DphRoot);
1630  ASSERT(DphNode != NULL);
1631  DphNode->pVirtualBlock = (PUCHAR)Base + 2*PAGE_SIZE + DPH_POOL_SIZE;
1632  DphNode->nVirtualBlockSize = MemSize - (2*PAGE_SIZE + DPH_POOL_SIZE);
1633  RtlpDphCoalesceNodeIntoAvailable(DphRoot, DphNode);
1634 
1635  //DphRoot->CreateStackTrace = RtlpDphLogStackTrace(1);
1636 
1637  /* Initialize AVL-based busy nodes table */
1642  NULL);
1643 
1644  /* Initialize per-process startup info */
1646 
1647  /* Acquire the heap list lock */
1649 
1650  /* Insert this heap to the tail of the global list */
1652 
1653  /* Note we increased the size of the list */
1655 
1656  /* Release the heap list lock */
1658 
1660  {
1661  DPRINT1("Page heap: process 0x%p created heap @ %p (%p, flags 0x%X)\n",
1663  DphRoot->NormalHeap, DphRoot->ExtraFlags);
1664  }
1665 
1666  /* Perform internal validation if required */
1669 
1670  return (PUCHAR)DphRoot - PAGE_SIZE;
1671 }
1672 
1673 PVOID NTAPI
1675 {
1676  PDPH_HEAP_ROOT DphRoot;
1677  PVOID Ptr;
1678  PDPH_HEAP_BLOCK Node, Next;
1679  PHEAP NormalHeap;
1680  ULONG Value;
1681 
1682  /* Check if it's not a process heap */
1683  if (HeapPtr == RtlGetProcessHeap())
1684  {
1685  DbgBreakPoint();
1686  return NULL;
1687  }
1688 
1689  /* Get pointer to the heap root */
1690  DphRoot = RtlpDphPointerFromHandle(HeapPtr);
1691  if (!DphRoot) return NULL;
1692 
1693  RtlpDphPreProcessing(DphRoot, DphRoot->HeapFlags);
1694 
1695  /* Get the pointer to the normal heap */
1696  NormalHeap = DphRoot->NormalHeap;
1697 
1698  /* Free the delayed-free blocks */
1699  RtlpDphFreeDelayedBlocksFromHeap(DphRoot, NormalHeap);
1700 
1701  /* Go through the busy blocks */
1703 
1704  while (Ptr)
1705  {
1706  Node = CONTAINING_RECORD(Ptr, DPH_HEAP_BLOCK, pUserAllocation);
1707  if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
1708  {
1709  if (!RtlpDphIsPageHeapBlock(DphRoot, Node->pUserAllocation, &Value, TRUE))
1710  {
1711  RtlpDphReportCorruptedBlock(DphRoot, 3, Node->pUserAllocation, Value);
1712  }
1713  }
1714 
1715  /* FIXME: Call AV notification */
1716  //AVrfInternalHeapFreeNotification();
1717 
1718  /* Go to the next node */
1720  }
1721 
1722  /* Acquire the global heap list lock */
1724 
1725  /* Remove the entry and decrement the global counter */
1726  RemoveEntryList(&DphRoot->NextHeap);
1728 
1729  /* Release the global heap list lock */
1731 
1732  /* Leave and delete this heap's critical section */
1733  RtlLeaveHeapLock(DphRoot->HeapCritSect);
1734  RtlDeleteHeapLock(DphRoot->HeapCritSect);
1735 
1736  /* Now go through all virtual list nodes and release the VM */
1737  Node = DphRoot->pVirtualStorageListHead;
1738  while (Node)
1739  {
1740  Next = Node->pNextAlloc;
1741  /* Release the memory without checking result */
1742  RtlpDphFreeVm(Node->pVirtualBlock, 0, MEM_RELEASE);
1743  Node = Next;
1744  }
1745 
1746  /* Destroy the normal heap */
1747  RtlDestroyHeap(NormalHeap);
1748 
1749  /* Report success */
1751  DPRINT1("Page heap: process 0x%p destroyed heap @ %p (%p)\n",
1752  NtCurrentTeb()->ClientId.UniqueProcess, HeapPtr, NormalHeap);
1753 
1754  return NULL;
1755 }
1756 
1757 PVOID NTAPI
1759  IN ULONG Flags,
1760  IN SIZE_T Size)
1761 {
1762  PDPH_HEAP_ROOT DphRoot;
1763  PDPH_HEAP_BLOCK AvailableNode, BusyNode;
1764  BOOLEAN Biased = FALSE;
1765  ULONG AllocateSize, AccessSize;
1766  NTSTATUS Status;
1767  SIZE_T UserActualSize;
1768  PVOID Ptr;
1769 
1770  /* Check requested size */
1771  if (Size > 0x7FF00000)
1772  {
1773  DPRINT1("extreme size request\n");
1774 
1775  /* Generate an exception if needed */
1777 
1778  return NULL;
1779  }
1780 
1781  /* Unbias the pointer if necessary */
1782  if (IS_BIASED_POINTER(HeapPtr))
1783  {
1784  HeapPtr = (PVOID)POINTER_REMOVE_BIAS(HeapPtr);
1785  Biased = TRUE;
1786  }
1787 
1788  /* Get a pointer to the heap root */
1789  DphRoot = RtlpDphPointerFromHandle(HeapPtr);
1790  if (!DphRoot) return NULL;
1791 
1792  /* Acquire the heap lock */
1793  RtlpDphPreProcessing(DphRoot, Flags);
1794 
1795  /* Perform internal validation if specified by flags */
1797  {
1799  }
1800 
1801  /* Add heap flags */
1802  Flags |= DphRoot->HeapFlags;
1803 
1804  if (!Biased && !RtlpDphShouldAllocateInPageHeap(DphRoot, Size))
1805  {
1806  /* Perform allocation from a normal heap */
1807  ASSERT(FALSE);
1808  }
1809 
1810  /* Perform heap integrity check if specified by flags */
1812  {
1813  RtlpDphVerifyIntegrity(DphRoot);
1814  }
1815 
1816  /* Calculate sizes */
1817  AccessSize = ROUND_UP(Size + sizeof(DPH_BLOCK_INFORMATION), PAGE_SIZE);
1818  AllocateSize = AccessSize + PAGE_SIZE;
1819 
1820  // FIXME: Move RtlpDphAllocateNode(DphRoot) to this place
1821  AvailableNode = RtlpDphFindAvailableMemory(DphRoot, AllocateSize, TRUE);
1822  if (!AvailableNode)
1823  {
1824  DPRINT1("Page heap: Unable to allocate virtual memory\n");
1825  DbgBreakPoint();
1826 
1827  /* Release the lock */
1828  RtlpDphPostProcessing(DphRoot);
1829 
1830  return NULL;
1831  }
1832  ASSERT(AvailableNode->nVirtualBlockSize >= AllocateSize);
1833 
1834  /* Set protection */
1836  AvailableNode->pVirtualBlock,
1837  AccessSize);
1838  if (!NT_SUCCESS(Status))
1839  {
1840  ASSERT(FALSE);
1841  }
1842 
1843  /* Save available node pointer */
1844  Ptr = AvailableNode->pVirtualBlock;
1845 
1846  /* Check node's size */
1847  if (AvailableNode->nVirtualBlockSize > AllocateSize)
1848  {
1849  /* The block contains too much free space, reduce it */
1850  AvailableNode->pVirtualBlock += AllocateSize;
1851  AvailableNode->nVirtualBlockSize -= AllocateSize;
1852  DphRoot->nAvailableAllocationBytesCommitted -= AllocateSize;
1853 
1854  /* Allocate a new node which will be our busy node */
1855  BusyNode = RtlpDphAllocateNode(DphRoot);
1856  ASSERT(BusyNode != NULL);
1857  BusyNode->pVirtualBlock = Ptr;
1858  BusyNode->nVirtualBlockSize = AllocateSize;
1859  }
1860  else
1861  {
1862  /* The block's size fits exactly */
1863  RtlpDphRemoveFromAvailableList(DphRoot, AvailableNode);
1864  BusyNode = AvailableNode;
1865  }
1866 
1867  /* Calculate actual user size */
1868  if (DphRoot->HeapFlags & HEAP_NO_ALIGNMENT)
1869  UserActualSize = Size;
1870  else
1871  UserActualSize = ROUND_UP(Size, 8);
1872 
1873  /* Set up the block */
1874  BusyNode->nVirtualAccessSize = AccessSize;
1875  BusyNode->nUserActualSize = UserActualSize;
1876  BusyNode->nUserRequestedSize = Size;
1877 
1878  if (DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN)
1879  BusyNode->pUserAllocation = BusyNode->pVirtualBlock + PAGE_SIZE;
1880  else
1881  BusyNode->pUserAllocation = BusyNode->pVirtualBlock + BusyNode->nVirtualAccessSize - UserActualSize;
1882 
1883  BusyNode->UserValue = NULL;
1885 
1886  // FIXME: Don't forget about stack traces if such flag was set
1887  BusyNode->StackTrace = NULL;
1888 
1889  /* Place it on busy list */
1890  RtlpDphPlaceOnBusyList(DphRoot, BusyNode);
1891 
1892  /* Zero or patter-fill memory depending on flags */
1893  if (Flags & HEAP_ZERO_MEMORY)
1894  RtlZeroMemory(BusyNode->pUserAllocation, Size);
1895  else
1897 
1898  /* Write DPH info */
1899  if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
1900  {
1902  BusyNode->pUserAllocation,
1903  Size,
1904  AccessSize);
1905  }
1906 
1907  /* Finally allocation is done, perform validation again if required */
1909  {
1911  }
1912 
1913  /* Release the lock */
1914  RtlpDphPostProcessing(DphRoot);
1915 
1916  DPRINT("Allocated user block pointer: %p\n", BusyNode->pUserAllocation);
1917 
1918  /* Return pointer to user allocation */
1919  return BusyNode->pUserAllocation;
1920 }
1921 
1922 BOOLEAN NTAPI
1924  ULONG Flags,
1925  PVOID Ptr)
1926 {
1927  PDPH_HEAP_ROOT DphRoot;
1929  ULONG ValidationInfo;
1931 
1932  /* Check for a NULL pointer freeing */
1933  if (!Ptr)
1934  {
1936  {
1937  DPRINT1("Page heap: freeing a null pointer\n");
1938  DbgBreakPoint();
1939  }
1940  return TRUE;
1941  }
1942 
1943  /* Get a pointer to the heap root */
1944  DphRoot = RtlpDphPointerFromHandle(HeapPtr);
1945  if (!DphRoot) return FALSE;
1946 
1947  /* Acquire the heap lock */
1948  RtlpDphPreProcessing(DphRoot, Flags);
1949 
1950  /* Perform internal validation if specified by flags */
1953 
1954  /* Add heap flags */
1955  Flags |= DphRoot->HeapFlags;
1956 
1957  /* Find busy memory */
1958  Node = RtlpDphFindBusyMemory(DphRoot, Ptr);
1959 
1960  if (!Node)
1961  {
1962  /* This block was not found in page heap, try a normal heap instead */
1963  //RtlpDphNormalHeapFree();
1964  ASSERT(FALSE);
1965  }
1966 
1967  if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
1968  {
1969  /* Check and report corrupted block */
1970  if (!RtlpDphIsPageHeapBlock(DphRoot, Ptr, &ValidationInfo, TRUE))
1971  {
1972  RtlpDphReportCorruptedBlock(DphRoot, 1, Ptr, ValidationInfo);
1973  }
1974 
1975  // FIXME: Should go inside RtlpDphSetProtectionAfterUse
1976  if (Node->nVirtualAccessSize != 0)
1977  {
1978  /* Set stamps */
1979  Info = (PDPH_BLOCK_INFORMATION)Node->pUserAllocation - 1;
1980  Info->StartStamp = DPH_FILL_START_STAMP_2;
1981  Info->EndStamp = DPH_FILL_END_STAMP_2;
1982 
1983  RtlpDphProtectVm(Node->pVirtualBlock, Node->nVirtualAccessSize, PAGE_NOACCESS);
1984  }
1985  }
1986  else
1987  {
1988  // FIXME: Should go inside RtlpDphSetProtectionAfterUse
1989  if (Node->nVirtualAccessSize != 0)
1990  RtlpDphProtectVm(Node->pVirtualBlock + PAGE_SIZE, Node->nVirtualAccessSize, PAGE_NOACCESS);
1991  }
1992 
1993  /* Set new protection */
1994  //RtlpDphSetProtectionAfterUse(DphRoot, Node);
1995 
1996  /* Remove it from the list of busy nodes */
1997  RtlpDphRemoveFromBusyList(DphRoot, Node);
1998 
1999  /* And put it into the list of free nodes */
2000  RtlpDphPlaceOnFreeList(DphRoot, Node);
2001 
2002  //if (DphRoot->ExtraFlags & DPH_EXTRA_LOG_STACK_TRACES)
2003  // Node->StackTrace = RtlpDphLogStackTrace(3);
2004  //else
2005  Node->StackTrace = NULL;
2006 
2007  /* Leave the heap lock */
2008  RtlpDphPostProcessing(DphRoot);
2009 
2010  /* Return success */
2011  return TRUE;
2012 }
2013 
2014 PVOID NTAPI
2016  ULONG Flags,
2017  PVOID Ptr,
2018  SIZE_T Size)
2019 {
2020  PDPH_HEAP_ROOT DphRoot;
2021  PDPH_HEAP_BLOCK Node = NULL, AllocatedNode;
2022  BOOLEAN Biased = FALSE, UseNormalHeap = FALSE, OldBlockPageHeap = TRUE;
2023  ULONG ValidationInfo;
2024  SIZE_T DataSize;
2025  PVOID NewAlloc = NULL;
2026 
2027  /* Check requested size */
2028  if (Size > 0x7FF00000)
2029  {
2030  DPRINT1("extreme size request\n");
2031 
2032  /* Generate an exception if needed */
2034 
2035  return NULL;
2036  }
2037 
2038  /* Unbias the pointer if necessary */
2039  if (IS_BIASED_POINTER(HeapPtr))
2040  {
2041  HeapPtr = (PVOID)POINTER_REMOVE_BIAS(HeapPtr);
2042  Biased = TRUE;
2043  }
2044 
2045  /* Get a pointer to the heap root */
2046  DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2047  if (!DphRoot) return NULL;
2048 
2049  /* Acquire the heap lock */
2050  RtlpDphPreProcessing(DphRoot, Flags);
2051 
2052  /* Perform internal validation if specified by flags */
2054  {
2056  }
2057 
2058  /* Add heap flags */
2059  Flags |= DphRoot->HeapFlags;
2060 
2061  /* Exit with NULL right away if inplace is specified */
2063  {
2064  /* Release the lock */
2065  RtlpDphPostProcessing(DphRoot);
2066 
2067  /* Generate an exception if needed */
2069 
2070  return NULL;
2071  }
2072 
2073  /* Try to get node of the allocated block */
2074  AllocatedNode = RtlpDphFindBusyMemory(DphRoot, Ptr);
2075 
2076  if (!AllocatedNode)
2077  {
2078  /* This block was not found in page heap, try a normal heap instead */
2079  //RtlpDphNormalHeapFree();
2080  ASSERT(FALSE);
2081  OldBlockPageHeap = FALSE;
2082  }
2083 
2084  /* Check the block */
2085  if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
2086  {
2087  if (!RtlpDphIsPageHeapBlock(DphRoot, AllocatedNode->pUserAllocation, &ValidationInfo, TRUE))
2088  {
2089  RtlpDphReportCorruptedBlock(DphRoot, 3, AllocatedNode->pUserAllocation, ValidationInfo);
2090  }
2091  }
2092 
2093  /* Remove old one from the busy list */
2094  RtlpDphRemoveFromBusyList(DphRoot, AllocatedNode);
2095 
2096  if (!Biased && !RtlpDphShouldAllocateInPageHeap(DphRoot, Size))
2097  {
2098  // FIXME: Use normal heap
2099  ASSERT(FALSE);
2100  UseNormalHeap = TRUE;
2101  }
2102  else
2103  {
2104  /* Now do a trick: bias the pointer and call our allocate routine */
2105  NewAlloc = RtlpPageHeapAllocate((PVOID)POINTER_ADD_BIAS(HeapPtr), Flags, Size);
2106  }
2107 
2108  if (!NewAlloc)
2109  {
2110  /* New allocation failed, put the block back (if it was found in page heap) */
2111  RtlpDphPlaceOnBusyList(DphRoot, AllocatedNode);
2112 
2113  /* Release the lock */
2114  RtlpDphPostProcessing(DphRoot);
2115 
2116  /* Perform validation again if required */
2118  {
2120  }
2121 
2122  /* Generate an exception if needed */
2124 
2125  return NULL;
2126  }
2127 
2128  /* Copy contents of the old block */
2129  if (AllocatedNode->nUserRequestedSize > Size)
2130  DataSize = Size;
2131  else
2132  DataSize = AllocatedNode->nUserRequestedSize;
2133 
2134  if (DataSize != 0) RtlCopyMemory(NewAlloc, Ptr, DataSize);
2135 
2136  /* Copy user flags and values */
2137  if (!UseNormalHeap)
2138  {
2139  /* Get the node of the new block */
2140  Node = RtlpDphFindBusyMemory(DphRoot, NewAlloc);
2141  ASSERT(Node != NULL);
2142 
2143  /* Set its values/flags */
2144  Node->UserValue = AllocatedNode->UserValue;
2146  Node->UserFlags = Flags & HEAP_SETTABLE_USER_FLAGS;
2147  else
2148  Node->UserFlags = AllocatedNode->UserFlags;
2149  }
2150 
2151  if (!OldBlockPageHeap)
2152  {
2153  /* Weird scenario, investigate */
2154  ASSERT(FALSE);
2155  }
2156 
2157  /* Mark the old block as no access */
2158  if (AllocatedNode->nVirtualAccessSize != 0)
2159  {
2160  RtlpDphProtectVm(AllocatedNode->pVirtualBlock, AllocatedNode->nVirtualAccessSize, PAGE_NOACCESS);
2161  }
2162 
2163  /* And place it on the free list */
2164  RtlpDphPlaceOnFreeList(DphRoot, AllocatedNode);
2165 
2166  // FIXME: Capture stack traces if needed
2167  AllocatedNode->StackTrace = NULL;
2168 
2169  /* Finally allocation is done, perform validation again if required */
2171  {
2173  }
2174 
2175  /* Release the lock */
2176  RtlpDphPostProcessing(DphRoot);
2177 
2178  DPRINT("Allocated new user block pointer: %p\n", NewAlloc);
2179 
2180  /* Return pointer to user allocation */
2181  return NewAlloc;
2182 }
2183 
2184 BOOLEAN NTAPI
2186  ULONG Flags,
2188  PVOID *UserValue,
2189  PULONG UserFlags)
2190 {
2191  PDPH_HEAP_ROOT DphRoot;
2193 
2194  /* Get a pointer to the heap root */
2195  DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2196  if (!DphRoot) return FALSE;
2197 
2198  /* Add heap flags */
2199  Flags |= DphRoot->HeapFlags;
2200 
2201  /* Acquire the heap lock */
2202  RtlpDphPreProcessing(DphRoot, Flags);
2203 
2204  /* Find busy memory */
2206 
2207  if (!Node)
2208  {
2209  /* This block was not found in page heap, try a normal heap instead */
2210  //RtlpDphNormalHeapGetUserInfo();
2211  ASSERT(FALSE);
2212  return FALSE;
2213  }
2214 
2215  /* Get user values and flags and store them in user provided pointers */
2216  if (UserValue) *UserValue = Node->UserValue;
2217  if (UserFlags) *UserFlags = Node->UserFlags;
2218 
2219  /* Leave the heap lock */
2220  RtlpDphPostProcessing(DphRoot);
2221 
2222  /* Return success */
2223  return TRUE;
2224 }
2225 
2226 BOOLEAN NTAPI
2228  ULONG Flags,
2230  PVOID UserValue)
2231 {
2232  PDPH_HEAP_ROOT DphRoot;
2234 
2235  /* Get a pointer to the heap root */
2236  DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2237  if (!DphRoot) return FALSE;
2238 
2239  /* Add heap flags */
2240  Flags |= DphRoot->HeapFlags;
2241 
2242  /* Acquire the heap lock */
2243  RtlpDphPreProcessing(DphRoot, Flags);
2244 
2245  /* Find busy memory */
2247 
2248  if (!Node)
2249  {
2250  /* This block was not found in page heap, try a normal heap instead */
2251  //RtlpDphNormalHeapSetUserValue();
2252  ASSERT(FALSE);
2253  return FALSE;
2254  }
2255 
2256  /* Get user values and flags and store them in user provided pointers */
2257  Node->UserValue = UserValue;
2258 
2259  /* Leave the heap lock */
2260  RtlpDphPostProcessing(DphRoot);
2261 
2262  /* Return success */
2263  return TRUE;
2264 }
2265 
2266 BOOLEAN
2267 NTAPI
2269  ULONG Flags,
2271  ULONG UserFlagsReset,
2272  ULONG UserFlagsSet)
2273 {
2274  PDPH_HEAP_ROOT DphRoot;
2276 
2277  /* Get a pointer to the heap root */
2278  DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2279  if (!DphRoot) return FALSE;
2280 
2281  /* Add heap flags */
2282  Flags |= DphRoot->HeapFlags;
2283 
2284  /* Acquire the heap lock */
2285  RtlpDphPreProcessing(DphRoot, Flags);
2286 
2287  /* Find busy memory */
2289 
2290  if (!Node)
2291  {
2292  /* This block was not found in page heap, try a normal heap instead */
2293  //RtlpDphNormalHeapSetUserFlags();
2294  ASSERT(FALSE);
2295  return FALSE;
2296  }
2297 
2298  /* Get user values and flags and store them in user provided pointers */
2299  Node->UserFlags &= ~(UserFlagsReset);
2300  Node->UserFlags |= UserFlagsSet;
2301 
2302  /* Leave the heap lock */
2303  RtlpDphPostProcessing(DphRoot);
2304 
2305  /* Return success */
2306  return TRUE;
2307 }
2308 
2309 SIZE_T NTAPI
2311  ULONG Flags,
2313 {
2314  PDPH_HEAP_ROOT DphRoot;
2316  SIZE_T Size;
2317 
2318  /* Get a pointer to the heap root */
2319  DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2320  if (!DphRoot) return -1;
2321 
2322  /* Add heap flags */
2323  Flags |= DphRoot->HeapFlags;
2324 
2325  /* Acquire the heap lock */
2326  RtlpDphPreProcessing(DphRoot, Flags);
2327 
2328  /* Find busy memory */
2330 
2331  if (!Node)
2332  {
2333  /* This block was not found in page heap, try a normal heap instead */
2334  //RtlpDphNormalHeapSize();
2335  ASSERT(FALSE);
2336  return -1;
2337  }
2338 
2339  /* Get heap block size */
2340  Size = Node->nUserRequestedSize;
2341 
2342  /* Leave the heap lock */
2343  RtlpDphPostProcessing(DphRoot);
2344 
2345  /* Return user requested size */
2346  return Size;
2347 }
2348 
2349 BOOLEAN
2350 NTAPI
2352  ULONG Flags,
2354 {
2355  PDPH_HEAP_ROOT DphRoot;
2357  BOOLEAN Valid = FALSE;
2358 
2359  /* Get a pointer to the heap root */
2360  DphRoot = RtlpDphPointerFromHandle(HeapHandle);
2361  if (!DphRoot) return -1;
2362 
2363  /* Add heap flags */
2364  Flags |= DphRoot->HeapFlags;
2365 
2366  /* Acquire the heap lock */
2367  RtlpDphPreProcessing(DphRoot, Flags);
2368 
2369  /* Find busy memory */
2370  if (BaseAddress)
2372 
2373  if (!Node)
2374  {
2375  /* This block was not found in page heap, or the request is to validate all normal heap */
2376  Valid = RtlpDphNormalHeapValidate(DphRoot, Flags, BaseAddress);
2377  }
2378 
2379  /* Leave the heap lock */
2380  RtlpDphPostProcessing(DphRoot);
2381 
2382  /* Return result of a normal heap validation */
2383  if (BaseAddress && !Node)
2384  return Valid;
2385 
2386  /* Otherwise return our own result */
2387  if (!BaseAddress || Node) Valid = TRUE;
2388 
2389  return Valid;
2390 }
2391 
2392 BOOLEAN
2393 NTAPI
2395  ULONG Flags,
2397 {
2399  if (!BaseAddress)
2400  {
2401  /* Validate all normal heap */
2402  return RtlValidateHeap(DphRoot->NormalHeap, Flags, NULL);
2403  }
2404 
2405  // FIXME: Check is this a normal heap block
2406  /*if (!RtlpDphIsNormalHeapBlock(DphRoot, BaseAddress, &ValidationInfo))
2407  {
2408  }*/
2409 
2410  return RtlValidateHeap(DphRoot->NormalHeap, Flags, BlockInfo);
2411 }
2412 
2413 BOOLEAN
2414 NTAPI
2416 {
2417  PDPH_HEAP_ROOT DphRoot;
2418 
2419  /* Get pointer to the heap root */
2420  DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2421  if (!DphRoot) return FALSE;
2422 
2423  RtlpDphEnterCriticalSection(DphRoot, DphRoot->HeapFlags);
2424  return TRUE;
2425 }
2426 
2427 BOOLEAN
2428 NTAPI
2430 {
2431  PDPH_HEAP_ROOT DphRoot;
2432 
2433  /* Get pointer to the heap root */
2434  DphRoot = RtlpDphPointerFromHandle(HeapPtr);
2435  if (!DphRoot) return FALSE;
2436 
2437  RtlpDphLeaveCriticalSection(DphRoot);
2438  return TRUE;
2439 }
2440 
2441 /* EOF */
#define DPH_BREAK_ON_FREE_FAIL
Definition: heappage.c:142
struct _LIST_ENTRY * PLIST_ENTRY
_SEH2_TRY
Definition: create.c:4226
#define DPH_DEBUG_VERBOSE
Definition: heappage.c:148
signed char * PCHAR
Definition: retypes.h:7
NTSYSAPI NTSTATUS NTAPI ZwQueryPerformanceCounter(_Out_ PLARGE_INTEGER Counter, _Out_opt_ PLARGE_INTEGER Frequency)
#define APPLICATION_VERIFIER_CORRUPTED_SUFFIX_PATTERN
Definition: verifier.h:95
NTSTATUS NTAPI RtlpDphProcessStartupInitialization(VOID)
Definition: heappage.c:1492
struct _DPH_HEAP_BLOCK DPH_HEAP_BLOCK
#define DPH_FILL_INFIX
Definition: heappage.c:161
#define IN
Definition: typedefs.h:39
PVOID UserValue
Definition: heappage.c:55
LIST_ENTRY AvailableAllocationHead
Definition: heappage.c:84
#define DPH_VALINFO_EXCEPTION
Definition: heappage.c:169
struct _DPH_HEAP_ROOT * PDPH_HEAP_ROOT
BOOLEAN NTAPI RtlpDphIsNormalFreeHeapBlock(PVOID Block, PULONG ValidationInformation, BOOLEAN CheckFillers)
Definition: heappage.c:1480
ASMGENDATA Table[]
Definition: genincdata.c:61
PHEAP_LOCK RtlpDphPageHeapListLock
Definition: heappage.c:116
SIZE_T RtlpDphMemoryUsedByDelayedFreeBlocks
Definition: heappage.c:124
LONG RtlpDphFreeFails
Definition: heappage.c:131
PDPH_HEAP_BLOCK pFreeAllocationListHead
Definition: heappage.c:79
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
SIZE_T NTAPI RtlpPageHeapSize(HANDLE HeapHandle, ULONG Flags, PVOID BaseAddress)
Definition: heappage.c:2310
SLIST_HEADER RtlpDphDelayedTemporaryPushList
Definition: heappage.c:123
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:863
Definition: ntbasedef.h:628
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
PHEAP_LOCK RtlpDphDelayedFreeQueueLock
Definition: heappage.c:121
NTSTATUS NTAPI RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:108
#define DPH_VALINFO_ALREADY_FREED
Definition: heappage.c:172
VOID NTAPI RtlpDphPlaceOnVirtualList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:531
#define TRUE
Definition: types.h:120
VOID NTAPI RtlpDphAddNewPool(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK NodeBlock, PVOID Virtual, SIZE_T Size, BOOLEAN PlaceOnPool)
Definition: heappage.c:825
#define ZwCurrentProcess()
#define DPH_BREAK_ON_COMMIT_FAIL
Definition: heappage.c:140
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
HEAP_LOCK _RtlpDphPageHeapListLock
Definition: heappage.c:115
#define IS_BIASED_POINTER(ptr)
Definition: heappage.c:179
NTSYSAPI BOOLEAN NTAPI RtlDeleteElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
VOID NTAPI RtlpDphReportCorruptedBlock(_In_ PDPH_HEAP_ROOT DphRoot, _In_ ULONG Reserved, _In_ PVOID Block, _In_ ULONG ValidationInfo)
Definition: heappage.c:1326
ULONG UserFlags
Definition: heappage.c:56
WCHAR RtlpDphTargetDlls[512]
Definition: heappage.c:111
unsigned char * PUCHAR
Definition: retypes.h:3
#define DPH_VALINFO_BAD_PREFIX_PATTERN
Definition: heappage.c:167
#define APPLICATION_VERIFIER_CORRUPTED_START_STAMP
Definition: verifier.h:96
BOOLEAN NTAPI RtlpDphShouldAllocateInPageHeap(PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
Definition: heappage.c:1524
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
BOOLEAN NTAPI RtlpPageHeapLock(HANDLE HeapPtr)
Definition: heappage.c:2415
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
VOID NTAPI RtlpDphPostProcessing(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:305
BOOLEAN NTAPI RtlpPageHeapFree(HANDLE HeapPtr, ULONG Flags, PVOID Ptr)
Definition: heappage.c:1923
NTSTATUS NTAPI RtlpDphProtectVm(PVOID Base, SIZE_T Size, ULONG Protection)
Definition: heappage.c:417
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2427
#define DPH_RESERVE_SIZE
Definition: heappage.c:134
VOID NTAPI RtlpDphRemoveFromFreeList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node, PDPH_HEAP_BLOCK Prev)
Definition: heappage.c:656
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
PDPH_HEAP_BLOCK pVirtualStorageListTail
Definition: heappage.c:70
BOOLEAN NTAPI RtlpDphNormalHeapValidate(PDPH_HEAP_ROOT DphRoot, ULONG Flags, PVOID BaseAddress)
Definition: heappage.c:2394
#define DPH_VALINFO_BAD_END_STAMP
Definition: heappage.c:165
NTSTATUS NTAPI RtlpDphSetProtectionBeforeUse(PDPH_HEAP_ROOT DphRoot, PUCHAR VirtualBlock, ULONG UserSize)
Definition: heappage.c:977
LIST_ENTRY FreeQueue
Definition: heappage.c:33
PVOID NormalHeap
Definition: heappage.c:100
#define POINTER_REMOVE_BIAS(ptr)
Definition: heappage.c:180
#define DPH_BREAK_ON_RELEASE_FAIL
Definition: heappage.c:141
struct _DPH_HEAP_ROOT DPH_HEAP_ROOT
_SEH2_END
Definition: create.c:4400
#define InsertTailList(ListHead, Entry)
NTSYSAPI VOID NTAPI RtlRaiseException(_In_ PEXCEPTION_RECORD ExceptionRecord)
BOOLEAN NTAPI RtlpPageHeapGetUserInfo(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID *UserValue, PULONG UserFlags)
Definition: heappage.c:2185
HANDLE UniqueProcess
Definition: compat.h:825
#define MEM_COMMIT
Definition: nt_native.h:1313
#define DPH_BREAK_ON_PROTECT_FAIL
Definition: heappage.c:143
LIST_ENTRY AdjacencyEntry
Definition: heappage.c:58
ULONG RtlpDphGlobalFlags
Definition: heappage.c:108
LIST_ENTRY RtlpDphPageHeapList
Definition: heappage.c:113
NTSTATUS NTAPI RtlpDphSetProtectionAfterUse(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:998
#define DPH_FILL_START_STAMP_1
Definition: heappage.c:156
PVOID ExceptionAddress
Definition: compat.h:211
LONG RtlpDphAllocFails
Definition: heappage.c:129
PVOID FirstThread
Definition: heappage.c:102
struct _HEAP_LOCK * PHEAP_LOCK
ULONG RtlpPageHeapSizeRangeStart
Definition: heappage.c:109
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define DPH_FILL_END_STAMP_2
Definition: heappage.c:159
CLIENT_ID ClientId
Definition: compat.h:839
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:683
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
DWORD ExceptionCode
Definition: compat.h:208
BOOLEAN NTAPI RtlpPageHeapUnlock(HANDLE HeapPtr)
Definition: heappage.c:2429
PHEAP_LOCK HeapCritSect
Definition: heappage.c:66
ULONG CLONG
Definition: umtypes.h:126
ULONG nRemoteLockAcquired
Definition: heappage.c:67
#define POINTER_ADD_BIAS(ptr)
Definition: heappage.c:181
PDPH_HEAP_BLOCK NTAPI RtlpDphSearchAvailableMemoryListForBestFit(PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
Definition: heappage.c:872
PVOID NTAPI RtlpDphAllocateNodeForTable(IN PRTL_AVL_TABLE Table, IN CLONG ByteSize)
Definition: heappage.c:1202
long __cdecl _InterlockedIncrement(_Interlocked_operand_ long volatile *_Addend)
PDPH_HEAP_BLOCK pVirtualStorageListHead
Definition: heappage.c:69
VOID NTAPI RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:680
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
VOID NTAPI RtlpDphRemoveFromBusyList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:638
VOID NTAPI DbgBreakPoint(VOID)
BOOLEAN NTAPI RtlpPageHeapSetUserValue(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, PVOID UserValue)
Definition: heappage.c:2227
PDPH_HEAP_BLOCK NTAPI RtlpDphFindBusyMemory(PDPH_HEAP_ROOT DphRoot, PVOID pUserMem)
Definition: heappage.c:960
long LONG
Definition: pedump.c:60
#define DPH_VALINFO_BAD_SUFFIX_PATTERN
Definition: heappage.c:168
union node Node
Definition: types.h:1255
SIZE_T nUserActualSize
Definition: heappage.c:54
#define MEM_RESERVE
Definition: nt_native.h:1314
BOOLEAN RtlpPageHeapEnabled
Definition: heappage.c:107
ULONG HeapFlags
Definition: heappage.c:65
BOOLEAN NTAPI RtlTryEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
Definition: libsupp.c:117
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement)
ULONG ExtraFlags
Definition: heappage.c:98
#define DPH_BREAK_ON_RESERVE_FAIL
Definition: heappage.c:139
ULONG NTAPI RtlpDphGetBlockSizeFromCorruptedBlock(PVOID Block)
Definition: heappage.c:246
#define PAGE_NOACCESS
Definition: nt_native.h:1302
unsigned char BOOLEAN
SIZE_T nVirtualAccessSize
Definition: heappage.c:52
static WCHAR Address[46]
Definition: ping.c:68
#define DPH_FILL_END_STAMP_1
Definition: heappage.c:158
PDPH_HEAP_BLOCK pFreeAllocationListTail
Definition: heappage.c:80
#define _In_
Definition: ms_sal.h:308
struct _DPH_BLOCK_INFORMATION * PDPH_BLOCK_INFORMATION
NTSYSAPI PVOID NTAPI RtlDestroyHeap(IN PVOID HeapHandle)
#define APPLICATION_VERIFIER_CORRUPTED_END_STAMP
Definition: verifier.h:97
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
Definition: bufpool.h:45
PDPH_HEAP_BLOCK NTAPI RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:1014
#define DPH_VALINFO_BAD_INFIX_PATTERN
Definition: heappage.c:171
return Found
Definition: dirsup.c:1270
void * PVOID
Definition: retypes.h:9
#define APPLICATION_VERIFIER_DOUBLE_FREE
Definition: verifier.h:90
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
ULONG RtlpDphPageHeapListLength
Definition: heappage.c:117
struct _DPH_HEAP_BLOCK * pNextAlloc
Definition: heappage.c:45
VOID NTAPI RtlpDphPlaceOnPoolList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:511
VOID NTAPI RtlpDphFreeNodeForTable(IN PRTL_AVL_TABLE Table, IN PVOID Buffer)
Definition: heappage.c:1223
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
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
#define DPH_FILL
Definition: heappage.c:155
#define DPH_POOL_SIZE
Definition: heappage.c:135
PVOID NTAPI RtlpPageHeapReAllocate(HANDLE HeapPtr, ULONG Flags, PVOID Ptr, SIZE_T Size)
Definition: heappage.c:2015
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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define APPLICATION_VERIFIER_EXCEPTION_WHILE_VERIFYING_BLOCK_HEADER
Definition: verifier.h:92
#define APPLICATION_VERIFIER_CORRUPT_HEAP_POINTER
Definition: verifier.h:89
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
VOID NTAPI RtlpDphReturnNodeToUnusedList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:569
VOID NTAPI RtlpDphEnterCriticalSection(PDPH_HEAP_ROOT DphRoot, ULONG Flags)
Definition: heappage.c:261
VOID NTAPI RtlpDphPlaceOnFreeList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:491
RTL_BALANCED_LINKS TableLinks
Definition: heappage.c:47
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1165
ULONG nNodePools
Definition: heappage.c:94
_IRQL_requires_same_ _In_ PVOID _In_ PVOID SecondStruct
Definition: rtltypes.h:383
#define ASSERT(a)
Definition: mode.c:44
LIST_ENTRY AvailableEntry
Definition: heappage.c:46
__wchar_t WCHAR
Definition: xmlstorage.h:180
PUCHAR pUserAllocation
Definition: heappage.c:49
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ BOOLEAN Restart)
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
HANDLE NTAPI RtlpPageHeapCreate(ULONG Flags, PVOID Addr, SIZE_T TotalSize, SIZE_T CommitSize, PVOID Lock, PRTL_HEAP_PARAMETERS Parameters)
Definition: heappage.c:1533
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:404
VOID NTAPI RtlApplicationVerifierStop(_In_ ULONG_PTR Code, _In_ PCSTR Message, _In_ PVOID Value1, _In_ PCSTR Description1, _In_ PVOID Value2, _In_ PCSTR Description2, _In_ PVOID Value3, _In_ PCSTR Description3, _In_ PVOID Value4, _In_ PCSTR Description4)
Definition: appverifier.c:23
#define DPH_FILL_START_STAMP_2
Definition: heappage.c:157
unsigned short WORD
Definition: ntddk_ex.h:93
Type
Definition: Type.h:6
NTSYSAPI BOOLEAN WINAPI RtlValidateHeap(HANDLE, ULONG, LPCVOID)
VOID NTAPI RtlpDphFreeDelayedBlocksFromHeap(PDPH_HEAP_ROOT DphRoot, PHEAP NormalHeap)
Definition: heappage.c:1254
PDPH_HEAP_BLOCK pNodePoolListTail
Definition: heappage.c:93
ULONG RtlpDphNumberOfDelayedFreeBlocks
Definition: heappage.c:125
#define HEAP_SETTABLE_USER_FLAGS
Definition: nt_native.h:1708
#define APPLICATION_VERIFIER_CORRUPTED_INFIX_PATTERN
Definition: verifier.h:94
BOOLEAN NTAPI RtlpPageHeapSetUserFlags(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, ULONG UserFlagsReset, ULONG UserFlagsSet)
Definition: heappage.c:2268
LIST_ENTRY RtlpDphDelayedFreeQueue
Definition: heappage.c:122
Definition: partlist.h:33
NTSTATUS NTAPI RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
Definition: libsupp.c:126
PDPH_HEAP_BLOCK NodeToAllocate
Definition: heappage.c:75
#define HEAP_NO_ALIGNMENT
Definition: rtltypes.h:163
PRTL_TRACE_BLOCK StackTrace
Definition: heappage.c:57
PUCHAR pVirtualBlock
Definition: heappage.c:50
SINGLE_LIST_ENTRY FreePushList
Definition: heappage.c:34
#define DPH_EXTRA_CHECK_UNDERRUN
Definition: heappage.c:152
ULONG RtlpPageHeapSizeRangeEnd
Definition: heappage.c:109
SIZE_T nVirtualStorageBytes
Definition: heappage.c:72
VOID NTAPI RtlpDphInternalValidatePageHeap(PDPH_HEAP_ROOT DphRoot, PVOID Address, ULONG Value)
Definition: heappage.c:1314
NTSTATUS NTAPI RtlpDphAllocateVm(PVOID *Base, SIZE_T Size, ULONG Type, ULONG Protection)
Definition: heappage.c:342
BOOLEAN NTAPI RtlpDphWritePageHeapBlockInformation(PDPH_HEAP_ROOT DphRoot, PVOID UserAllocation, SIZE_T Size, SIZE_T UserSize)
Definition: heappage.c:441
VOID NTAPI RtlpDphPlaceOnBusyList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK DphNode)
Definition: heappage.c:467
SIZE_T nVirtualBlockSize
Definition: heappage.c:51
ULONG LowPart
Definition: typedefs.h:106
_IRQL_requires_same_ _In_ PVOID FirstStruct
Definition: rtltypes.h:383
VOID NTAPI RtlInitializeGenericTableAvl(IN OUT PRTL_AVL_TABLE Table, IN PRTL_AVL_COMPARE_ROUTINE CompareRoutine, IN PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine, IN PRTL_AVL_FREE_ROUTINE FreeRoutine, IN PVOID TableContext)
Definition: avltable.c:26
NTSYSAPI PVOID NTAPI RtlCreateHeap(IN ULONG Flags, IN PVOID HeapBase OPTIONAL, IN ULONG ReserveSize OPTIONAL, IN ULONG CommitSize OPTIONAL, IN PVOID Lock OPTIONAL, IN PRTL_HEAP_PARAMETERS Parameters OPTIONAL)
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
#define PAGE_SIZE
Definition: env_spec_w32.h:49
SIZE_T nBusyAllocationBytesAccessible
Definition: heappage.c:91
Definition: typedefs.h:119
SIZE_T nUserRequestedSize
Definition: heappage.c:53
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:305
ULONG RtlpPageHeapDllRangeEnd
Definition: heappage.c:110
#define HEAP_FLAG_PAGE_ALLOCS
Definition: rtltypes.h:160
#define DPH_VALINFO_BAD_POINTER
Definition: heappage.c:166
#define DPH_DEBUG_INTERNAL_VALIDATE
Definition: heappage.c:147
#define DPH_BREAK_ON_NULL_FREE
Definition: heappage.c:144
#define DPH_VALINFO_CORRUPTED_AFTER_FREE
Definition: heappage.c:173
LONG RtlpDphCounter
Definition: heappage.c:128
LIST_ENTRY NextHeap
Definition: heappage.c:97
ULONG Seed
Definition: heappage.c:99
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:210
PVOID NTAPI RtlpPageHeapAllocate(IN PVOID HeapPtr, IN ULONG Flags, IN SIZE_T Size)
Definition: heappage.c:1758
PVOID NTAPI RtlpDphHeapFromPointer(PDPH_HEAP_ROOT DphHeap)
Definition: heappage.c:240
NTSYSAPI VOID NTAPI RtlInitializeSListHead(_Out_ PSLIST_HEADER ListHead)
Definition: slist.c:25
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: compat.h:835
VOID NTAPI RtlpDphLeaveCriticalSection(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:289
ULONG Signature
Definition: heappage.c:64
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
UNICODE_STRING RtlpDphTargetDllsUnicode
Definition: heappage.c:118
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
PDPH_HEAP_BLOCK NTAPI RtlpDphFindAvailableMemory(PDPH_HEAP_ROOT DphRoot, SIZE_T Size, BOOLEAN Grow)
Definition: heappage.c:904
PVOID NTAPI RtlpDphPointerFromHandle(PVOID Handle)
Definition: heappage.c:223
ULONG Flags
Definition: heap.h:226
VOID NTAPI RtlpDphPreProcessing(PDPH_HEAP_ROOT DphRoot, ULONG Flags)
Definition: heappage.c:297
VOID NTAPI RtlpDphRaiseException(NTSTATUS Status)
Definition: heappage.c:207
PUCHAR pVirtualRegion
Definition: heappage.c:59
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
struct _DPH_BLOCK_INFORMATION DPH_BLOCK_INFORMATION
#define DPH_FILL_SUFFIX
Definition: heappage.c:160
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
PDPH_HEAP_BLOCK pUnusedNodeListHead
Definition: heappage.c:88
struct _DPH_HEAP_BLOCK * PDPH_HEAP_BLOCK
HEAP_LOCK _RtlpDphDelayedFreeQueueLock
Definition: heappage.c:120
SIZE_T nFreeAllocationBytesCommitted
Definition: heappage.c:82
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
#define PAGE_READONLY
Definition: compat.h:138
enum _RTL_GENERIC_COMPARE_RESULTS RTL_GENERIC_COMPARE_RESULTS
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
SIZE_T nNodePoolBytes
Definition: heappage.c:95
PDPH_HEAP_BLOCK NTAPI RtlpDphTakeNodeFromUnusedList(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:547
PRTL_TRACE_BLOCK CreateStackTrace
Definition: heappage.c:101
#define DPRINT1
Definition: precomp.h:8
unsigned char Byte
Definition: zlib.h:37
PVOID NTAPI RtlpPageHeapDestroy(HANDLE HeapPtr)
Definition: heappage.c:1674
NTSTATUS NTAPI RtlpSecMemFreeVirtualMemory(HANDLE Process, PVOID *Base, PSIZE_T Size, ULONG Type)
Definition: heappage.c:319
NTSTATUS NTAPI RtlpDphFreeVm(PVOID Base, SIZE_T Size, ULONG Type)
Definition: heappage.c:381
ULONG RtlpDphBreakOptions
Definition: heappage.c:184
#define MEM_RELEASE
Definition: nt_native.h:1316
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
BOOLEAN NTAPI RtlFlushSecureMemoryCache(IN PVOID MemoryCache, IN OPTIONAL SIZE_T MemoryLength)
Definition: security.c:830
_In_ HANDLE Handle
Definition: extypes.h:390
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
BOOLEAN NTAPI RtlpDphIsPageHeapBlock(PDPH_HEAP_ROOT DphRoot, PVOID Block, PULONG ValidationInformation, BOOLEAN CheckFillers)
Definition: heappage.c:1417
ULONG nAvailableAllocations
Definition: heappage.c:85
BOOLEAN RtlpDphPageHeapListInitialized
Definition: heappage.c:114
VOID NTAPI RtlpDphRemoveFromAvailableList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
Definition: heappage.c:585
unsigned int ULONG
Definition: retypes.h:1
struct _HEAP * PHEAP
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define UNIMPLEMENTED
Definition: debug.h:115
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlLookupElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
DWORD ExceptionFlags
Definition: compat.h:209
SIZE_T nBusyAllocationBytesCommitted
Definition: heappage.c:77
ULONG nUnusedNodes
Definition: heappage.c:90
NTSTATUS NTAPI RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock)
Definition: libsupp.c:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
NTSTATUS NTAPI RtlpDphTargetDllsLogicInitialize(VOID)
Definition: heappage.c:1307
LONG RtlpDphProtectFails
Definition: heappage.c:132
ULONG ForceFlags
Definition: heap.h:227
ULONG nVirtualStorageRanges
Definition: heappage.c:71
ULONG RtlpDphDebugOptions
Definition: heappage.c:185
VOID NTAPI RtlpDphCoalesceFreeIntoAvailable(PDPH_HEAP_ROOT DphRoot, ULONG LeaveOnFreeList)
Definition: heappage.c:794
PDPH_HEAP_BLOCK pUnusedNodeListTail
Definition: heappage.c:89
RTL_AVL_TABLE BusyNodesTable
Definition: heappage.c:74
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define DPH_FREE_LIST_MINIMUM
Definition: heappage.c:136
#define STATUS_SUCCESS
Definition: shellext.h:65
DWORD NumberParameters
Definition: compat.h:212
#define DPRINT
Definition: sndvol32.h:71
LONG RtlpDphReleaseFails
Definition: heappage.c:130
ULONG RtlpPageHeapDllRangeStart
Definition: heappage.c:110
#define APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK_AFTER_FREE
Definition: verifier.h:93
BOOLEAN NTAPI RtlpDebugPageHeapValidate(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress)
Definition: heappage.c:2351
RTL_GENERIC_COMPARE_RESULTS NTAPI RtlpDphCompareNodeForTable(IN PRTL_AVL_TABLE Table, IN PVOID FirstStruct, IN PVOID SecondStruct)
Definition: heappage.c:1183
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:393
#define APPLICATION_VERIFIER_CORRUPTED_PREFIX_PATTERN
Definition: verifier.h:98
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
NTSYSAPI NTSTATUS NTAPI ZwProtectVirtualMemory(_In_ HANDLE ProcessHandle, _In_ PVOID *BaseAddress, _In_ SIZE_T *NumberOfBytesToProtect, _In_ ULONG NewAccessProtection, _Out_ PULONG OldAccessProtection)
ULONG nFreeAllocations
Definition: heappage.c:81
BOOLEAN NTAPI RtlpDphGrowVirtual(PDPH_HEAP_ROOT DphRoot, SIZE_T Size)
Definition: heappage.c:1124
#define HEAP_REALLOC_IN_PLACE_ONLY
Definition: nt_native.h:1696
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
NTSTATUS NTAPI RtlpDphInitializeDelayedFreeQueue(VOID)
Definition: heappage.c:1230
#define DPH_SIGNATURE
Definition: heappage.c:176
Definition: heap.c:51
VOID NTAPI RtlpDphVerifyIntegrity(PDPH_HEAP_ROOT DphRoot)
Definition: heappage.c:1320
SIZE_T nAvailableAllocationBytesCommitted
Definition: heappage.c:86
#define PAGE_READWRITE
Definition: nt_native.h:1304
Definition: dlist.c:348
PDPH_HEAP_BLOCK pNodePoolListHead
Definition: heappage.c:92
ULONG nBusyAllocations
Definition: heappage.c:76
#define DPH_VALINFO_BAD_START_STAMP
Definition: heappage.c:164