windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/dbgext/enumheap.cxx
2020-09-26 16:20:57 +08:00

485 lines
9.4 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1995-1999 Microsoft Corporation
Module Name:
enumheap.cxx
Abstract:
This module implements a heap enumerator.
Author:
Keith Moore (keithmo) 31-Oct-1997
Revision History:
--*/
#include "inetdbgp.h"
BOOLEAN
EnumProcessHeaps(
IN PFN_ENUMHEAPS EnumProc,
IN PVOID Param
)
/*++
Routine Description:
Enumerates all heaps in the debugee.
Arguments:
EnumProc - An enumeration proc that will be invoked for each heap.
Param - An uninterpreted parameter passed to the enumeration proc.
Return Value:
BOOLEAN - TRUE if successful, FALSE otherwise.
--*/
{
BOOLEAN result = FALSE;
PROCESS_BASIC_INFORMATION basicInfo;
NTSTATUS status;
PVOID * heapList;
ULONG numHeaps;
ULONG i;
PEB peb;
HEAP heap;
//
// Setup locals so we know how to cleanup on exit.
//
heapList = NULL;
//
// Get the process info.
//
status = NtQueryInformationProcess(
ExtensionCurrentProcess,
ProcessBasicInformation,
&basicInfo,
sizeof(basicInfo),
NULL
);
if( !NT_SUCCESS(status) ) {
goto cleanup;
}
if( !ReadMemory(
(ULONG_PTR)basicInfo.PebBaseAddress,
&peb,
sizeof(peb),
NULL
) ) {
goto cleanup;
}
//
// Allocate an array for the heap pointers, then read them from
// the debugee.
//
numHeaps = peb.NumberOfHeaps;
heapList = (PVOID *)malloc( numHeaps * sizeof(PVOID) );
if( heapList == NULL ) {
goto cleanup;
}
if( !ReadMemory(
(ULONG_PTR)peb.ProcessHeaps,
heapList,
numHeaps * sizeof(PVOID),
NULL
) ) {
goto cleanup;
}
//
// Now that we have the heap list, we can scan it and invoke the
// enum proc.
//
for( i = 0 ; i < numHeaps ; i++ ) {
if( CheckControlC() ) {
goto cleanup;
}
if( !ReadMemory(
(ULONG_PTR)heapList[i],
&heap,
sizeof(heap),
NULL
) ) {
goto cleanup;
}
if( heap.Signature != HEAP_SIGNATURE ) {
dprintf(
"Heap @ %08lp has invalid signature %08lx\n",
heapList[i],
heap.Signature
);
goto cleanup;
}
if( !EnumProc(
Param,
&heap,
(PHEAP)heapList[i],
i
) ) {
break;
}
}
//
// Success!
//
result = TRUE;
cleanup:
if( heapList != NULL ) {
free( heapList );
}
return result;
} // EnumProcessHeaps
BOOLEAN
EnumHeapSegments(
IN PHEAP LocalHeap,
IN PHEAP RemoteHeap,
IN PFN_ENUMHEAPSEGMENTS EnumProc,
IN PVOID Param
)
/*++
Routine Description:
Enumerates all heap segments within a heap.
Arguments:
LocalHeap - Pointer to a local copy of the HEAP to enumerate.
RemoteHeap - The actual address of the heap in the debugee.
EnumProc - An enumeration proc that will be invoked for each heap
segment.
Param - An uninterpreted parameter passed to the enumeration proc.
Return Value:
BOOLEAN - TRUE if successful, FALSE otherwise.
--*/
{
BOOLEAN result = FALSE;
ULONG i;
HEAP_SEGMENT heapSegment;
//
// Scan the segments.
//
for( i = 0 ; i < HEAP_MAXIMUM_SEGMENTS ; i++ ) {
if( CheckControlC() ) {
goto cleanup;
}
if( LocalHeap->Segments[i] != NULL ) {
//
// Read the segment, invoke the enumeration proc.
//
if( !ReadMemory(
(ULONG_PTR)LocalHeap->Segments[i],
&heapSegment,
sizeof(heapSegment),
NULL
) ) {
goto cleanup;
}
if( heapSegment.Signature != HEAP_SEGMENT_SIGNATURE ) {
dprintf(
"HeapSegment @ %08lp has invalid signature %08lx\n",
LocalHeap->Segments[i],
heapSegment.Signature
);
goto cleanup;
}
if( !EnumProc(
Param,
&heapSegment,
LocalHeap->Segments[i],
i
) ) {
break;
}
}
}
result = TRUE;
cleanup:
return result;
} // EnumHeapSegments
BOOLEAN
EnumHeapSegmentEntries(
IN PHEAP_SEGMENT LocalHeapSegment,
IN PHEAP_SEGMENT RemoteHeapSegment,
IN PFN_ENUMHEAPSEGMENTENTRIES EnumProc,
IN PVOID Param
)
/*++
Routine Description:
Enumerates all heap entries in a heap segment.
Arguments:
LocalHeapSegment - Pointer to a local copy of the HEAP_SEGMENT to
enumerate.
RemoteHeapSegment - The actual address of hte heap segment in the
debugee.
EnumProc - An enumeration proc that will be invoked for each heap
segment.
Param - An uninterpreted parameter passed to the enumeration proc.
Return Value:
BOOLEAN - TRUE if successful, FALSE otherwise.
--*/
{
BOOLEAN result = FALSE;
PHEAP_ENTRY lastHeapEntry;
PHEAP_ENTRY remoteHeapEntry;
HEAP_ENTRY localHeapEntry;
PHEAP_UNCOMMMTTED_RANGE remoteUCR;
HEAP_UNCOMMMTTED_RANGE localUCR;
//
// Snag the beginning & ending limits of this segment.
//
remoteHeapEntry = LocalHeapSegment->FirstEntry;
lastHeapEntry = LocalHeapSegment->LastValidEntry;
//
// If this segment has one or more uncommitted ranges, then
// read the first one.
//
remoteUCR = LocalHeapSegment->UnCommittedRanges;
if( remoteUCR != NULL ) {
if( !ReadMemory(
(ULONG_PTR)remoteUCR,
&localUCR,
sizeof(localUCR),
NULL
) ) {
goto cleanup;
}
}
//
// Scan the entries.
//
while( remoteHeapEntry < lastHeapEntry ) {
if( CheckControlC() ) {
goto cleanup;
}
//
// Read the heap entry, invoke the enumeration proc.
//
if( !ReadMemory(
(ULONG_PTR)remoteHeapEntry,
&localHeapEntry,
sizeof(localHeapEntry),
NULL
) ) {
goto cleanup;
}
if( !EnumProc(
Param,
&localHeapEntry,
remoteHeapEntry
) ) {
break;
}
//
// Advance to the next entry.
//
remoteHeapEntry = (PHEAP_ENTRY)( (PUCHAR)remoteHeapEntry +
( localHeapEntry.Size << HEAP_GRANULARITY_SHIFT ) );
//
// If this is the last entry in this run, then we'll need
// some special handling to skip over the uncommitted ranges
// (if any).
//
if( localHeapEntry.Flags & HEAP_ENTRY_LAST_ENTRY ) {
if( remoteUCR == NULL ) {
break;
}
//
// Skip the uncommitted range, then read the next uncommitted
// range descriptor if available.
//
remoteHeapEntry = (PHEAP_ENTRY)( (PUCHAR)remoteHeapEntry +
localUCR.Size );
remoteUCR = localUCR.Next;
if( remoteUCR != NULL ) {
if( !ReadMemory(
(ULONG_PTR)remoteUCR,
&localUCR,
sizeof(localUCR),
NULL
) ) {
goto cleanup;
}
}
}
}
result = TRUE;
cleanup:
return result;
} // EnumHeapSegmentEntries
BOOLEAN
EnumHeapFreeLists(
IN PHEAP LocalHeap,
IN PHEAP RemoteHeap,
IN PFN_ENUMHEAPFREELISTS EnumProc,
IN PVOID Param
)
{
BOOLEAN result = FALSE;
ULONG i;
PLIST_ENTRY nextEntry;
PHEAP_FREE_ENTRY remoteFreeHeapEntry;
HEAP_FREE_ENTRY localFreeHeapEntry;
//
// Scan the free lists.
//
for( i = 0 ; i < HEAP_MAXIMUM_FREELISTS ; i++ ) {
if( CheckControlC() ) {
goto cleanup;
}
nextEntry = LocalHeap->FreeLists[i].Flink;
while( nextEntry != &RemoteHeap->FreeLists[i] ) {
if( CheckControlC() ) {
goto cleanup;
}
remoteFreeHeapEntry = CONTAINING_RECORD(
nextEntry,
HEAP_FREE_ENTRY,
FreeList
);
//
// Read the heap entry, invoke the enumerator.
//
if( !ReadMemory(
(ULONG_PTR)remoteFreeHeapEntry,
&localFreeHeapEntry,
sizeof(localFreeHeapEntry),
NULL
) ) {
goto cleanup;
}
if( !EnumProc(
Param,
&localFreeHeapEntry,
remoteFreeHeapEntry
) ) {
break;
}
}
}
result = TRUE;
cleanup:
return result;
} // EnumHeapFreeLists