mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
[RTL/DPH]
- Implement heap free operation using already implemented busy/free/available/unused lists support and other base routines. - Implement missing place to free list and remove from busy list routines. - Implement find busy block routine (using AVL tree). - Fix a bug in RtlpDphCoalesceNodeIntoAvailable() which resulted in unwanted attempt to merge the only node with itself (which failed anyway). - Fix a bug in RtlpDphCoalesceNodeIntoAvailable() which incorrectly removed a node from available list (which is implemented as a standard NT double-linked list, compared to unused and free lists which are implemented as single-linked custom lists and busy list which is an AVL tree). Result of that bug was an infinite loop at the next attempt to traverse the list of available nodes. - In RtlpDphCoalesceFreeIntoAvailable() break when FreeAllocations becomes less than LeaveOnFreeList (before it would break 1 size too early). - Fix list traversal in RtlpDphSearchAvailableMemoryListForBestFit(). If it couldn't find a node, it would return the last node in the list instead of NULL. - In RtlpDphFindAvailableMemory(), a new smaller size should be 4 times smaller, not just 2. - Add a #if0-ed section in RtlpDphRemoveFromAvailableList which checks if a request to remove node not in the list performed. Used only for debugging. - Add a trace dprint to every type of list insert/removal operation for easier tracking. - Add break on NULL ptr freeing support. - RtlpDphSetProtectionAfterUse() is stubbed and protection is set directly in RtlpDphHeapFree(). To be moved into this function. svn path=/trunk/; revision=50860
This commit is contained in:
parent
77aa443412
commit
e9af1d723f
1 changed files with 230 additions and 29 deletions
|
@ -137,20 +137,22 @@ LONG RtlpDphProtectFails;
|
||||||
#define DPH_BREAK_ON_RELEASE_FAIL 0x04
|
#define DPH_BREAK_ON_RELEASE_FAIL 0x04
|
||||||
#define DPH_BREAK_ON_FREE_FAIL 0x08
|
#define DPH_BREAK_ON_FREE_FAIL 0x08
|
||||||
#define DPH_BREAK_ON_PROTECT_FAIL 0x10
|
#define DPH_BREAK_ON_PROTECT_FAIL 0x10
|
||||||
|
#define DPH_BREAK_ON_NULL_FREE 0x80
|
||||||
|
|
||||||
/* RtlpDphDebugOptions */
|
/* RtlpDphDebugOptions */
|
||||||
#define DPH_DEBUG_INTERNAL_VALIDATE 0x01
|
#define DPH_DEBUG_INTERNAL_VALIDATE 0x01
|
||||||
#define DPH_DEBUG_VERBOSE 0x04
|
#define DPH_DEBUG_VERBOSE 0x04
|
||||||
|
|
||||||
/* DPH ExtraFlags */
|
/* DPH ExtraFlags */
|
||||||
#define DPH_EXTRA_CHECK_UNDERRUN 0x10
|
#define DPH_EXTRA_LOG_STACK_TRACES 0x02
|
||||||
#define DPH_LOG_STACK_TRACES 0x0 //FIXME: Get correct value
|
#define DPH_EXTRA_CHECK_UNDERRUN 0x10
|
||||||
|
|
||||||
/* Fillers */
|
/* Fillers */
|
||||||
#define DPH_FILL 0xEEEEEEEE
|
#define DPH_FILL 0xEEEEEEEE
|
||||||
#define DPH_FILL_START_STAMP_1 0xABCDBBBB
|
#define DPH_FILL_START_STAMP_1 0xABCDBBBB
|
||||||
#define DPH_FILL_START_STAMP_2 0xABCDBBBA
|
#define DPH_FILL_START_STAMP_2 0xABCDBBBA
|
||||||
#define DPH_FILL_END_STAMP_1 0xDCBABBBB
|
#define DPH_FILL_END_STAMP_1 0xDCBABBBB
|
||||||
|
#define DPH_FILL_END_STAMP_2 0xDCBABBBA
|
||||||
#define DPH_FILL_SUFFIX 0xD0
|
#define DPH_FILL_SUFFIX 0xD0
|
||||||
#define DPH_FILL_INFIX 0xC0
|
#define DPH_FILL_INFIX 0xC0
|
||||||
|
|
||||||
|
@ -452,10 +454,32 @@ RtlpDphPlaceOnBusyList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK DphNode)
|
||||||
DphRoot->nBusyAllocationBytesCommitted += DphNode->nVirtualBlockSize;
|
DphRoot->nBusyAllocationBytesCommitted += DphNode->nVirtualBlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
RtlpDphPlaceOnFreeList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
|
||||||
|
{
|
||||||
|
DPRINT("RtlpDphPlaceOnFreeList(%p %p)\n", DphRoot, Node);
|
||||||
|
|
||||||
|
/* Node is being added to the tail of the list */
|
||||||
|
Node->pNextAlloc = NULL;
|
||||||
|
|
||||||
|
/* Add it to the tail of the linked list */
|
||||||
|
if (DphRoot->pFreeAllocationListTail)
|
||||||
|
DphRoot->pFreeAllocationListTail->pNextAlloc = Node;
|
||||||
|
else
|
||||||
|
DphRoot->pFreeAllocationListHead = Node;
|
||||||
|
DphRoot->pFreeAllocationListTail = Node;
|
||||||
|
|
||||||
|
/* Update byte counts taking in account this new node */
|
||||||
|
DphRoot->nFreeAllocations++;
|
||||||
|
DphRoot->nFreeAllocationBytesCommitted += Node->nVirtualBlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
RtlpDphPlaceOnPoolList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
|
RtlpDphPlaceOnPoolList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
|
||||||
{
|
{
|
||||||
/* DphNode is being added to the tail of the list */
|
DPRINT("RtlpDphPlaceOnPoolList(%p %p)\n", DphRoot, Node);
|
||||||
|
|
||||||
|
/* Node is being added to the tail of the list */
|
||||||
Node->pNextAlloc = NULL;
|
Node->pNextAlloc = NULL;
|
||||||
|
|
||||||
/* Add it to the tail of the linked list */
|
/* Add it to the tail of the linked list */
|
||||||
|
@ -473,6 +497,8 @@ RtlpDphPlaceOnPoolList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
RtlpDphPlaceOnVirtualList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
|
RtlpDphPlaceOnVirtualList(PDPH_HEAP_ROOT DphRoot, PDPH_HEAP_BLOCK Node)
|
||||||
{
|
{
|
||||||
|
DPRINT("RtlpDphPlaceOnVirtualList(%p %p)\n", DphRoot, Node);
|
||||||
|
|
||||||
/* Add it to the head of the virtual list */
|
/* Add it to the head of the virtual list */
|
||||||
Node->pNextAlloc = DphRoot->pVirtualStorageListHead;
|
Node->pNextAlloc = DphRoot->pVirtualStorageListHead;
|
||||||
if (!DphRoot->pVirtualStorageListHead)
|
if (!DphRoot->pVirtualStorageListHead)
|
||||||
|
@ -490,6 +516,8 @@ RtlpDphTakeNodeFromUnusedList(PDPH_HEAP_ROOT DphRoot)
|
||||||
PDPH_HEAP_BLOCK Node = DphRoot->pUnusedNodeListHead;
|
PDPH_HEAP_BLOCK Node = DphRoot->pUnusedNodeListHead;
|
||||||
PDPH_HEAP_BLOCK Next;
|
PDPH_HEAP_BLOCK Next;
|
||||||
|
|
||||||
|
DPRINT("RtlpDphTakeNodeFromUnusedList(%p), ret %p\n", DphRoot, Node);
|
||||||
|
|
||||||
/* Take the first entry */
|
/* Take the first entry */
|
||||||
if (!Node) return NULL;
|
if (!Node) return NULL;
|
||||||
|
|
||||||
|
@ -508,6 +536,8 @@ VOID NTAPI
|
||||||
RtlpDphReturnNodeToUnusedList(PDPH_HEAP_ROOT DphRoot,
|
RtlpDphReturnNodeToUnusedList(PDPH_HEAP_ROOT DphRoot,
|
||||||
PDPH_HEAP_BLOCK Node)
|
PDPH_HEAP_BLOCK Node)
|
||||||
{
|
{
|
||||||
|
DPRINT("RtlpDphReturnNodeToUnusedList(%p, %p)\n", DphRoot, Node);
|
||||||
|
|
||||||
/* Add it back to the head of the unused list */
|
/* Add it back to the head of the unused list */
|
||||||
Node->pNextAlloc = DphRoot->pUnusedNodeListHead;
|
Node->pNextAlloc = DphRoot->pUnusedNodeListHead;
|
||||||
if (!DphRoot->pUnusedNodeListHead)
|
if (!DphRoot->pUnusedNodeListHead)
|
||||||
|
@ -528,6 +558,37 @@ RtlpDphRemoveFromAvailableList(PDPH_HEAP_ROOT DphRoot,
|
||||||
|
|
||||||
DPRINT("RtlpDphRemoveFromAvailableList(%p %p)\n", DphRoot, Node);
|
DPRINT("RtlpDphRemoveFromAvailableList(%p %p)\n", DphRoot, Node);
|
||||||
|
|
||||||
|
/* Check if it is in the list */
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
PLIST_ENTRY CurEntry;
|
||||||
|
PDPH_HEAP_BLOCK NodeEntry;
|
||||||
|
BOOLEAN Found = FALSE;
|
||||||
|
|
||||||
|
/* Find where to put this node according to its virtual address */
|
||||||
|
CurEntry = DphRoot->AvailableAllocationHead.Flink;
|
||||||
|
|
||||||
|
while (CurEntry != &DphRoot->AvailableAllocationHead)
|
||||||
|
{
|
||||||
|
NodeEntry = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
|
||||||
|
|
||||||
|
if (NodeEntry == Node)
|
||||||
|
{
|
||||||
|
Found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurEntry = CurEntry->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Found)
|
||||||
|
{
|
||||||
|
DPRINT1("Trying to remove non-existing in availlist node!\n");
|
||||||
|
DbgBreakPoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Remove it from the list */
|
/* Remove it from the list */
|
||||||
RemoveEntryList(&Node->AvailableEntry);
|
RemoveEntryList(&Node->AvailableEntry);
|
||||||
|
|
||||||
|
@ -540,6 +601,24 @@ RtlpDphRemoveFromAvailableList(PDPH_HEAP_ROOT DphRoot,
|
||||||
Node->AdjacencyEntry.Blink = (PLIST_ENTRY)POINTER_REMOVE_BIAS(Node->AdjacencyEntry.Blink);
|
Node->AdjacencyEntry.Blink = (PLIST_ENTRY)POINTER_REMOVE_BIAS(Node->AdjacencyEntry.Blink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
RtlpDphRemoveFromBusyList(PDPH_HEAP_ROOT DphRoot,
|
||||||
|
PDPH_HEAP_BLOCK Node)
|
||||||
|
{
|
||||||
|
BOOLEAN ElementPresent;
|
||||||
|
|
||||||
|
DPRINT("RtlpDphRemoveFromBusyList(%p %p)\n", DphRoot, Node);
|
||||||
|
|
||||||
|
/* Delete it from busy nodes table */
|
||||||
|
ElementPresent = RtlDeleteElementGenericTableAvl(&DphRoot->BusyNodesTable, &Node->pUserAllocation);
|
||||||
|
ASSERT(ElementPresent == TRUE);
|
||||||
|
|
||||||
|
/* Update counters */
|
||||||
|
DphRoot->nBusyAllocations--;
|
||||||
|
DphRoot->nBusyAllocationBytesCommitted -= Node->nVirtualBlockSize;
|
||||||
|
DphRoot->nBusyAllocationBytesAccessible -= Node->nVirtualAccessSize;
|
||||||
|
}
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
RtlpDphRemoveFromFreeList(PDPH_HEAP_ROOT DphRoot,
|
RtlpDphRemoveFromFreeList(PDPH_HEAP_ROOT DphRoot,
|
||||||
PDPH_HEAP_BLOCK Node,
|
PDPH_HEAP_BLOCK Node,
|
||||||
|
@ -547,6 +626,8 @@ RtlpDphRemoveFromFreeList(PDPH_HEAP_ROOT DphRoot,
|
||||||
{
|
{
|
||||||
PDPH_HEAP_BLOCK Next;
|
PDPH_HEAP_BLOCK Next;
|
||||||
|
|
||||||
|
DPRINT("RtlpDphRemoveFromFreeList(%p %p %p)\n", DphRoot, Node, Prev);
|
||||||
|
|
||||||
/* Detach it from the list */
|
/* Detach it from the list */
|
||||||
Next = Node->pNextAlloc;
|
Next = Node->pNextAlloc;
|
||||||
if (DphRoot->pFreeAllocationListHead == Node)
|
if (DphRoot->pFreeAllocationListHead == Node)
|
||||||
|
@ -578,12 +659,13 @@ RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
||||||
|
|
||||||
/* Find where to put this node according to its virtual address */
|
/* Find where to put this node according to its virtual address */
|
||||||
AvailListHead = &DphRoot->AvailableAllocationHead;
|
AvailListHead = &DphRoot->AvailableAllocationHead;
|
||||||
|
|
||||||
|
/* Find a point where to insert an available node */
|
||||||
CurEntry = AvailListHead->Flink;
|
CurEntry = AvailListHead->Flink;
|
||||||
|
|
||||||
while (CurEntry != AvailListHead)
|
while (CurEntry != AvailListHead)
|
||||||
{
|
{
|
||||||
NodeEntry = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
|
NodeEntry = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
|
||||||
|
|
||||||
if (NodeEntry->pVirtualBlock >= Node->pVirtualBlock)
|
if (NodeEntry->pVirtualBlock >= Node->pVirtualBlock)
|
||||||
{
|
{
|
||||||
PrevNode = NodeEntry;
|
PrevNode = NodeEntry;
|
||||||
|
@ -592,10 +674,9 @@ RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
||||||
CurEntry = CurEntry->Flink;
|
CurEntry = CurEntry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Did we find a node to insert our one after? */
|
|
||||||
if (!PrevNode)
|
if (!PrevNode)
|
||||||
{
|
{
|
||||||
/* No, just add to the head of the list then */
|
/* That means either this list is empty, or we should add to the head of it */
|
||||||
InsertHeadList(AvailListHead, &Node->AvailableEntry);
|
InsertHeadList(AvailListHead, &Node->AvailableEntry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -615,20 +696,22 @@ RtlpDphCoalesceNodeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
||||||
/* Insert after PrevNode */
|
/* Insert after PrevNode */
|
||||||
InsertTailList(&PrevNode->AvailableEntry, &Node->AvailableEntry);
|
InsertTailList(&PrevNode->AvailableEntry, &Node->AvailableEntry);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Now check the next entry after our one */
|
/* Now check the next entry after our one */
|
||||||
if (Node->AvailableEntry.Flink != AvailListHead)
|
if (Node->AvailableEntry.Flink != AvailListHead)
|
||||||
{
|
|
||||||
NextNode = CONTAINING_RECORD(Node->AvailableEntry.Flink, DPH_HEAP_BLOCK, AvailableEntry);;
|
|
||||||
/* Node is not at the tail of the list, check if it's adjacent */
|
|
||||||
if (Node->pVirtualBlock + Node->nVirtualBlockSize == NextNode->pVirtualBlock)
|
|
||||||
{
|
{
|
||||||
/* They are adjacent - merge! */
|
NextNode = CONTAINING_RECORD(Node->AvailableEntry.Flink, DPH_HEAP_BLOCK, AvailableEntry);
|
||||||
Node->nVirtualBlockSize += NextNode->nVirtualBlockSize;
|
/* Node is not at the tail of the list, check if it's adjacent */
|
||||||
Node->pNextAlloc = NextNode->pNextAlloc;
|
if (Node->pVirtualBlock + Node->nVirtualBlockSize == NextNode->pVirtualBlock)
|
||||||
RtlpDphReturnNodeToUnusedList(DphRoot, NextNode);
|
{
|
||||||
DphRoot->nAvailableAllocations--;
|
/* They are adjacent - merge! */
|
||||||
|
Node->nVirtualBlockSize += NextNode->nVirtualBlockSize;
|
||||||
|
|
||||||
|
/* Remove next entry from the list and put it into unused entries list */
|
||||||
|
RemoveEntryList(&NextNode->AvailableEntry);
|
||||||
|
RtlpDphReturnNodeToUnusedList(DphRoot, NextNode);
|
||||||
|
DphRoot->nAvailableAllocations--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -643,10 +726,12 @@ RtlpDphCoalesceFreeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
||||||
/* Make sure requested size is not too big */
|
/* Make sure requested size is not too big */
|
||||||
ASSERT(FreeAllocations >= LeaveOnFreeList);
|
ASSERT(FreeAllocations >= LeaveOnFreeList);
|
||||||
|
|
||||||
|
DPRINT("RtlpDphCoalesceFreeIntoAvailable(%p %d)\n", DphRoot, LeaveOnFreeList);
|
||||||
|
|
||||||
while (Node)
|
while (Node)
|
||||||
{
|
{
|
||||||
FreeAllocations--;
|
FreeAllocations--;
|
||||||
if (FreeAllocations <= LeaveOnFreeList) break;
|
if (FreeAllocations < LeaveOnFreeList) break;
|
||||||
|
|
||||||
/* Get the next pointer, because it may be changed after following two calls */
|
/* Get the next pointer, because it may be changed after following two calls */
|
||||||
Next = Node->pNextAlloc;
|
Next = Node->pNextAlloc;
|
||||||
|
@ -657,6 +742,7 @@ RtlpDphCoalesceFreeIntoAvailable(PDPH_HEAP_ROOT DphRoot,
|
||||||
/* And put into the available */
|
/* And put into the available */
|
||||||
RtlpDphCoalesceNodeIntoAvailable(DphRoot, Node);
|
RtlpDphCoalesceNodeIntoAvailable(DphRoot, Node);
|
||||||
|
|
||||||
|
/* Go to the next node */
|
||||||
Node = Next;
|
Node = Next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,20 +799,21 @@ RtlpDphSearchAvailableMemoryListForBestFit(PDPH_HEAP_ROOT DphRoot,
|
||||||
SIZE_T Size)
|
SIZE_T Size)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY CurEntry;
|
PLIST_ENTRY CurEntry;
|
||||||
PDPH_HEAP_BLOCK Node;
|
PDPH_HEAP_BLOCK Node, NodeFound = NULL;
|
||||||
|
|
||||||
CurEntry = DphRoot->AvailableAllocationHead.Flink;
|
CurEntry = DphRoot->AvailableAllocationHead.Flink;
|
||||||
|
|
||||||
while (TRUE)
|
while (CurEntry != &DphRoot->AvailableAllocationHead)
|
||||||
{
|
{
|
||||||
/* If we reached end of the list - return right away */
|
|
||||||
if (CurEntry == &DphRoot->AvailableAllocationHead) return NULL;
|
|
||||||
|
|
||||||
/* Get the current available node */
|
/* Get the current available node */
|
||||||
Node = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
|
Node = CONTAINING_RECORD(CurEntry, DPH_HEAP_BLOCK, AvailableEntry);
|
||||||
|
|
||||||
/* Check its size */
|
/* Check its size */
|
||||||
if (Node->nVirtualBlockSize >= Size) break;
|
if (Node->nVirtualBlockSize >= Size)
|
||||||
|
{
|
||||||
|
NodeFound = Node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Move to the next available entry */
|
/* Move to the next available entry */
|
||||||
CurEntry = CurEntry->Flink;
|
CurEntry = CurEntry->Flink;
|
||||||
|
@ -736,7 +823,7 @@ RtlpDphSearchAvailableMemoryListForBestFit(PDPH_HEAP_ROOT DphRoot,
|
||||||
//ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Flink));
|
//ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Flink));
|
||||||
//ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Blink));
|
//ASSERT(IS_BIASED_POINTER(Node->AdjacencyEntry.Blink));
|
||||||
|
|
||||||
return Node;
|
return NodeFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDPH_HEAP_BLOCK NTAPI
|
PDPH_HEAP_BLOCK NTAPI
|
||||||
|
@ -757,7 +844,7 @@ RtlpDphFindAvailableMemory(PDPH_HEAP_ROOT DphRoot,
|
||||||
if (DphRoot->nFreeAllocations <= DPH_FREE_LIST_MINIMUM) break;
|
if (DphRoot->nFreeAllocations <= DPH_FREE_LIST_MINIMUM) break;
|
||||||
|
|
||||||
/* Calculate a new free list size */
|
/* Calculate a new free list size */
|
||||||
NewSize = DphRoot->nFreeAllocations >> 1;
|
NewSize = DphRoot->nFreeAllocations >> 2;
|
||||||
if (NewSize < DPH_FREE_LIST_MINIMUM) NewSize = DPH_FREE_LIST_MINIMUM;
|
if (NewSize < DPH_FREE_LIST_MINIMUM) NewSize = DPH_FREE_LIST_MINIMUM;
|
||||||
|
|
||||||
/* Coalesce free into available */
|
/* Coalesce free into available */
|
||||||
|
@ -795,6 +882,23 @@ RtlpDphFindAvailableMemory(PDPH_HEAP_ROOT DphRoot,
|
||||||
return Node;
|
return Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDPH_HEAP_BLOCK NTAPI
|
||||||
|
RtlpDphFindBusyMemory(PDPH_HEAP_ROOT DphRoot,
|
||||||
|
PVOID pUserMem)
|
||||||
|
{
|
||||||
|
PDPH_HEAP_BLOCK Node;
|
||||||
|
PVOID Ptr;
|
||||||
|
|
||||||
|
/* Lookup busy block in AVL */
|
||||||
|
Ptr = RtlLookupElementGenericTableAvl(&DphRoot->BusyNodesTable, &pUserMem);
|
||||||
|
if (!Ptr) return NULL;
|
||||||
|
|
||||||
|
/* Restore pointer to the heap block */
|
||||||
|
Node = CONTAINING_RECORD(Ptr, DPH_HEAP_BLOCK, pUserAllocation);
|
||||||
|
ASSERT(Node->pUserAllocation == pUserMem);
|
||||||
|
return Node;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
RtlpDphSetProtectionBeforeUse(PDPH_HEAP_ROOT DphRoot, PUCHAR VirtualBlock, ULONG UserSize)
|
RtlpDphSetProtectionBeforeUse(PDPH_HEAP_ROOT DphRoot, PUCHAR VirtualBlock, ULONG UserSize)
|
||||||
{
|
{
|
||||||
|
@ -817,6 +921,20 @@ RtlpDphSetProtectionBeforeUse(PDPH_HEAP_ROOT DphRoot, PUCHAR VirtualBlock, ULONG
|
||||||
return RtlpDphProtectVm(Base, UserSize, Protection);
|
return RtlpDphProtectVm(Base, UserSize, Protection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
RtlpDphSetProtectionAfterUse(PDPH_HEAP_ROOT DphRoot, /*PUCHAR VirtualBlock*/PDPH_HEAP_BLOCK Node)
|
||||||
|
{
|
||||||
|
// FIXME: Bring stuff here
|
||||||
|
if (DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
PDPH_HEAP_BLOCK NTAPI
|
PDPH_HEAP_BLOCK NTAPI
|
||||||
RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
|
RtlpDphAllocateNode(PDPH_HEAP_ROOT DphRoot)
|
||||||
{
|
{
|
||||||
|
@ -1685,8 +1803,91 @@ RtlpPageHeapFree(HANDLE HeapPtr,
|
||||||
ULONG Flags,
|
ULONG Flags,
|
||||||
PVOID Ptr)
|
PVOID Ptr)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
PDPH_HEAP_ROOT DphRoot;
|
||||||
return FALSE;
|
PDPH_HEAP_BLOCK Node;
|
||||||
|
ULONG ValidationInfo;
|
||||||
|
PDPH_BLOCK_INFORMATION Info;
|
||||||
|
|
||||||
|
/* Check for a NULL pointer freeing */
|
||||||
|
if (!HeapPtr)
|
||||||
|
{
|
||||||
|
if (RtlpDphBreakOptions & DPH_BREAK_ON_NULL_FREE)
|
||||||
|
{
|
||||||
|
DPRINT1("Page heap: freeing a null pointer \n");
|
||||||
|
DbgBreakPoint();
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a pointer to the heap root */
|
||||||
|
DphRoot = RtlpDphPointerFromHandle(HeapPtr);
|
||||||
|
if (!DphRoot) return FALSE;
|
||||||
|
|
||||||
|
/* Acquire the heap lock */
|
||||||
|
RtlpDphPreProcessing(DphRoot, Flags);
|
||||||
|
|
||||||
|
/* Perform internal validation if specified by flags */
|
||||||
|
if (RtlpDphDebugOptions & DPH_DEBUG_INTERNAL_VALIDATE)
|
||||||
|
RtlpDphInternalValidatePageHeap(DphRoot, NULL, 0);
|
||||||
|
|
||||||
|
/* Add heap flags */
|
||||||
|
Flags |= DphRoot->HeapFlags;
|
||||||
|
|
||||||
|
/* Find busy memory */
|
||||||
|
Node = RtlpDphFindBusyMemory(DphRoot, Ptr);
|
||||||
|
|
||||||
|
if (!Node)
|
||||||
|
{
|
||||||
|
/* This block was not found in page heap, try a normal heap instead */
|
||||||
|
//RtlpDphNormalHeapFree();
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
|
||||||
|
{
|
||||||
|
/* Check and report corrupted block */
|
||||||
|
if (!RtlpDphIsPageHeapBlock(DphRoot, Ptr, &ValidationInfo, TRUE))
|
||||||
|
{
|
||||||
|
RtlpDphReportCorruptedBlock(DphRoot, 1, Ptr, ValidationInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Should go inside RtlpDphSetProtectionAfterUse
|
||||||
|
if (Node->nVirtualAccessSize != 0)
|
||||||
|
{
|
||||||
|
/* Set stamps */
|
||||||
|
Info = (PDPH_BLOCK_INFORMATION)Node->pUserAllocation - 1;
|
||||||
|
Info->StartStamp = DPH_FILL_START_STAMP_2;
|
||||||
|
Info->EndStamp = DPH_FILL_END_STAMP_2;
|
||||||
|
|
||||||
|
RtlpDphProtectVm(Node->pVirtualBlock, Node->nVirtualAccessSize, PAGE_NOACCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FIXME: Should go inside RtlpDphSetProtectionAfterUse
|
||||||
|
if (Node->nVirtualAccessSize != 0)
|
||||||
|
RtlpDphProtectVm(Node->pVirtualBlock + PAGE_SIZE, Node->nVirtualAccessSize, PAGE_NOACCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set new protection */
|
||||||
|
RtlpDphSetProtectionAfterUse(DphRoot, Node);
|
||||||
|
|
||||||
|
/* Remove it from the list of busy nodes */
|
||||||
|
RtlpDphRemoveFromBusyList(DphRoot, Node);
|
||||||
|
|
||||||
|
/* And put it into the list of free nodes */
|
||||||
|
RtlpDphPlaceOnFreeList(DphRoot, Node);
|
||||||
|
|
||||||
|
//if (DphRoot->ExtraFlags & DPH_EXTRA_LOG_STACK_TRACES)
|
||||||
|
// Node->StackTrace = RtlpDphLogStackTrace(3);
|
||||||
|
//else
|
||||||
|
Node->StackTrace = NULL;
|
||||||
|
|
||||||
|
/* Leave the heap lock */
|
||||||
|
RtlpDphPostProcessing(DphRoot);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVOID NTAPI
|
PVOID NTAPI
|
||||||
|
|
Loading…
Reference in a new issue