home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / heapwalk.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  8KB  |  294 lines

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