|
|
/*++
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
|