mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[RTL/DPH]
- Implement other support locking/unlocking, handle-related routines. - Fix RtlpDphFreeVm definition. - Node lists related improvements: Add a function for removing a node from a free list, implement coalescing free nodes into an available list. - Implement a non-implemented case in RtlpDphAllocateNode when there is a need to allocate more virtual memory, and fix incorrect size calculation too. - Implement a function for validating the page heap block. - Implement RtlpPageHeapDestroy. Now we have two exported APIs ready: heap create and heap destroy. svn path=/trunk/; revision=50721
This commit is contained in:
parent
a92739091b
commit
d0e56f53d1
1 changed files with 312 additions and 16 deletions
|
@ -139,8 +139,21 @@ LONG RtlpDphProtectFails;
|
||||||
#define DPH_DEBUG_INTERNAL_VALIDATE 0x01
|
#define DPH_DEBUG_INTERNAL_VALIDATE 0x01
|
||||||
#define DPH_DEBUG_VERBOSE 0x04
|
#define DPH_DEBUG_VERBOSE 0x04
|
||||||
|
|
||||||
|
/* DPH ExtraFlags */
|
||||||
|
#define DPH_EXTRA_CHECK_CORRUPTED_BLOCKS 0x10
|
||||||
|
|
||||||
/* Fillers */
|
/* Fillers */
|
||||||
#define DPH_FILL 0xEEEEEEEE
|
#define DPH_FILL 0xEEEEEEEE
|
||||||
|
#define DPH_FILL_START_STAMP_1 0xABCDBBBB
|
||||||
|
#define DPH_FILL_START_STAMP_2 0xABCDBBBA
|
||||||
|
#define DPH_FILL_END_STAMP_1 0xDCBABBBB
|
||||||
|
#define DPH_FILL_BLOCK_END 0xD0
|
||||||
|
|
||||||
|
/* Validation info flags */
|
||||||
|
#define DPH_VALINFO_BAD_START_STAMP 0x01
|
||||||
|
#define DPH_VALINFO_BAD_END_STAMP 0x02
|
||||||
|
#define DPH_VALINFO_BAD_POINTER 0x04
|
||||||
|
#define DPH_VALINFO_BAD_END_FILL 0x10
|
||||||
|
|
||||||
/* Signatures */
|
/* Signatures */
|
||||||
#define DPH_SIGNATURE 0xFFEEDDCC
|
#define DPH_SIGNATURE 0xFFEEDDCC
|
||||||
|
@ -155,6 +168,67 @@ LONG RtlpDphProtectFails;
|
||||||
BOOLEAN NTAPI
|
BOOLEAN NTAPI
|
||||||
RtlpDphGrowVirtual(PDPH_HEAP_ROOT DphRoot, SIZE_T Size);
|
RtlpDphGrowVirtual(PDPH_HEAP_ROOT DphRoot, SIZE_T Size);
|
||||||
|
|
||||||
|
PVOID NTAPI
|
||||||
|
RtlpDphPointerFromHandle(PVOID Handle)
|
||||||
|
{
|
||||||
|
PHEAP NormalHeap = (PHEAP)Handle;
|
||||||
|
PDPH_HEAP_ROOT DphHeap = (PDPH_HEAP_ROOT)((PUCHAR)Handle + PAGE_SIZE);
|
||||||
|
|
||||||
|
if (NormalHeap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
|
||||||
|
{
|
||||||
|
if (DphHeap->Signature == DPH_SIGNATURE)
|
||||||
|
return DphHeap;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("heap handle with incorrect signature\n");
|
||||||
|
DbgBreakPoint();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
RtlpDphEnterCriticalSection(PDPH_HEAP_ROOT DphRoot, ULONG Flags)
|
||||||
|
{
|
||||||
|
if (Flags & HEAP_NO_SERIALIZE)
|
||||||
|
{
|
||||||
|
/* More complex scenario */
|
||||||
|
if (!RtlTryEnterCriticalSection(DphRoot->HeapCritSect))
|
||||||
|
{
|
||||||
|
if (!DphRoot->nRemoteLockAcquired)
|
||||||
|
{
|
||||||
|
DPRINT1("multithreaded access in HEAP_NO_SERIALIZE heap\n");
|
||||||
|
DbgBreakPoint();
|
||||||
|
|
||||||
|
/* Clear out the no serialize flag */
|
||||||
|
DphRoot->HeapFlags &= ~HEAP_NO_SERIALIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter the heap's critical section */
|
||||||
|
RtlEnterCriticalSection(DphRoot->HeapCritSect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Just enter the heap's critical section */
|
||||||
|
RtlEnterCriticalSection(DphRoot->HeapCritSect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
RtlpDphLeaveCriticalSection(PDPH_HEAP_ROOT DphRoot)
|
||||||
|
{
|
||||||
|
/* Just leave the heap's critical section */
|
||||||
|
RtlLeaveCriticalSection(DphRoot->HeapCritSect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
RtlpDphPreProcessing(PDPH_HEAP_ROOT DphRoot, ULONG Flags)
|
||||||
|
{
|
||||||
|
RtlpDphEnterCriticalSection(DphRoot, Flags);
|
||||||
|
|
||||||
|
/* FIXME: Validate integrity, internal lists if necessary */
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
RtlpSecMemFreeVirtualMemory(HANDLE Process, PVOID *Base, PSIZE_T Size, ULONG Type)
|
RtlpSecMemFreeVirtualMemory(HANDLE Process, PVOID *Base, PSIZE_T Size, ULONG Type)
|
||||||
{
|
{
|
||||||
|
@ -218,7 +292,7 @@ RtlpDphAllocateVm(PVOID *Base, SIZE_T Size, ULONG Type, ULONG Protection)
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
RtlpDphFreeVm(PVOID Base, SIZE_T Size, ULONG Type, ULONG Protection)
|
RtlpDphFreeVm(PVOID Base, SIZE_T Size, ULONG Type)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
@ -362,6 +436,28 @@ RtlpDphRemoveFromAvailableList(PDPH_HEAP_ROOT DphRoot,
|
||||||
POINTER_REMOVE_BIAS(Node->AdjacencyEntry.Blink);
|
POINTER_REMOVE_BIAS(Node->AdjacencyEntry.Blink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
RtlpDphRemoveFromFreeList(PDPH_HEAP_ROOT DphRoot,
|
||||||
|
PDPH_HEAP_BLOCK Node,
|
||||||
|
PDPH_HEAP_BLOCK Prev)
|
||||||
|
{
|
||||||
|
PDPH_HEAP_BLOCK Next;
|
||||||
|
|
||||||
|
/* Detach it from the list */
|
||||||
|
Next = Node->pNextAlloc;
|
||||||
|
if (DphRoot->pFreeAllocationListHead == Node)
|
||||||
|
DphRoot->pFreeAllocationListHead = Next;
|
||||||
|
if (DphRoot->pFreeAllocationListTail == Node)
|
||||||
|
DphRoot->pFreeAllocationListTail = Prev;
|
||||||
|
if (Prev) Prev->pNextAlloc = Next;
|
||||||
|
|
||||||
|
/* Decrease heap counters */
|
||||||
|
DphRoot->nFreeAllocations--;
|
||||||
|
DphRoot->nFreeAllocationBytesCommitted -= Node->nVirtualBlockSize;
|
||||||
|
|
||||||
|
Node->StackTrace = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
||||||
PDPH_HEAP_BLOCK Node)
|
PDPH_HEAP_BLOCK Node)
|
||||||
|
@ -433,9 +529,30 @@ RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
RtlpDphCoalesceFreeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
RtlpDphCoalesceFreeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
||||||
ULONG Size)
|
ULONG LeaveOnFreeList)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
PDPH_HEAP_BLOCK Node = DphRoot->pFreeAllocationListHead, Next;
|
||||||
|
SIZE_T FreeAllocations = DphRoot->nFreeAllocations;
|
||||||
|
|
||||||
|
/* Make sure requested size is not too big */
|
||||||
|
ASSERT(FreeAllocations >= LeaveOnFreeList);
|
||||||
|
|
||||||
|
while (Node)
|
||||||
|
{
|
||||||
|
FreeAllocations--;
|
||||||
|
if (FreeAllocations <= LeaveOnFreeList) break;
|
||||||
|
|
||||||
|
/* Get the next pointer, because it may be changed after following two calls */
|
||||||
|
Next = Node->pNextAlloc;
|
||||||
|
|
||||||
|
/* Remove it from the free list */
|
||||||
|
RtlpDphRemoveFromFreeList(DphRoot, Node, NULL);
|
||||||
|
|
||||||
|
/* And put into the available */
|
||||||
|
RtlpDphCoalesceNodeIntoAvailable(DphRoot, Node);
|
||||||
|
|
||||||
|
Node = Next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
|
@ -573,7 +690,7 @@ RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
|
||||||
{
|
{
|
||||||
PDPH_HEAP_BLOCK Node;
|
PDPH_HEAP_BLOCK Node;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG Size = DPH_POOL_SIZE;
|
SIZE_T Size = DPH_POOL_SIZE, SizeVirtual;
|
||||||
PVOID Ptr;
|
PVOID Ptr;
|
||||||
|
|
||||||
/* Check for the easy case */
|
/* Check for the easy case */
|
||||||
|
@ -601,17 +718,20 @@ RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
|
||||||
{
|
{
|
||||||
RtlpDphRemoveFromAvailableList(DphRoot, Node);
|
RtlpDphRemoveFromAvailableList(DphRoot, Node);
|
||||||
Ptr = Node->pVirtualBlock;
|
Ptr = Node->pVirtualBlock;
|
||||||
|
SizeVirtual = Node->nVirtualBlockSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No free space, need to alloc a new VM block */
|
/* No free space, need to alloc a new VM block */
|
||||||
Size = DPH_POOL_SIZE;
|
Size = DPH_POOL_SIZE;
|
||||||
Status = RtlpDphAllocateVm(&Ptr, DPH_RESERVE_SIZE, MEM_COMMIT, PAGE_NOACCESS);
|
SizeVirtual = DPH_RESERVE_SIZE;
|
||||||
|
Status = RtlpDphAllocateVm(&Ptr, SizeVirtual, MEM_COMMIT, PAGE_NOACCESS);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Retry with a smaller size */
|
/* Retry with a smaller size */
|
||||||
Status = RtlpDphAllocateVm(&Ptr, 0x10000, MEM_COMMIT, PAGE_NOACCESS);
|
SizeVirtual = 0x10000;
|
||||||
|
Status = RtlpDphAllocateVm(&Ptr, SizeVirtual, MEM_COMMIT, PAGE_NOACCESS);
|
||||||
if (!NT_SUCCESS(Status)) return NULL;
|
if (!NT_SUCCESS(Status)) return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -620,7 +740,16 @@ RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
|
||||||
Status = RtlpDphProtectVm(Ptr, Size, PAGE_READWRITE);
|
Status = RtlpDphProtectVm(Ptr, Size, PAGE_READWRITE);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ASSERT(FALSE);
|
if (Node)
|
||||||
|
{
|
||||||
|
RtlpDphCoalesceNodeIntoAvailable(DphRoot, Node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//RtlpDphFreeVm();
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,11 +759,7 @@ RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
|
||||||
/* Add a new pool based on this VM */
|
/* Add a new pool based on this VM */
|
||||||
RtlpDphAddNewPool(DphRoot, Node, Ptr, Size, TRUE);
|
RtlpDphAddNewPool(DphRoot, Node, Ptr, Size, TRUE);
|
||||||
|
|
||||||
if (!Node)
|
if (Node)
|
||||||
{
|
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (Node->nVirtualBlockSize > Size)
|
if (Node->nVirtualBlockSize > Size)
|
||||||
{
|
{
|
||||||
|
@ -648,6 +773,23 @@ RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
|
||||||
RtlpDphReturnNodeToUnusedList(DphRoot, Node);
|
RtlpDphReturnNodeToUnusedList(DphRoot, Node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The new VM block was just allocated a few code lines ago,
|
||||||
|
so initialize it */
|
||||||
|
Node = RtlpDphTakeNodeFromUnusedList(DphRoot);
|
||||||
|
Node->pVirtualBlock = Ptr;
|
||||||
|
Node->nVirtualBlockSize = SizeVirtual;
|
||||||
|
RtlpDphPlaceOnVirtualList(DphRoot, Node);
|
||||||
|
|
||||||
|
Node = RtlpDphTakeNodeFromUnusedList(DphRoot);
|
||||||
|
Node->pVirtualBlock = (PUCHAR)Ptr + Size;
|
||||||
|
Node->nVirtualBlockSize = SizeVirtual - Size;
|
||||||
|
RtlpDphPlaceOnVirtualList(DphRoot, Node);
|
||||||
|
|
||||||
|
/* Coalesce them into available list */
|
||||||
|
RtlpDphCoalesceNodeIntoAvailable(DphRoot, Node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return RtlpDphTakeNodeFromUnusedList(DphRoot);
|
return RtlpDphTakeNodeFromUnusedList(DphRoot);
|
||||||
|
@ -709,7 +851,7 @@ RtlpDphCompareNodeForTable(IN PRTL_AVL_TABLE Table,
|
||||||
IN PVOID FirstStruct,
|
IN PVOID FirstStruct,
|
||||||
IN PVOID SecondStruct)
|
IN PVOID SecondStruct)
|
||||||
{
|
{
|
||||||
/* FIXME: TODO */
|
UNIMPLEMENTED;
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -719,7 +861,7 @@ NTAPI
|
||||||
RtlpDphAllocateNodeForTable(IN PRTL_AVL_TABLE Table,
|
RtlpDphAllocateNodeForTable(IN PRTL_AVL_TABLE Table,
|
||||||
IN CLONG ByteSize)
|
IN CLONG ByteSize)
|
||||||
{
|
{
|
||||||
/* FIXME: TODO */
|
UNIMPLEMENTED;
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -729,7 +871,7 @@ NTAPI
|
||||||
RtlpDphFreeNodeForTable(IN PRTL_AVL_TABLE Table,
|
RtlpDphFreeNodeForTable(IN PRTL_AVL_TABLE Table,
|
||||||
IN PVOID Buffer)
|
IN PVOID Buffer)
|
||||||
{
|
{
|
||||||
/* FIXME: TODO */
|
UNIMPLEMENTED;
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,6 +882,13 @@ RtlpDphInitializeDelayedFreeQueue()
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
RtlpDphFreeDelayedBlocksFromHeap(PDPH_HEAP_ROOT DphRoot,
|
||||||
|
PHEAP NormalHeap)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
RtlpDphTargetDllsLogicInitialize()
|
RtlpDphTargetDllsLogicInitialize()
|
||||||
{
|
{
|
||||||
|
@ -753,6 +902,78 @@ RtlpDphInternalValidatePageHeap(PDPH_HEAP_ROOT DphRoot, PVOID Address, ULONG Val
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
RtlpDphReportCorruptedBlock(PDPH_HEAP_ROOT DphRoot,
|
||||||
|
ULONG Reserved,
|
||||||
|
PVOID Block,
|
||||||
|
ULONG ValidationInfo)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN NTAPI
|
||||||
|
RtlpDphIsPageHeapBlock(PDPH_HEAP_ROOT DphRoot,
|
||||||
|
PVOID Block,
|
||||||
|
PULONG ValidationInformation,
|
||||||
|
BOOLEAN CheckFillers)
|
||||||
|
{
|
||||||
|
PDPH_BLOCK_INFORMATION BlockInfo;
|
||||||
|
BOOLEAN SomethingWrong = FALSE;
|
||||||
|
PUCHAR Byte, Start, End;
|
||||||
|
|
||||||
|
ASSERT(ValidationInformation != NULL);
|
||||||
|
*ValidationInformation = 0;
|
||||||
|
|
||||||
|
// _SEH2_TRY {
|
||||||
|
BlockInfo = (PDPH_BLOCK_INFORMATION)Block - 1;
|
||||||
|
|
||||||
|
/* Check stamps */
|
||||||
|
if (BlockInfo->StartStamp != DPH_FILL_START_STAMP_1)
|
||||||
|
{
|
||||||
|
*ValidationInformation |= DPH_VALINFO_BAD_START_STAMP;
|
||||||
|
SomethingWrong = TRUE;
|
||||||
|
|
||||||
|
/* Check if it has an alloc/free mismatch */
|
||||||
|
if (BlockInfo->StartStamp == DPH_FILL_START_STAMP_2)
|
||||||
|
{
|
||||||
|
/* Notify respectively */
|
||||||
|
*ValidationInformation = 0x101;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BlockInfo->EndStamp != DPH_FILL_END_STAMP_1)
|
||||||
|
{
|
||||||
|
*ValidationInformation |= DPH_VALINFO_BAD_END_STAMP;
|
||||||
|
SomethingWrong = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check root heap pointer */
|
||||||
|
if (BlockInfo->Heap != DphRoot)
|
||||||
|
{
|
||||||
|
*ValidationInformation |= DPH_VALINFO_BAD_POINTER;
|
||||||
|
SomethingWrong = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check other fillers if requested */
|
||||||
|
if (CheckFillers)
|
||||||
|
{
|
||||||
|
/* Check space after the block */
|
||||||
|
Start = (PUCHAR)Block + BlockInfo->RequestedSize;
|
||||||
|
End = (PUCHAR)ROUND_UP(Start, PAGE_SIZE);
|
||||||
|
for (Byte = Start; Byte < End; Byte++)
|
||||||
|
{
|
||||||
|
if (*Byte != DPH_FILL_BLOCK_END)
|
||||||
|
{
|
||||||
|
*ValidationInformation |= DPH_VALINFO_BAD_END_FILL;
|
||||||
|
SomethingWrong = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (SomethingWrong == FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
RtlpDphProcessStartupInitialization()
|
RtlpDphProcessStartupInitialization()
|
||||||
{
|
{
|
||||||
|
@ -926,7 +1147,82 @@ RtlpPageHeapCreate(ULONG Flags,
|
||||||
PVOID NTAPI
|
PVOID NTAPI
|
||||||
RtlpPageHeapDestroy(HANDLE HeapPtr)
|
RtlpPageHeapDestroy(HANDLE HeapPtr)
|
||||||
{
|
{
|
||||||
return FALSE;
|
PDPH_HEAP_ROOT DphRoot;
|
||||||
|
PDPH_HEAP_BLOCK Node, Next;
|
||||||
|
PHEAP NormalHeap;
|
||||||
|
ULONG Value;
|
||||||
|
|
||||||
|
/* Check if it's not a process heap */
|
||||||
|
if (HeapPtr == RtlGetProcessHeap())
|
||||||
|
{
|
||||||
|
DbgBreakPoint();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get pointer to the heap root */
|
||||||
|
DphRoot = RtlpDphPointerFromHandle(HeapPtr);
|
||||||
|
if (!DphRoot) return NULL;
|
||||||
|
|
||||||
|
RtlpDphPreProcessing(DphRoot, DphRoot->HeapFlags);
|
||||||
|
|
||||||
|
/* Get the pointer to the normal heap */
|
||||||
|
NormalHeap = DphRoot->NormalHeap;
|
||||||
|
|
||||||
|
/* Free the delayed-free blocks */
|
||||||
|
RtlpDphFreeDelayedBlocksFromHeap(DphRoot, NormalHeap);
|
||||||
|
|
||||||
|
/* Go through the busy blocks */
|
||||||
|
Node = RtlEnumerateGenericTableAvl(&DphRoot->BusyNodesTable, TRUE);
|
||||||
|
|
||||||
|
while (Node)
|
||||||
|
{
|
||||||
|
if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_CORRUPTED_BLOCKS))
|
||||||
|
{
|
||||||
|
if (!RtlpDphIsPageHeapBlock(DphRoot, Node->pUserAllocation, &Value, TRUE))
|
||||||
|
{
|
||||||
|
RtlpDphReportCorruptedBlock(DphRoot, 3, Node->pUserAllocation, Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Call AV notification */
|
||||||
|
//AVrfInternalHeapFreeNotification();
|
||||||
|
|
||||||
|
/* Go to the next node */
|
||||||
|
Node = RtlEnumerateGenericTableAvl(&DphRoot->BusyNodesTable, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Acquire the global heap list lock */
|
||||||
|
RtlEnterCriticalSection(&RtlpDphPageHeapListLock);
|
||||||
|
|
||||||
|
/* Remove the entry and decrement the global counter */
|
||||||
|
RemoveEntryList(&DphRoot->NextHeap);
|
||||||
|
RtlpDphPageHeapListLength--;
|
||||||
|
|
||||||
|
/* Release the global heap list lock */
|
||||||
|
RtlLeaveCriticalSection(&RtlpDphPageHeapListLock);
|
||||||
|
|
||||||
|
/* Leave and delete this heap's critical section */
|
||||||
|
RtlLeaveCriticalSection(DphRoot->HeapCritSect);
|
||||||
|
RtlDeleteCriticalSection(DphRoot->HeapCritSect);
|
||||||
|
|
||||||
|
/* Now go through all virtual list nodes and release the VM */
|
||||||
|
Node = DphRoot->pVirtualStorageListHead;
|
||||||
|
while (Node)
|
||||||
|
{
|
||||||
|
Next = Node->pNextAlloc;
|
||||||
|
/* Release the memory without checking result */
|
||||||
|
RtlpDphFreeVm(Node->pVirtualBlock, 0, MEM_RELEASE);
|
||||||
|
Node = Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroy the normal heap */
|
||||||
|
RtlDestroyHeap(NormalHeap);
|
||||||
|
|
||||||
|
/* Report success */
|
||||||
|
if (RtlpDphDebugOptions & DPH_DEBUG_VERBOSE)
|
||||||
|
DPRINT1("Page heap: process 0x%X destroyed heap @ %p (%p)\n", NtCurrentTeb()->ClientId.UniqueProcess, HeapPtr, NormalHeap);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVOID NTAPI
|
PVOID NTAPI
|
||||||
|
|
Loading…
Reference in a new issue