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