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