memmgr.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 26k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  * memmgr.c - Memory manager module.
  3.  */
  4. /*
  5.    The memory manager implementation in this module uses either a private
  6. shared heap (if PRIVATE_HEAP is #defined) or the non-shared process heap (if
  7. PRIVATE_HEAP is not #defined).  Thde debug implementation of this memory
  8. manager keeps track of memory blocks allocated from the heap using a
  9. doubly-linked list of heap element nodes.  Each node describes one allocated
  10. heap element.
  11.    Debug heap elements are allocated with extra space at the beginning and end
  12. of the element.  Prefix and suffix sentinels surround each allocated heap
  13. element.  New heap elements are filled with UNINITIALIZED_BYTE_VALUE.  Freed
  14. heap elements are filled with FREED_BYTE_VALUE.  The new tails of grown heap
  15. elements are filled with UNINITIALIZED_BYTE_VALUE.
  16. */
  17. /* Headers
  18.  **********/
  19. #include "project.h"
  20. #pragma hdrstop
  21. /* Constants
  22.  ************/
  23. #ifdef PRIVATE_HEAP
  24. /* undocumented flag for HeapCreate() from kernel32.h */
  25. #define HEAP_SHARED                 (0x04000000)
  26. /*
  27.  * Set maximum shared heap size used for CreateHeap() to 0 since we don't know
  28.  * how big the heap may get, and we don't want to restrict its size
  29.  * artificially.  BrianSm says this is ok.
  30.  */
  31. #define MAX_SHARED_HEAP_SIZE        (0)
  32. #endif   /* PRIVATE_HEAP */
  33. #ifdef DEBUG
  34. /* heap element byte fill values */
  35. #define UNINITIALIZED_BYTE_VALUE    (0xcc)
  36. #define FREED_BYTE_VALUE            (0xdd)
  37. #endif   /* DEBUG */
  38. /* Macros
  39.  *********/
  40. /* atomic memory management function wrappers for translation */
  41. #ifdef PRIVATE_HEAP
  42. #define GetHeap()                   (Mhheap)
  43. #define MEMALLOCATE(size)           HeapAlloc(GetHeap(), 0, (size))
  44. #define MEMREALLOCATE(pv, size)     HeapReAlloc(GetHeap(), 0, (pv), (size))
  45. #define MEMFREE(pv)                 HeapFree(GetHeap(), 0, (pv))
  46. #define MEMSIZE(pv)                 (DWORD)HeapSize(GetHeap(), 0, (pv))
  47. #else
  48. #define MEMALLOCATE(size)           LocalAlloc(LMEM_FIXED, (size))
  49. #define MEMREALLOCATE(pv, size)     LocalReAlloc((pv), (size), 0)
  50. #define MEMFREE(pv)                 (! LocalFree(pv))
  51. #define MEMSIZE(pv)                 (DWORD)LocalSize(pv)
  52. #endif
  53. /* Types
  54.  ********/
  55. #ifdef DEBUG
  56. /* heap element descriptor structure */
  57. typedef struct _heapelemdesc
  58. {
  59.    TCHAR rgchSize[6];       /* enough for 99,999 lines */
  60.    TCHAR rgchFile[24];      
  61.    ULONG ulLine;
  62. }
  63. HEAPELEMDESC;
  64. DECLARE_STANDARD_TYPES(HEAPELEMDESC);
  65. /* heap node */
  66. typedef struct _heapnode
  67. {
  68.    PCVOID pcv;
  69.    DWORD dwcbSize;
  70.    struct _heapnode *phnPrev;
  71.    struct _heapnode *phnNext;
  72.    HEAPELEMDESC hed;
  73. }
  74. HEAPNODE;
  75. DECLARE_STANDARD_TYPES(HEAPNODE);
  76. /* heap */
  77. typedef struct _heap
  78. {
  79.    HEAPNODE hnHead;
  80. }
  81. HEAP;
  82. DECLARE_STANDARD_TYPES(HEAP);
  83. /* heap summary filled in by AnalyzeHeap() */
  84. typedef struct _heapsummary
  85. {
  86.    ULONG ulcUsedElements;
  87.    DWORD dwcbUsedSize;
  88. }
  89. HEAPSUMMARY;
  90. DECLARE_STANDARD_TYPES(HEAPSUMMARY);
  91. /* debug flags */
  92. typedef enum _memmgrdebugflags
  93. {
  94.    MEMMGR_DFL_VALIDATE_HEAP_ON_ENTRY   = 0x0001,
  95.    MEMMGR_DFL_VALIDATE_HEAP_ON_EXIT    = 0x0002,
  96.    ALL_MEMMGR_DFLAGS                   = (MEMMGR_DFL_VALIDATE_HEAP_ON_ENTRY |
  97.                                           MEMMGR_DFL_VALIDATE_HEAP_ON_EXIT)
  98. }
  99. MEMMGRDEBUGFLAGS;
  100. #endif   /* DEBUG */
  101. /* Global Variables
  102.  *******************/
  103. #ifdef DEBUG
  104. #pragma data_seg(DATA_SEG_PER_INSTANCE)
  105. /* parameters used by debug AllocateMemory() macro */
  106. PUBLIC_DATA LPCTSTR GpcszElemHdrSize = NULL;
  107. PUBLIC_DATA LPCTSTR GpcszElemHdrFile = NULL;
  108. PUBLIC_DATA ULONG GulElemHdrLine = 0;
  109. #pragma data_seg()
  110. #endif   /* DEBUG */
  111. /* Module Variables
  112.  *******************/
  113. #ifdef PRIVATE_HEAP
  114. #pragma data_seg(DATA_SEG_SHARED)
  115. /* handle to global shared heap */
  116. PRIVATE_DATA HANDLE Mhheap = NULL;
  117. #pragma data_seg()
  118. #endif   /* PRIVATE_HEAP */
  119. #ifdef DEBUG
  120. #ifdef PRIVATE_HEAP
  121. #pragma data_seg(DATA_SEG_SHARED)
  122. #else
  123. #pragma data_seg(DATA_SEG_PER_INSTANCE)
  124. #endif   /* PRIVATE_HEAP */
  125. /* heap */
  126. PRIVATE_DATA PHEAP Mpheap = NULL;
  127. #pragma data_seg(DATA_SEG_SHARED)
  128. /* debug flags */
  129. PRIVATE_DATA DWORD MdwMemoryManagerModuleFlags = 0;
  130. #pragma data_seg(DATA_SEG_READ_ONLY)
  131. /* heap element sentinels */
  132. PRIVATE_DATA CONST struct
  133. {
  134.    BYTE rgbyte[4];
  135. }
  136. MchsPrefix =
  137. {
  138.    { TEXT('H'), TEXT('E'), TEXT('A'), TEXT('D') }
  139. };
  140. PRIVATE_DATA CONST struct
  141. {
  142.    BYTE rgbyte[4];
  143. }
  144. MchsSuffix =
  145. {
  146.    { TEXT('T'), TEXT('A'), TEXT('I'), TEXT('L') }
  147. };
  148. /* .ini file switch descriptions */
  149. PRIVATE_DATA CBOOLINISWITCH cbisValidateHeapOnEntry =
  150. {
  151.    IST_BOOL,
  152.    TEXT("ValidateHeapOnEntry"),
  153.    &MdwMemoryManagerModuleFlags,
  154.    MEMMGR_DFL_VALIDATE_HEAP_ON_ENTRY
  155. };
  156. PRIVATE_DATA CBOOLINISWITCH cbisValidateHeapOnExit =
  157. {
  158.    IST_BOOL,
  159.    TEXT("ValidateHeapOnExit"),
  160.    &MdwMemoryManagerModuleFlags,
  161.    MEMMGR_DFL_VALIDATE_HEAP_ON_EXIT
  162. };
  163. PRIVATE_DATA const PCVOID MrgcpcvisMemoryManagerModule[] =
  164. {
  165.    &cbisValidateHeapOnEntry,
  166.    &cbisValidateHeapOnExit
  167. };
  168. #pragma data_seg()
  169. #endif   /* DEBUG */
  170. /***************************** Private Functions *****************************/
  171. /* Module Prototypes
  172.  ********************/
  173. #ifdef DEBUG
  174. PRIVATE_CODE DWORD CalculatePrivateSize(DWORD);
  175. PRIVATE_CODE PVOID GetPrivateHeapPtr(PVOID);
  176. PRIVATE_CODE PVOID GetPublicHeapPtr(PVOID);
  177. PRIVATE_CODE DWORD GetHeapSize(PCVOID);
  178. PRIVATE_CODE BOOL AddHeapElement(PCVOID, DWORD);
  179. PRIVATE_CODE void RemoveHeapElement(PCVOID);
  180. PRIVATE_CODE void ModifyHeapElement(PCVOID, PCVOID, DWORD);
  181. PRIVATE_CODE BOOL FindHeapElement(PCVOID, PHEAPNODE *);
  182. PRIVATE_CODE void FillNewMemory(PBYTE, DWORD, DWORD);
  183. PRIVATE_CODE void FillFreedMemory(PBYTE, DWORD);
  184. PRIVATE_CODE void FillGrownMemory(PBYTE, DWORD, DWORD, DWORD);
  185. PRIVATE_CODE void FillShrunkenMemory(PBYTE, DWORD, DWORD, DWORD);
  186. PRIVATE_CODE BOOL IsValidHeapPtr(PCVOID);
  187. PRIVATE_CODE BOOL IsHeapOK(void);
  188. PRIVATE_CODE BOOL IsValidPCHEAPNODE(PCHEAPNODE);
  189. PRIVATE_CODE BOOL IsValidPCHEAPELEMDESC(PCHEAPELEMDESC);
  190. PRIVATE_CODE BOOL IsValidHeapElement(PCBYTE, DWORD, DWORD);
  191. PRIVATE_CODE void SpewHeapElementInfo(PCHEAPNODE);
  192. PRIVATE_CODE void AnalyzeHeap(PHEAPSUMMARY, DWORD);
  193. #endif   /* DEBUG */
  194. #ifdef PRIVATE_HEAP
  195. /*
  196. ** InitPrivateHeapModule()
  197. **
  198. **
  199. **
  200. ** Arguments:
  201. **
  202. ** Returns:
  203. **
  204. ** Side Effects:  none
  205. */
  206. PRIVATE_CODE BOOL InitPrivateHeapModule(void)
  207. {
  208.    BOOL bResult;
  209.    SYSTEM_INFO si;
  210.    ASSERT(! Mhheap);
  211.    /* Create shared heap. */
  212.    GetSystemInfo(&si);
  213.    #ifdef WINNT
  214.    Mhheap = HeapCreate(0, si.dwPageSize, MAX_SHARED_HEAP_SIZE);
  215. #else      
  216.    Mhheap = HeapCreate(HEAP_SHARED, si.dwPageSize, MAX_SHARED_HEAP_SIZE);
  217. #endif
  218.    if (Mhheap)
  219.    {
  220. #ifdef DEBUG
  221.       ASSERT(! Mpheap);
  222.       Mpheap = MEMALLOCATE(sizeof(*Mpheap));
  223.       
  224.       if (Mpheap)
  225.       {
  226.          FillMemory(Mpheap, sizeof(*Mpheap), 0);
  227.          bResult = TRUE;
  228.          TRACE_OUT((TEXT("InitMemoryManagerModule(): Created shared heap, initial size == %lu, maximum size == %lu."),
  229.                     si.dwPageSize,
  230.                     MAX_SHARED_HEAP_SIZE));
  231.       }
  232.       else
  233.       {
  234.          EVAL(HeapDestroy(Mhheap));
  235.          Mhheap = NULL;
  236.          bResult = FALSE;
  237.          WARNING_OUT((TEXT("InitMemoryManagerModule(): Failed to create shared heap head.")));
  238.       }
  239. #else    /* DEBUG */
  240.       bResult = TRUE;
  241. #endif   /* DEBUG */
  242.          
  243.    }
  244.    else
  245.    {
  246.       bResult = FALSE;
  247.       WARNING_OUT((TEXT("InitMemoryManagerModule(): Failed to create shared heap.")));
  248.    }
  249.    return(bResult);
  250. }
  251. #else    /* PRIVATE_HEAP */
  252. /*
  253. ** InitHeapModule()
  254. **
  255. **
  256. **
  257. ** Arguments:
  258. **
  259. ** Returns:
  260. **
  261. ** Side Effects:  none
  262. */
  263. PRIVATE_CODE BOOL InitHeapModule(void)
  264. {
  265.    BOOL bResult;
  266. #ifdef DEBUG
  267.    ASSERT(! Mpheap);
  268.    Mpheap = MEMALLOCATE(sizeof(*Mpheap));
  269.    
  270.    if (Mpheap)
  271.    {
  272.       FillMemory(Mpheap, sizeof(*Mpheap), 0);
  273.       TRACE_OUT((TEXT("InitMemoryManagerModule(): Created heap.")));
  274.    }
  275.    else
  276.       WARNING_OUT((TEXT("InitMemoryManagerModule(): Failed to create heap head.")));
  277.          
  278.    bResult = (Mpheap != NULL);
  279. #else
  280.    bResult = TRUE;
  281. #endif
  282.    return(bResult);
  283. }
  284. #endif   /* PRIVATE_HEAP */
  285. #ifdef DEBUG
  286. /*
  287. ** CalculatePrivateSize()
  288. **
  289. **
  290. **
  291. ** Arguments:
  292. **
  293. ** Returns:
  294. **
  295. ** Side Effects:  none
  296. */
  297. PRIVATE_CODE DWORD CalculatePrivateSize(DWORD dwcbPublicSize)
  298. {
  299.    ASSERT(dwcbPublicSize <= DWORD_MAX - sizeof(MchsPrefix) - sizeof(MchsSuffix));
  300.    return(dwcbPublicSize + sizeof(MchsPrefix) + sizeof(MchsSuffix));
  301. }
  302. /*
  303. ** GetPrivateHeapPtr()
  304. **
  305. **
  306. **
  307. ** Arguments:
  308. **
  309. ** Returns:
  310. **
  311. ** Side Effects:  none
  312. */
  313. PRIVATE_CODE PVOID GetPrivateHeapPtr(PVOID pvPublic)
  314. {
  315.    ASSERT((ULONG_PTR)pvPublic > sizeof(MchsPrefix));
  316.    return((PBYTE)pvPublic - sizeof(MchsPrefix));
  317. }
  318. /*
  319. ** GetPublicHeapPtr()
  320. **
  321. **
  322. **
  323. ** Arguments:
  324. **
  325. ** Returns:
  326. **
  327. ** Side Effects:  none
  328. */
  329. PRIVATE_CODE PVOID GetPublicHeapPtr(PVOID pvPrivate)
  330. {
  331.    ASSERT((PCBYTE)pvPrivate <= (PCBYTE)PTR_MAX - sizeof(MchsPrefix));
  332.    return((PBYTE)pvPrivate + sizeof(MchsPrefix));
  333. }
  334. /*
  335. ** GetHeapSize()
  336. **
  337. **
  338. **
  339. ** Arguments:
  340. **
  341. ** Returns:
  342. **
  343. ** Side Effects:  none
  344. */
  345. PRIVATE_CODE DWORD GetHeapSize(PCVOID pcv)
  346. {
  347.    PHEAPNODE phn;
  348.    DWORD dwcbSize;
  349.    if (EVAL(FindHeapElement(pcv, &phn)))
  350.       dwcbSize = phn->dwcbSize;
  351.    else
  352.       dwcbSize = 0;
  353.    return(dwcbSize);
  354. }
  355. /*
  356. ** AddHeapElement()
  357. **
  358. **
  359. **
  360. ** Arguments:
  361. **
  362. ** Returns:
  363. **
  364. ** Side Effects:  none
  365. **
  366. ** Assumes that the global variables GpcszElemHdrSize, GpcszElemHdrFile, and
  367. ** GulElemHdrLine are filled in.
  368. */
  369. PRIVATE_CODE BOOL AddHeapElement(PCVOID pcvNew, DWORD dwcbSize)
  370. {
  371.    PHEAPNODE phnNew;
  372.    /* Is the new heap element already in the list? */
  373.    ASSERT(! FindHeapElement(pcvNew, &phnNew));
  374.    if (Mpheap)
  375.    {
  376.       /* Create new heap node. */
  377.       phnNew = MEMALLOCATE(sizeof(*phnNew));
  378.       if (phnNew)
  379.       {
  380.          /* Fill in heap node fields. */
  381.          phnNew->pcv = pcvNew;
  382.          phnNew->dwcbSize = dwcbSize;
  383.          /* Insert heap node at front of list. */
  384.          phnNew->phnNext = Mpheap->hnHead.phnNext;
  385.          phnNew->phnPrev = &(Mpheap->hnHead);
  386.          Mpheap->hnHead.phnNext = phnNew;
  387.          if (phnNew->phnNext)
  388.             phnNew->phnNext->phnPrev = phnNew;
  389.          /* Fill in heap element descriptor fields. */
  390.          MyLStrCpyN(phnNew->hed.rgchSize, GpcszElemHdrSize, ARRAYSIZE(phnNew->hed.rgchSize));
  391.          MyLStrCpyN(phnNew->hed.rgchFile, GpcszElemHdrFile, ARRAYSIZE(phnNew->hed.rgchFile));
  392.          phnNew->hed.ulLine = GulElemHdrLine;
  393.          ASSERT(IS_VALID_STRUCT_PTR(phnNew, CHEAPNODE));
  394.       }
  395.    }
  396.    else
  397.       phnNew = NULL;
  398.    return(phnNew != NULL);
  399. }
  400. /*
  401. ** RemoveHeapElement()
  402. **
  403. **
  404. **
  405. ** Arguments:
  406. **
  407. ** Returns:
  408. **
  409. ** Side Effects:  none
  410. */
  411. PRIVATE_CODE void RemoveHeapElement(PCVOID pcvOld)
  412. {
  413.    PHEAPNODE phnOld;
  414.    if (EVAL(FindHeapElement(pcvOld, &phnOld)))
  415.    {
  416.       /* Remove heap node from list. */
  417.       phnOld->phnPrev->phnNext = phnOld->phnNext;
  418.       if (phnOld->phnNext)
  419.          phnOld->phnNext->phnPrev = phnOld->phnPrev;
  420.       MEMFREE(phnOld);
  421.    }
  422.    return;
  423. }
  424. /*
  425. ** ModifyHeapElement()
  426. **
  427. **
  428. **
  429. ** Arguments:
  430. **
  431. ** Returns:
  432. **
  433. ** Side Effects:  none
  434. */
  435. PRIVATE_CODE void ModifyHeapElement(PCVOID pcvOld, PCVOID pcvNew, DWORD dwcbNewSize)
  436. {
  437.    PHEAPNODE phn;
  438.    if (EVAL(FindHeapElement(pcvOld, &phn)))
  439.    {
  440.       phn->pcv = pcvNew;
  441.       phn->dwcbSize = dwcbNewSize;
  442.    }
  443.    return;
  444. }
  445. /*
  446. ** FindHeapElement()
  447. **
  448. **
  449. **
  450. ** Arguments:
  451. **
  452. ** Returns:
  453. **
  454. ** Side Effects:  none
  455. */
  456. PRIVATE_CODE BOOL FindHeapElement(PCVOID pcvTarget, PHEAPNODE *pphn)
  457. {
  458.    BOOL bFound = FALSE;
  459.    PHEAPNODE phn;
  460.    ASSERT(IS_VALID_WRITE_PTR(pphn, PHEAPNODE));
  461.    if (Mpheap)
  462.    {
  463.       for (phn = Mpheap->hnHead.phnNext;
  464.            phn;
  465.            phn = phn->phnNext)
  466.       {
  467.          /*
  468.           * Verify each HEAPNODE structure carefully.  We may be in the middle of
  469.           * a ModifyHeapElement() call, in which case just the target HEAPNODE may
  470.           * be invalid, e.g., after MEMREALLOCATE() in ReallocateMemory().
  471.           */
  472.          ASSERT((IS_VALID_READ_PTR(phn, CHEAPNODE) && phn->pcv == pcvTarget) ||
  473.                 IS_VALID_STRUCT_PTR(phn, CHEAPNODE));
  474.          if (phn->pcv == pcvTarget)
  475.          {
  476.             *pphn = phn;
  477.             bFound = TRUE;
  478.             break;
  479.          }
  480.       }
  481.    }
  482.    return(bFound);
  483. }
  484. /*
  485. ** FillNewMemory()
  486. **
  487. **
  488. **
  489. ** Arguments:
  490. **
  491. ** Returns:
  492. **
  493. ** Side Effects:  none
  494. */
  495. PRIVATE_CODE void FillNewMemory(PBYTE pbyte, DWORD dwcbRequestedSize,
  496.                            DWORD dwcbAllocatedSize)
  497. {
  498.    ASSERT(dwcbRequestedSize >= sizeof(MchsPrefix) + sizeof(MchsSuffix));
  499.    ASSERT(dwcbAllocatedSize >= dwcbRequestedSize);
  500.    ASSERT(IS_VALID_WRITE_BUFFER_PTR(pbyte, BYTE, (UINT)dwcbAllocatedSize));
  501.    /* Fill new heap element with the uninitialized byte value. */
  502.    FillMemory(pbyte, dwcbAllocatedSize, UNINITIALIZED_BYTE_VALUE);
  503.    /* Copy prefix and suffix heap element sentinels. */
  504.    CopyMemory(pbyte, &MchsPrefix, sizeof(MchsPrefix));
  505.    CopyMemory(pbyte + dwcbRequestedSize - sizeof(MchsSuffix), &MchsSuffix,
  506.               sizeof(MchsSuffix));
  507.    return;
  508. }
  509. /*
  510. ** FillFreedMemory()
  511. **
  512. **
  513. **
  514. ** Arguments:
  515. **
  516. ** Returns:
  517. **
  518. ** Side Effects:  none
  519. */
  520. PRIVATE_CODE void FillFreedMemory(PBYTE pbyte, DWORD dwcbAllocatedSize)
  521. {
  522.    ASSERT(IS_VALID_WRITE_BUFFER_PTR(pbyte, BYTE, (UINT)dwcbAllocatedSize));
  523.    /* Fill old heap element with the freed byte value. */
  524.    FillMemory(pbyte, dwcbAllocatedSize, FREED_BYTE_VALUE);
  525.    return;
  526. }
  527. /*
  528. ** FillGrownMemory()
  529. **
  530. **
  531. **
  532. ** Arguments:
  533. **
  534. ** Returns:
  535. **
  536. ** Side Effects:  none
  537. */
  538. PRIVATE_CODE void FillGrownMemory(PBYTE pbyte, DWORD dwcbOldRequestedSize,
  539.                              DWORD dwcbNewRequestedSize,
  540.                              DWORD dwcbNewAllocatedSize)
  541. {
  542.    ASSERT(dwcbOldRequestedSize >= sizeof(MchsPrefix) + sizeof(MchsSuffix));
  543.    ASSERT(dwcbNewRequestedSize > dwcbOldRequestedSize);
  544.    ASSERT(dwcbNewAllocatedSize >= dwcbNewRequestedSize);
  545.    ASSERT(IS_VALID_WRITE_BUFFER_PTR(pbyte, BYTE, (UINT)dwcbNewAllocatedSize));
  546.    ASSERT(MyMemComp(pbyte, &MchsPrefix, sizeof(MchsPrefix)) == CR_EQUAL);
  547.    /* Fill new heap element tail with the uninitialized byte value. */
  548.    FillMemory(pbyte + dwcbOldRequestedSize - sizeof(MchsSuffix),
  549.               dwcbNewRequestedSize - dwcbOldRequestedSize,
  550.               UNINITIALIZED_BYTE_VALUE);
  551.    /* Copy suffix heap element sentinel. */
  552.    CopyMemory(pbyte + dwcbNewRequestedSize - sizeof(MchsSuffix), &MchsSuffix,
  553.               sizeof(MchsSuffix));
  554.    return;
  555. }
  556. /*
  557. ** FillShrunkenMemory()
  558. **
  559. **
  560. **
  561. ** Arguments:
  562. **
  563. ** Returns:
  564. **
  565. ** Side Effects:  none
  566. */
  567. PRIVATE_CODE void FillShrunkenMemory(PBYTE pbyte, DWORD dwcbOldRequestedSize,
  568.                                 DWORD dwcbNewRequestedSize,
  569.                                 DWORD dwcbNewAllocatedSize)
  570. {
  571.    ASSERT(dwcbNewRequestedSize >= sizeof(MchsPrefix) + sizeof(MchsSuffix));
  572.    ASSERT(dwcbNewRequestedSize < dwcbOldRequestedSize);
  573.    ASSERT(dwcbNewAllocatedSize >= dwcbNewRequestedSize);
  574.    ASSERT(IS_VALID_WRITE_BUFFER_PTR(pbyte, BYTE, (UINT)dwcbNewAllocatedSize));
  575.    ASSERT(MyMemComp(pbyte, &MchsPrefix, sizeof(MchsPrefix)) == CR_EQUAL);
  576.    /* Fill old heap element tail with the freed byte value. */
  577.    FillMemory(pbyte + dwcbNewRequestedSize,
  578.               dwcbOldRequestedSize - dwcbNewRequestedSize, FREED_BYTE_VALUE);
  579.    /* Copy suffix heap element sentinel. */
  580.    CopyMemory(pbyte + dwcbNewRequestedSize - sizeof(MchsSuffix), &MchsSuffix,
  581.               sizeof(MchsSuffix));
  582.    return;
  583. }
  584. /*
  585. ** IsValidHeapPtr()
  586. **
  587. **
  588. **
  589. ** Arguments:
  590. **
  591. ** Returns:
  592. **
  593. ** Side Effects:  none
  594. */
  595. PRIVATE_CODE BOOL IsValidHeapPtr(PCVOID pcv)
  596. {
  597.    PHEAPNODE phnUnused;
  598.    return(FindHeapElement(pcv, &phnUnused));
  599. }
  600. /*
  601. ** IsHeapOK()
  602. **
  603. **
  604. **
  605. ** Arguments:
  606. **
  607. ** Returns:
  608. **
  609. ** Side Effects:  none
  610. */
  611. PRIVATE_CODE BOOL IsHeapOK(void)
  612. {
  613.    PHEAPNODE phn;
  614.    if (Mpheap)
  615.    {
  616.       for (phn = Mpheap->hnHead.phnNext;
  617.            phn && IS_VALID_STRUCT_PTR(phn, CHEAPNODE);
  618.            phn = phn->phnNext)
  619.          ;
  620.    }
  621.    else
  622.       phn = (PHEAPNODE)0xFFFF;
  623.    return(phn == NULL);
  624. }
  625. /*
  626. ** IsValidPCHEAPNODE()
  627. **
  628. **
  629. **
  630. ** Arguments:
  631. **
  632. ** Returns:
  633. **
  634. ** Side Effects:  none
  635. */
  636. PRIVATE_CODE BOOL IsValidPCHEAPNODE(PCHEAPNODE pchn)
  637. {
  638.    BOOL bResult;
  639.    if (IS_VALID_READ_PTR(pchn, CHEAPNODE) &&
  640.        IS_VALID_READ_PTR(pchn->phnPrev, CHEAPNODE) &&
  641.        EVAL(pchn->phnPrev->phnNext == pchn) &&
  642.        EVAL(! pchn->phnNext ||
  643.             (IS_VALID_READ_PTR(pchn->phnNext, CHEAPNODE) &&
  644.              EVAL(pchn->phnNext->phnPrev == pchn))) &&
  645.        EVAL(IsValidHeapElement(pchn->pcv, pchn->dwcbSize, MEMSIZE((PVOID)(pchn->pcv)))) &&
  646.        IS_VALID_STRUCT_PTR(&(pchn->hed), CHEAPELEMDESC))
  647.       bResult = TRUE;
  648.    else
  649.       bResult = FALSE;
  650.    return(bResult);
  651. }
  652. /*
  653. ** IsValidPCHEAPELEMDESC()
  654. **
  655. **
  656. **
  657. ** Arguments:
  658. **
  659. ** Returns:
  660. **
  661. ** Side Effects:  none
  662. */
  663. PRIVATE_CODE BOOL IsValidPCHEAPELEMDESC(PCHEAPELEMDESC pched)
  664. {
  665.    BOOL bResult;
  666.    /* Any value for pched->ulLine is valid. */
  667.    if (IS_VALID_READ_PTR(pched, CHEAPELEMDESC))
  668.       bResult = TRUE;
  669.    else
  670.       bResult = FALSE;
  671.    return(bResult);
  672. }
  673. /*
  674. ** IsValidHeapElement()
  675. **
  676. **
  677. **
  678. ** Arguments:
  679. **
  680. ** Returns:
  681. **
  682. ** Side Effects:  none
  683. */
  684. PRIVATE_CODE BOOL IsValidHeapElement(PCBYTE pcbyte, DWORD dwcbRequestedSize,
  685.                                 DWORD dwcbAllocatedSize)
  686. {
  687.    BOOL bResult;
  688.    if (EVAL(dwcbRequestedSize >= sizeof(MchsPrefix) + sizeof(MchsSuffix)) &&
  689.        EVAL(dwcbAllocatedSize >= dwcbRequestedSize) &&
  690.        IS_VALID_READ_PTR(pcbyte, dwcbAllocatedSize) &&
  691.        EVAL(MyMemComp(pcbyte, &MchsPrefix, sizeof(MchsPrefix)) == CR_EQUAL) &&
  692.        EVAL(MyMemComp(pcbyte + dwcbRequestedSize - sizeof(MchsSuffix), &MchsSuffix, sizeof(MchsSuffix)) == CR_EQUAL))
  693.       bResult = TRUE;
  694.    else
  695.       bResult = FALSE;
  696.    return(bResult);
  697. }
  698. /*
  699. ** SpewHeapElementInfo()
  700. **
  701. **
  702. **
  703. ** Arguments:
  704. **
  705. ** Returns:
  706. **
  707. ** Side Effects:  none
  708. */
  709. PRIVATE_CODE void SpewHeapElementInfo(PCHEAPNODE pchn)
  710. {
  711.    ASSERT(IS_VALID_STRUCT_PTR(pchn, CHEAPNODE));
  712.    TRACE_OUT((TEXT("Used heap element at %#lx:rn")
  713.               TEXT("     %lu bytes requestedrn")
  714.               TEXT("     %lu bytes allocatedrn")
  715.               TEXT("     originally allocated as '%s' bytes in file %s at line %lu"),
  716.               pchn->pcv,
  717.               pchn->dwcbSize,
  718.               MEMSIZE((PVOID)(pchn->pcv)),
  719.               pchn->hed.rgchSize,
  720.               pchn->hed.rgchFile,
  721.               pchn->hed.ulLine));
  722.    return;
  723. }
  724. /*
  725. ** AnalyzeHeap()
  726. **
  727. **
  728. **
  729. ** Arguments:
  730. **
  731. ** Returns:
  732. **
  733. ** Side Effects:  none
  734. */
  735. PRIVATE_CODE void AnalyzeHeap(PHEAPSUMMARY phs, DWORD dwFlags)
  736. {
  737.    PCHEAPNODE pchn;
  738.    ULONG ulcHeapElements = 0;
  739.    DWORD dwcbUsed = 0;
  740.    ASSERT(IS_VALID_WRITE_PTR(phs, HEAPSUMMARY));
  741.    ASSERT(FLAGS_ARE_VALID(dwFlags, SHS_FL_SPEW_USED_INFO));
  742.    ASSERT(IsHeapOK());
  743.    TRACE_OUT((TEXT("Starting private heap analysis.")));
  744.    if (Mpheap)
  745.    {
  746.       for (pchn = Mpheap->hnHead.phnNext;
  747.            pchn;
  748.            pchn = pchn->phnNext)
  749.       {
  750.          ASSERT(IS_VALID_STRUCT_PTR(pchn, CHEAPNODE));
  751.          ASSERT(ulcHeapElements < ULONG_MAX);
  752.          ulcHeapElements++;
  753.          ASSERT(dwcbUsed < DWORD_MAX - pchn->dwcbSize);
  754.          dwcbUsed += pchn->dwcbSize;
  755.          if (IS_FLAG_SET(dwFlags, SHS_FL_SPEW_USED_INFO))
  756.             SpewHeapElementInfo(pchn);
  757.       }
  758.       phs->ulcUsedElements = ulcHeapElements;
  759.       phs->dwcbUsedSize = dwcbUsed;
  760.    }
  761.    else
  762.       WARNING_OUT((TEXT("Private heap not allocated!")));
  763.    TRACE_OUT((TEXT("Private heap analysis complete.")));
  764.    return;
  765. }
  766. #endif   /* DEBUG */
  767. /****************************** Public Functions *****************************/
  768. /*
  769. ** InitMemoryManagerModule()
  770. **
  771. ** When PRIVATE_HEAP is defined, this function should be called only
  772. ** once, when the DLL is being first initialized.  When PRIVATE_HEAP
  773. ** is not defined, this function should be called for every 
  774. ** DLL_PROCESS_ATTACH.
  775. **
  776. **
  777. ** Arguments:
  778. **
  779. ** Returns:
  780. **
  781. ** Side Effects:  none
  782. */
  783. PUBLIC_CODE BOOL InitMemoryManagerModule(void)
  784. {
  785.    BOOL bResult;
  786. #ifdef PRIVATE_HEAP
  787.    bResult = InitPrivateHeapModule();
  788. #else  /* PRIVATE_HEAP */
  789.    bResult = InitHeapModule();
  790. #endif
  791.    return(bResult);
  792. }
  793. /*
  794. ** ExitMemoryManagerModule()
  795. **
  796. ** When PRIVATE_HEAP is defined, this function should be called only
  797. ** once, when the DLL is finally being terminated.  When PRIVATE_HEAP
  798. ** is not defined, this function should be called for every 
  799. ** DLL_PROCESS_DETACH.
  800. **
  801. **
  802. ** Arguments:
  803. **
  804. ** Returns:
  805. **
  806. ** Side Effects:  none
  807. */
  808. PUBLIC_CODE void ExitMemoryManagerModule(void)
  809. {
  810. #ifdef DEBUG
  811.    if (Mpheap)
  812.    {
  813.       MEMFREE(Mpheap);
  814.       Mpheap = NULL;
  815.    }
  816.    else
  817.       WARNING_OUT((TEXT("ExitMemoryManagerModule() called when Mpheap is NULL.")));
  818. #endif
  819. #ifdef PRIVATE_HEAP
  820.    if (Mhheap)
  821.    {
  822.       EVAL(HeapDestroy(Mhheap));
  823.       Mhheap = NULL;
  824.    }
  825.    else
  826.       WARNING_OUT((TEXT("ExitMemoryManagerModule() called when Mhheap is NULL.")));
  827. #endif
  828.    return;
  829. }
  830. /*
  831. ** MyMemComp()
  832. **
  833. **
  834. **
  835. ** Arguments:
  836. **
  837. ** Returns:
  838. **
  839. ** Side Effects:  none
  840. */
  841. PUBLIC_CODE COMPARISONRESULT MyMemComp(PCVOID pcv1, PCVOID pcv2, DWORD dwcbSize)
  842. {
  843.    int nResult = 0;
  844.    PCBYTE pcbyte1 = pcv1;
  845.    PCBYTE pcbyte2 = pcv2;
  846.    ASSERT(IS_VALID_READ_BUFFER_PTR(pcv1, BYTE, (UINT)dwcbSize));
  847.    ASSERT(IS_VALID_READ_BUFFER_PTR(pcv2, BYTE, (UINT)dwcbSize));
  848.    while (dwcbSize > 0 &&
  849.           ! (nResult = *pcbyte1 - *pcbyte2))
  850.    {
  851.       pcbyte1++;
  852.       pcbyte2++;
  853.       dwcbSize--;
  854.    }
  855.    return(MapIntToComparisonResult(nResult));
  856. }
  857. /*
  858. ** MyAllocateMemory()
  859. **
  860. **
  861. **
  862. ** Arguments:
  863. **
  864. ** Returns:
  865. **
  866. ** Side Effects:  none
  867. */
  868. PUBLIC_CODE BOOL MyAllocateMemory(DWORD dwcbSize, PVOID *ppvNew)
  869. {
  870. #ifdef DEBUG
  871.    DWORD dwcbRequestedSize = dwcbSize;
  872.    ASSERT(dwcbSize >= 0);
  873.    ASSERT(IS_VALID_WRITE_PTR(ppvNew, PVOID));
  874.    dwcbSize = CalculatePrivateSize(dwcbSize);
  875.    if (IS_FLAG_SET(MdwMemoryManagerModuleFlags, MEMMGR_DFL_VALIDATE_HEAP_ON_ENTRY))
  876.       ASSERT(IsHeapOK());
  877. #endif
  878.    *ppvNew = MEMALLOCATE(dwcbSize);
  879. #ifdef DEBUG
  880.    if (*ppvNew)
  881.    {
  882.       FillNewMemory(*ppvNew, dwcbSize, MEMSIZE(*ppvNew));
  883.       if (AddHeapElement(*ppvNew, dwcbSize))
  884.       {
  885.          *ppvNew = GetPublicHeapPtr(*ppvNew);
  886.          ASSERT(IS_VALID_WRITE_BUFFER_PTR(*ppvNew, BYTE, (UINT)dwcbRequestedSize));
  887.       }
  888.       else
  889.       {
  890.          EVAL(MEMFREE(*ppvNew));
  891.          *ppvNew = NULL;
  892.       }
  893.    }
  894.    if (IS_FLAG_SET(MdwMemoryManagerModuleFlags, MEMMGR_DFL_VALIDATE_HEAP_ON_EXIT))
  895.       ASSERT(IsHeapOK());
  896. #endif
  897.    return(*ppvNew != NULL);
  898. }
  899. /*
  900. ** FreeMemory()
  901. **
  902. **
  903. **
  904. ** Arguments:
  905. **
  906. ** Returns:
  907. **
  908. ** Side Effects:  none
  909. */
  910. PUBLIC_CODE void FreeMemory(PVOID pvOld)
  911. {
  912. #ifdef DEBUG
  913.    if (IS_FLAG_SET(MdwMemoryManagerModuleFlags, MEMMGR_DFL_VALIDATE_HEAP_ON_ENTRY))
  914.       ASSERT(IsHeapOK());
  915.    pvOld = GetPrivateHeapPtr(pvOld);
  916.    ASSERT(IsValidHeapPtr(pvOld));
  917.    RemoveHeapElement(pvOld);
  918.    FillFreedMemory(pvOld, MEMSIZE(pvOld));
  919. #endif
  920.    EVAL(MEMFREE(pvOld));
  921. #ifdef DEBUG
  922.    if (IS_FLAG_SET(MdwMemoryManagerModuleFlags, MEMMGR_DFL_VALIDATE_HEAP_ON_EXIT))
  923.       ASSERT(IsHeapOK());
  924. #endif   /* DEBUG */
  925.    return;
  926. }
  927. /*
  928. ** ReallocateMemory()
  929. **
  930. **
  931. **
  932. ** Arguments:
  933. **
  934. ** Returns:
  935. **
  936. ** Side Effects:  none
  937. */
  938. PUBLIC_CODE BOOL ReallocateMemory(PVOID pvOld, DWORD dwcbNewSize, PVOID *ppvNew)
  939. {
  940. #ifdef DEBUG
  941.    DWORD dwcbRequestedSize = dwcbNewSize;
  942.    DWORD dwcbOldSize;
  943.    ASSERT(IS_VALID_WRITE_PTR(ppvNew, PVOID));
  944.    if (IS_FLAG_SET(MdwMemoryManagerModuleFlags, MEMMGR_DFL_VALIDATE_HEAP_ON_ENTRY))
  945.       ASSERT(IsHeapOK());
  946.    pvOld = GetPrivateHeapPtr(pvOld);
  947.    ASSERT(IsValidHeapPtr(pvOld));
  948.    dwcbNewSize = CalculatePrivateSize(dwcbNewSize);
  949.    dwcbOldSize = GetHeapSize(pvOld);
  950.    if (dwcbNewSize == dwcbOldSize)
  951.       WARNING_OUT((TEXT("ReallocateMemory(): Size of heap element %#lx is already %lu bytes."),
  952.                    GetPublicHeapPtr(pvOld),
  953.                    dwcbNewSize));
  954. #endif
  955.    *ppvNew = MEMREALLOCATE(pvOld, dwcbNewSize);
  956. #ifdef DEBUG
  957.    if (*ppvNew)
  958.    {
  959.       /* Bigger or smaller? */
  960.       if (dwcbNewSize > dwcbOldSize)
  961.          /* Bigger. */
  962.          FillGrownMemory(*ppvNew, dwcbOldSize, dwcbNewSize, MEMSIZE(*ppvNew));
  963.       else
  964.          /* Smaller. */
  965.          FillShrunkenMemory(*ppvNew, dwcbOldSize, dwcbNewSize, MEMSIZE(*ppvNew));
  966.       ModifyHeapElement(pvOld, *ppvNew, dwcbNewSize);
  967.       *ppvNew = GetPublicHeapPtr(*ppvNew);
  968.       ASSERT(IS_VALID_WRITE_BUFFER_PTR(*ppvNew, BYTE, (UINT)dwcbRequestedSize));
  969.    }
  970.    if (IS_FLAG_SET(MdwMemoryManagerModuleFlags, MEMMGR_DFL_VALIDATE_HEAP_ON_EXIT))
  971.       ASSERT(IsHeapOK());
  972. #endif
  973.    return(*ppvNew != NULL);
  974. }
  975. /*
  976. ** GetMemorySize()
  977. **
  978. **
  979. **
  980. ** Arguments:
  981. **
  982. ** Returns:
  983. **
  984. ** Side Effects:  none
  985. */
  986. PUBLIC_CODE DWORD GetMemorySize(PVOID pv)
  987. {
  988.    ASSERT(IsValidHeapPtr(GetPrivateHeapPtr(pv)));
  989.    return(MEMSIZE(pv));
  990. }
  991. #ifdef DEBUG
  992. /*
  993. ** SetMemoryManagerModuleIniSwitches()
  994. **
  995. **
  996. **
  997. ** Arguments:
  998. **
  999. ** Returns:
  1000. **
  1001. ** Side Effects:  none
  1002. */
  1003. PUBLIC_CODE BOOL SetMemoryManagerModuleIniSwitches(void)
  1004. {
  1005.    BOOL bResult;
  1006.    bResult = SetIniSwitches(MrgcpcvisMemoryManagerModule,
  1007.                             ARRAY_ELEMENTS(MrgcpcvisMemoryManagerModule));
  1008.    ASSERT(FLAGS_ARE_VALID(MdwMemoryManagerModuleFlags, ALL_MEMMGR_DFLAGS));
  1009.    return(bResult);
  1010. }
  1011. /*
  1012. ** SpewHeapSummary()
  1013. **
  1014. **
  1015. **
  1016. ** Arguments:
  1017. **
  1018. ** Returns:
  1019. **
  1020. ** Side Effects:  none
  1021. */
  1022. PUBLIC_CODE void SpewHeapSummary(DWORD dwFlags)
  1023. {
  1024.    HEAPSUMMARY hs;
  1025.    ASSERT(FLAGS_ARE_VALID(dwFlags, SHS_FL_SPEW_USED_INFO));
  1026.    AnalyzeHeap(&hs, dwFlags);
  1027.    TRACE_OUT((TEXT("Heap summary: %lu bytes in %lu used elements."),
  1028.               hs.dwcbUsedSize,
  1029.               hs.ulcUsedElements));
  1030.    return;
  1031. }
  1032. #endif   /* DEBUG */