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