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.

316 lines
6.5 KiB

  1. /***
  2. *heapwalk.c - walk the heap
  3. *
  4. * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Defines the _heapwalk() function
  8. *
  9. *Revision History:
  10. * 07-05-89 JCR Module created.
  11. * 11-13-89 GJF Added MTHREAD support, also fixed copyright.
  12. * 11-14-89 JCR Fixed bug -- returned address was off by HDRSIZE
  13. * 12-18-89 GJF Removed DEBUG286 stuff, also some tuning, cleaned up
  14. * format a bit, changed header file name to heap.h, added
  15. * explicit _cdecl to function definition
  16. * 12-20-89 GJF Removed references to plastdesc
  17. * 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
  18. * <cruntime.h> and removed #include <register.h>.
  19. * 09-28-90 GJF New-style function declarator.
  20. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  21. * 05-01-95 GJF Spliced on winheap version.
  22. * 05-11-95 GJF Added code to detect end-of-heap.
  23. * 05-26-95 GJF Validate _pentry field with HeapValidate call.
  24. * 06-14-95 GJF Fix from Bryan Tuttle to avoid calling HeapValidate
  25. * on unallocated block. Also fixed error return.
  26. * 06-14-95 GJF Better version of above fix.
  27. * 07-18-95 GJF If the HeapWalk() API is not implemented, return
  28. * _HEAPEND instead of _HEAPOK.
  29. *
  30. *******************************************************************************/
  31. #ifdef WINHEAP
  32. #include <cruntime.h>
  33. #include <windows.h>
  34. #include <errno.h>
  35. #include <malloc.h>
  36. #include <mtdll.h>
  37. #include <stddef.h>
  38. #include <stdlib.h>
  39. #include <winheap.h>
  40. #ifndef _POSIX_
  41. /***
  42. *int _heapwalk() - Walk the heap
  43. *
  44. *Purpose:
  45. * Walk the heap returning information on one entry at a time.
  46. *
  47. *Entry:
  48. * struct _heapinfo {
  49. * int * _pentry; heap entry pointer
  50. * size_t size; size of heap entry
  51. * int _useflag; free/inuse flag
  52. * } *entry;
  53. *
  54. *Exit:
  55. * Returns one of the following values:
  56. *
  57. * _HEAPOK - completed okay
  58. * _HEAPEMPTY - heap not initialized
  59. * _HEAPBADPTR - _pentry pointer is bogus
  60. * _HEAPBADBEGIN - can't find initial header info
  61. * _HEAPBADNODE - malformed node somewhere
  62. * _HEAPEND - end of heap successfully reached
  63. *
  64. *Uses:
  65. *
  66. *Exceptions:
  67. *
  68. *******************************************************************************/
  69. int __cdecl _heapwalk (
  70. struct _heapinfo *_entry
  71. )
  72. {
  73. PROCESS_HEAP_ENTRY Entry;
  74. DWORD errval;
  75. int errflag;
  76. int retval = _HEAPOK;
  77. Entry.wFlags = 0;
  78. Entry.iRegionIndex = 0;
  79. if ( (Entry.lpData = _entry->_pentry) == NULL ) {
  80. if ( !HeapWalk( _crtheap, &Entry ) ) {
  81. if ( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED ) {
  82. _doserrno = ERROR_CALL_NOT_IMPLEMENTED;
  83. errno = ENOSYS;
  84. return _HEAPEND;
  85. }
  86. return _HEAPBADBEGIN;
  87. }
  88. }
  89. else {
  90. if ( _entry->_useflag == _USEDENTRY ) {
  91. if ( !HeapValidate( _crtheap, 0, _entry->_pentry ) )
  92. return _HEAPBADNODE;
  93. Entry.wFlags = PROCESS_HEAP_ENTRY_BUSY;
  94. }
  95. nextBlock:
  96. /*
  97. * Guard the HeapWalk call in case we were passed a bad pointer
  98. * to an allegedly free block.
  99. */
  100. __try {
  101. errflag = 0;
  102. if ( !HeapWalk( _crtheap, &Entry ) )
  103. errflag = 1;
  104. }
  105. __except( EXCEPTION_EXECUTE_HANDLER ) {
  106. errflag = 2;
  107. }
  108. /*
  109. * Check errflag to see how HeapWalk fared...
  110. */
  111. if ( errflag == 1 ) {
  112. /*
  113. * HeapWalk returned an error.
  114. */
  115. if ( (errval = GetLastError()) == ERROR_NO_MORE_ITEMS ) {
  116. return _HEAPEND;
  117. }
  118. else if ( errval == ERROR_CALL_NOT_IMPLEMENTED ) {
  119. _doserrno = errval;
  120. errno = ENOSYS;
  121. return _HEAPEND;
  122. }
  123. return _HEAPBADNODE;
  124. }
  125. else if ( errflag == 2 ) {
  126. /*
  127. * Exception occurred during the HeapWalk!
  128. */
  129. return _HEAPBADNODE;
  130. }
  131. }
  132. if ( Entry.wFlags & (PROCESS_HEAP_REGION |
  133. PROCESS_HEAP_UNCOMMITTED_RANGE) )
  134. {
  135. goto nextBlock;
  136. }
  137. _entry->_pentry = Entry.lpData;
  138. _entry->_size = Entry.cbData;
  139. if ( Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY ) {
  140. _entry->_useflag = _USEDENTRY;
  141. }
  142. else {
  143. _entry->_useflag = _FREEENTRY;
  144. }
  145. return( retval );
  146. }
  147. #endif /* !_POSIX_ */
  148. #else /* ndef WINHEAP */
  149. #include <cruntime.h>
  150. #include <heap.h>
  151. #include <malloc.h>
  152. #include <mtdll.h>
  153. #include <stddef.h>
  154. /***
  155. *int _heapwalk() - Walk the heap
  156. *
  157. *Purpose:
  158. * Walk the heap returning information on one entry at a time.
  159. *
  160. *Entry:
  161. * struct _heapinfo {
  162. * int * _pentry; heap entry pointer
  163. * size_t size; size of heap entry
  164. * int _useflag; free/inuse flag
  165. * } *entry;
  166. *
  167. *Exit:
  168. * Returns one of the following values:
  169. *
  170. * _HEAPOK - completed okay
  171. * _HEAPEMPTY - heap not initialized
  172. * _HEAPBADPTR - _pentry pointer is bogus
  173. * _HEAPBADBEGIN - can't find initial header info
  174. * _HEAPBADNODE - malformed node somewhere
  175. * _HEAPEND - end of heap successfully reached
  176. *
  177. *Uses:
  178. *
  179. *Exceptions:
  180. *
  181. *******************************************************************************/
  182. int __cdecl _heapwalk (
  183. struct _heapinfo *_entry
  184. )
  185. {
  186. REG1 _PBLKDESC pdesc;
  187. _PBLKDESC polddesc;
  188. int retval = _HEAPOK;
  189. /*
  190. * Lock the heap
  191. */
  192. _mlock(_HEAP_LOCK);
  193. /*
  194. * Quick header check
  195. */
  196. if ( (_heap_desc.pfirstdesc == NULL) ||
  197. (_heap_desc.proverdesc == NULL) ||
  198. (_heap_desc.sentinel.pnextdesc != NULL) ) {
  199. retval = _HEAPBADBEGIN;
  200. goto done;
  201. }
  202. /*
  203. * Check for an empty heap
  204. */
  205. if ( _heap_desc.pfirstdesc == &_heap_desc.sentinel ) {
  206. retval = _HEAPEMPTY;
  207. goto done;
  208. }
  209. /*
  210. * If _pentry is NULL, return info about the first entry.
  211. * Else, get info about the next entry in the heap.
  212. */
  213. if ( _entry->_pentry == NULL ) {
  214. pdesc = _heap_desc.pfirstdesc;
  215. }
  216. else {
  217. /*
  218. * Find the entry we gave to the user last time around
  219. */
  220. if ( _heap_findaddr( (void *)((char *)(_entry->_pentry) -
  221. _HDRSIZE), &polddesc) != _HEAPFIND_EXACT ) {
  222. retval = _HEAPBADPTR;
  223. goto done;
  224. }
  225. pdesc = polddesc->pnextdesc;
  226. } /* else */
  227. /*
  228. * pdesc = entry to return info about
  229. */
  230. /*
  231. * Skip over dummy entries
  232. */
  233. while ( _IS_DUMMY(pdesc) )
  234. pdesc = pdesc->pnextdesc;
  235. /*
  236. * See if we're at the end of the heap
  237. */
  238. if ( pdesc == &_heap_desc.sentinel ) {
  239. retval = _HEAPEND;
  240. goto done;
  241. }
  242. /*
  243. * Check back pointer (note that pdesc cannot point to a dummy
  244. * descriptor since we have skipped over them)
  245. */
  246. if (!_CHECK_PDESC(pdesc)) {
  247. retval = _HEAPBADPTR;
  248. goto done;
  249. }
  250. /*
  251. * Return info on the next block
  252. */
  253. _entry->_pentry = ( (void *)((char *)_ADDRESS(pdesc) + _HDRSIZE) );
  254. _entry->_size = _BLKSIZE(pdesc);
  255. _entry->_useflag = ( _IS_INUSE(pdesc) ? _USEDENTRY : _FREEENTRY );
  256. /*
  257. * Common return
  258. */
  259. done:
  260. /*
  261. * Release the heap lock
  262. */
  263. _munlock(_HEAP_LOCK);
  264. return(retval);
  265. }
  266. #endif /* WINHEAP */