Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

484 lines
9.4 KiB

  1. /*++
  2. Copyright (c) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. enumheap.cxx
  5. Abstract:
  6. This module implements a heap enumerator.
  7. Author:
  8. Keith Moore (keithmo) 31-Oct-1997
  9. Revision History:
  10. --*/
  11. #include "inetdbgp.h"
  12. BOOLEAN
  13. EnumProcessHeaps(
  14. IN PFN_ENUMHEAPS EnumProc,
  15. IN PVOID Param
  16. )
  17. /*++
  18. Routine Description:
  19. Enumerates all heaps in the debugee.
  20. Arguments:
  21. EnumProc - An enumeration proc that will be invoked for each heap.
  22. Param - An uninterpreted parameter passed to the enumeration proc.
  23. Return Value:
  24. BOOLEAN - TRUE if successful, FALSE otherwise.
  25. --*/
  26. {
  27. BOOLEAN result = FALSE;
  28. PROCESS_BASIC_INFORMATION basicInfo;
  29. NTSTATUS status;
  30. PVOID * heapList;
  31. ULONG numHeaps;
  32. ULONG i;
  33. PEB peb;
  34. HEAP heap;
  35. //
  36. // Setup locals so we know how to cleanup on exit.
  37. //
  38. heapList = NULL;
  39. //
  40. // Get the process info.
  41. //
  42. status = NtQueryInformationProcess(
  43. ExtensionCurrentProcess,
  44. ProcessBasicInformation,
  45. &basicInfo,
  46. sizeof(basicInfo),
  47. NULL
  48. );
  49. if( !NT_SUCCESS(status) ) {
  50. goto cleanup;
  51. }
  52. if( !ReadMemory(
  53. (ULONG_PTR)basicInfo.PebBaseAddress,
  54. &peb,
  55. sizeof(peb),
  56. NULL
  57. ) ) {
  58. goto cleanup;
  59. }
  60. //
  61. // Allocate an array for the heap pointers, then read them from
  62. // the debugee.
  63. //
  64. numHeaps = peb.NumberOfHeaps;
  65. heapList = (PVOID *)malloc( numHeaps * sizeof(PVOID) );
  66. if( heapList == NULL ) {
  67. goto cleanup;
  68. }
  69. if( !ReadMemory(
  70. (ULONG_PTR)peb.ProcessHeaps,
  71. heapList,
  72. numHeaps * sizeof(PVOID),
  73. NULL
  74. ) ) {
  75. goto cleanup;
  76. }
  77. //
  78. // Now that we have the heap list, we can scan it and invoke the
  79. // enum proc.
  80. //
  81. for( i = 0 ; i < numHeaps ; i++ ) {
  82. if( CheckControlC() ) {
  83. goto cleanup;
  84. }
  85. if( !ReadMemory(
  86. (ULONG_PTR)heapList[i],
  87. &heap,
  88. sizeof(heap),
  89. NULL
  90. ) ) {
  91. goto cleanup;
  92. }
  93. if( heap.Signature != HEAP_SIGNATURE ) {
  94. dprintf(
  95. "Heap @ %08lp has invalid signature %08lx\n",
  96. heapList[i],
  97. heap.Signature
  98. );
  99. goto cleanup;
  100. }
  101. if( !EnumProc(
  102. Param,
  103. &heap,
  104. (PHEAP)heapList[i],
  105. i
  106. ) ) {
  107. break;
  108. }
  109. }
  110. //
  111. // Success!
  112. //
  113. result = TRUE;
  114. cleanup:
  115. if( heapList != NULL ) {
  116. free( heapList );
  117. }
  118. return result;
  119. } // EnumProcessHeaps
  120. BOOLEAN
  121. EnumHeapSegments(
  122. IN PHEAP LocalHeap,
  123. IN PHEAP RemoteHeap,
  124. IN PFN_ENUMHEAPSEGMENTS EnumProc,
  125. IN PVOID Param
  126. )
  127. /*++
  128. Routine Description:
  129. Enumerates all heap segments within a heap.
  130. Arguments:
  131. LocalHeap - Pointer to a local copy of the HEAP to enumerate.
  132. RemoteHeap - The actual address of the heap in the debugee.
  133. EnumProc - An enumeration proc that will be invoked for each heap
  134. segment.
  135. Param - An uninterpreted parameter passed to the enumeration proc.
  136. Return Value:
  137. BOOLEAN - TRUE if successful, FALSE otherwise.
  138. --*/
  139. {
  140. BOOLEAN result = FALSE;
  141. ULONG i;
  142. HEAP_SEGMENT heapSegment;
  143. //
  144. // Scan the segments.
  145. //
  146. for( i = 0 ; i < HEAP_MAXIMUM_SEGMENTS ; i++ ) {
  147. if( CheckControlC() ) {
  148. goto cleanup;
  149. }
  150. if( LocalHeap->Segments[i] != NULL ) {
  151. //
  152. // Read the segment, invoke the enumeration proc.
  153. //
  154. if( !ReadMemory(
  155. (ULONG_PTR)LocalHeap->Segments[i],
  156. &heapSegment,
  157. sizeof(heapSegment),
  158. NULL
  159. ) ) {
  160. goto cleanup;
  161. }
  162. if( heapSegment.Signature != HEAP_SEGMENT_SIGNATURE ) {
  163. dprintf(
  164. "HeapSegment @ %08lp has invalid signature %08lx\n",
  165. LocalHeap->Segments[i],
  166. heapSegment.Signature
  167. );
  168. goto cleanup;
  169. }
  170. if( !EnumProc(
  171. Param,
  172. &heapSegment,
  173. LocalHeap->Segments[i],
  174. i
  175. ) ) {
  176. break;
  177. }
  178. }
  179. }
  180. result = TRUE;
  181. cleanup:
  182. return result;
  183. } // EnumHeapSegments
  184. BOOLEAN
  185. EnumHeapSegmentEntries(
  186. IN PHEAP_SEGMENT LocalHeapSegment,
  187. IN PHEAP_SEGMENT RemoteHeapSegment,
  188. IN PFN_ENUMHEAPSEGMENTENTRIES EnumProc,
  189. IN PVOID Param
  190. )
  191. /*++
  192. Routine Description:
  193. Enumerates all heap entries in a heap segment.
  194. Arguments:
  195. LocalHeapSegment - Pointer to a local copy of the HEAP_SEGMENT to
  196. enumerate.
  197. RemoteHeapSegment - The actual address of hte heap segment in the
  198. debugee.
  199. EnumProc - An enumeration proc that will be invoked for each heap
  200. segment.
  201. Param - An uninterpreted parameter passed to the enumeration proc.
  202. Return Value:
  203. BOOLEAN - TRUE if successful, FALSE otherwise.
  204. --*/
  205. {
  206. BOOLEAN result = FALSE;
  207. PHEAP_ENTRY lastHeapEntry;
  208. PHEAP_ENTRY remoteHeapEntry;
  209. HEAP_ENTRY localHeapEntry;
  210. PHEAP_UNCOMMMTTED_RANGE remoteUCR;
  211. HEAP_UNCOMMMTTED_RANGE localUCR;
  212. //
  213. // Snag the beginning & ending limits of this segment.
  214. //
  215. remoteHeapEntry = LocalHeapSegment->FirstEntry;
  216. lastHeapEntry = LocalHeapSegment->LastValidEntry;
  217. //
  218. // If this segment has one or more uncommitted ranges, then
  219. // read the first one.
  220. //
  221. remoteUCR = LocalHeapSegment->UnCommittedRanges;
  222. if( remoteUCR != NULL ) {
  223. if( !ReadMemory(
  224. (ULONG_PTR)remoteUCR,
  225. &localUCR,
  226. sizeof(localUCR),
  227. NULL
  228. ) ) {
  229. goto cleanup;
  230. }
  231. }
  232. //
  233. // Scan the entries.
  234. //
  235. while( remoteHeapEntry < lastHeapEntry ) {
  236. if( CheckControlC() ) {
  237. goto cleanup;
  238. }
  239. //
  240. // Read the heap entry, invoke the enumeration proc.
  241. //
  242. if( !ReadMemory(
  243. (ULONG_PTR)remoteHeapEntry,
  244. &localHeapEntry,
  245. sizeof(localHeapEntry),
  246. NULL
  247. ) ) {
  248. goto cleanup;
  249. }
  250. if( !EnumProc(
  251. Param,
  252. &localHeapEntry,
  253. remoteHeapEntry
  254. ) ) {
  255. break;
  256. }
  257. //
  258. // Advance to the next entry.
  259. //
  260. remoteHeapEntry = (PHEAP_ENTRY)( (PUCHAR)remoteHeapEntry +
  261. ( localHeapEntry.Size << HEAP_GRANULARITY_SHIFT ) );
  262. //
  263. // If this is the last entry in this run, then we'll need
  264. // some special handling to skip over the uncommitted ranges
  265. // (if any).
  266. //
  267. if( localHeapEntry.Flags & HEAP_ENTRY_LAST_ENTRY ) {
  268. if( remoteUCR == NULL ) {
  269. break;
  270. }
  271. //
  272. // Skip the uncommitted range, then read the next uncommitted
  273. // range descriptor if available.
  274. //
  275. remoteHeapEntry = (PHEAP_ENTRY)( (PUCHAR)remoteHeapEntry +
  276. localUCR.Size );
  277. remoteUCR = localUCR.Next;
  278. if( remoteUCR != NULL ) {
  279. if( !ReadMemory(
  280. (ULONG_PTR)remoteUCR,
  281. &localUCR,
  282. sizeof(localUCR),
  283. NULL
  284. ) ) {
  285. goto cleanup;
  286. }
  287. }
  288. }
  289. }
  290. result = TRUE;
  291. cleanup:
  292. return result;
  293. } // EnumHeapSegmentEntries
  294. BOOLEAN
  295. EnumHeapFreeLists(
  296. IN PHEAP LocalHeap,
  297. IN PHEAP RemoteHeap,
  298. IN PFN_ENUMHEAPFREELISTS EnumProc,
  299. IN PVOID Param
  300. )
  301. {
  302. BOOLEAN result = FALSE;
  303. ULONG i;
  304. PLIST_ENTRY nextEntry;
  305. PHEAP_FREE_ENTRY remoteFreeHeapEntry;
  306. HEAP_FREE_ENTRY localFreeHeapEntry;
  307. //
  308. // Scan the free lists.
  309. //
  310. for( i = 0 ; i < HEAP_MAXIMUM_FREELISTS ; i++ ) {
  311. if( CheckControlC() ) {
  312. goto cleanup;
  313. }
  314. nextEntry = LocalHeap->FreeLists[i].Flink;
  315. while( nextEntry != &RemoteHeap->FreeLists[i] ) {
  316. if( CheckControlC() ) {
  317. goto cleanup;
  318. }
  319. remoteFreeHeapEntry = CONTAINING_RECORD(
  320. nextEntry,
  321. HEAP_FREE_ENTRY,
  322. FreeList
  323. );
  324. //
  325. // Read the heap entry, invoke the enumerator.
  326. //
  327. if( !ReadMemory(
  328. (ULONG_PTR)remoteFreeHeapEntry,
  329. &localFreeHeapEntry,
  330. sizeof(localFreeHeapEntry),
  331. NULL
  332. ) ) {
  333. goto cleanup;
  334. }
  335. if( !EnumProc(
  336. Param,
  337. &localFreeHeapEntry,
  338. remoteFreeHeapEntry
  339. ) ) {
  340. break;
  341. }
  342. }
  343. }
  344. result = TRUE;
  345. cleanup:
  346. return result;
  347. } // EnumHeapFreeLists