MALSPY.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:16k
源码类别:

Windows编程

开发平台:

Visual C++

  1. //+---------------------------------------------------------------------
  2. //
  3. //  Microsoft Windows
  4. //  Copyright (C) Microsoft Corporation, 1994 - 1996.
  5. //
  6. //  File:       cmallspy.c
  7. //
  8. //  Contents:   Sample implementation of IMallocSpy.  The implementation here
  9. //              is pretty simple.  It assumes that all we want to do is keep
  10. //              a header on the front of all allocations so we can note
  11. //              interesting information.
  12. //
  13. //  Classes:    CMallocSpy
  14. //
  15. //----------------------------------------------------------------------
  16. #include <ole2.h>
  17. #include <olestd.h>
  18. OLEDBGDATA
  19. #include "malspy.h"
  20. #define TOKEN 0xDEAD
  21. typedef struct tagHeader
  22. {
  23.     UINT    uiTag;
  24.     ULONG   cbSize;
  25. } HEADER, * LPHEADER;
  26. // The following macro is used to ensure that the token placed at the
  27. // end of each memory block is always aligned on a dword boundary.
  28. // This is necessary to avoid alignment faults on some systems.
  29. #define DWORDALIGN(x) ((x + 3) & (~3))
  30. typedef struct CMallocSpy {
  31.   IMallocSpyVtbl FAR*     lpVtbl;
  32.   ULONG                   m_cRef;   // interface specific ref count.
  33.   ULONG                   m_cbRequested;
  34. } CMALLOCSPY, *LPCMALLOCSPY;
  35. STDMETHODIMP MallocSpy_QueryInterface(
  36.       LPMALLOCSPY             this,
  37.       REFIID                  riid,
  38.       LPVOID FAR*             lplpUnk);
  39. STDMETHODIMP_(ULONG) MallocSpy_AddRef(
  40.     LPMALLOCSPY this);
  41. STDMETHODIMP_(ULONG) MallocSpy_Release(
  42.     LPMALLOCSPY this);
  43. STDMETHODIMP_(ULONG) MallocSpy_PreAlloc(
  44.     LPMALLOCSPY this,
  45.     ULONG cbRequest);
  46. STDMETHODIMP_(void *) MallocSpy_PostAlloc(
  47.     LPMALLOCSPY this,
  48.     void *pActual);
  49. STDMETHODIMP_(void *) MallocSpy_PreFree(
  50.     LPMALLOCSPY this,
  51.     void *pRequest, BOOL fSpyed);
  52. STDMETHODIMP_(void) MallocSpy_PostFree(
  53.     LPMALLOCSPY this,
  54.     BOOL fSpyed);
  55. STDMETHODIMP_(ULONG) MallocSpy_PreRealloc(
  56.     LPMALLOCSPY this,
  57.     void *pRequest,
  58.     ULONG cbRequest,
  59.     void **ppNewRequest,
  60.     BOOL fSpyed);
  61. STDMETHODIMP_(void *) MallocSpy_PostRealloc(
  62.     LPMALLOCSPY this,
  63.     void *pActual,
  64.     BOOL fSpyed);
  65. STDMETHODIMP_(void *) MallocSpy_PreGetSize(
  66.     LPMALLOCSPY this,
  67.     void *pRequest,
  68.     BOOL fSpyed);
  69. STDMETHODIMP_(ULONG) MallocSpy_PostGetSize(
  70.     LPMALLOCSPY this,
  71.     ULONG cbActual,
  72.     BOOL fSpyed);
  73. STDMETHODIMP_(void *) MallocSpy_PreDidAlloc(
  74.     LPMALLOCSPY this,
  75.     void *pRequest,
  76.     BOOL fSpyed);
  77. STDMETHODIMP_(BOOL) MallocSpy_PostDidAlloc(
  78.     LPMALLOCSPY this,
  79.     void *pRequest,
  80.     BOOL fSpyed,
  81.     BOOL fActual);
  82. STDMETHODIMP_(void) MallocSpy_PreHeapMinimize(
  83.     LPMALLOCSPY this);
  84. STDMETHODIMP_(void) MallocSpy_PostHeapMinimize(
  85.     LPMALLOCSPY this);
  86. IMallocSpyVtbl g_MallocSpyVtbl;
  87. BOOL InitializeMallocSpy(void)
  88. {
  89.     BOOL fStatus;
  90.     LPCMALLOCSPY lpcMallocSpy = NULL;
  91.     HRESULT hr;
  92.     OleStdInitVtbl(
  93.           &g_MallocSpyVtbl,
  94.           sizeof(g_MallocSpyVtbl));
  95.     g_MallocSpyVtbl.QueryInterface      = MallocSpy_QueryInterface;
  96.     g_MallocSpyVtbl.AddRef              = MallocSpy_AddRef;
  97.     g_MallocSpyVtbl.Release             = MallocSpy_Release;
  98.     g_MallocSpyVtbl.PreAlloc            = MallocSpy_PreAlloc;
  99.     g_MallocSpyVtbl.PostAlloc           = MallocSpy_PostAlloc;
  100.     g_MallocSpyVtbl.PreFree             = MallocSpy_PreFree;
  101.     g_MallocSpyVtbl.PostFree            = MallocSpy_PostFree;
  102.     g_MallocSpyVtbl.PreRealloc          = MallocSpy_PreRealloc;
  103.     g_MallocSpyVtbl.PostRealloc         = MallocSpy_PostRealloc;
  104.     g_MallocSpyVtbl.PreGetSize          = MallocSpy_PreGetSize;
  105.     g_MallocSpyVtbl.PostGetSize         = MallocSpy_PostGetSize;
  106.     g_MallocSpyVtbl.PreDidAlloc         = MallocSpy_PreDidAlloc;
  107.     g_MallocSpyVtbl.PostDidAlloc        = MallocSpy_PostDidAlloc;
  108.     g_MallocSpyVtbl.PreHeapMinimize     = MallocSpy_PreHeapMinimize;
  109.     g_MallocSpyVtbl.PostHeapMinimize    = MallocSpy_PostHeapMinimize;
  110.     fStatus = OleStdCheckVtbl(
  111.           &g_MallocSpyVtbl,
  112.           sizeof(g_MallocSpyVtbl),
  113.           OLESTR("IMallocSpy"));
  114.     if (! fStatus)
  115.         return FALSE;
  116.     lpcMallocSpy = malloc(sizeof(CMALLOCSPY));
  117.     if (NULL == lpcMallocSpy)
  118.     {
  119.         return FALSE;
  120.     }
  121.     lpcMallocSpy->lpVtbl = &g_MallocSpyVtbl;
  122.     lpcMallocSpy->m_cRef = 0;
  123.     hr = CoRegisterMallocSpy((LPMALLOCSPY)lpcMallocSpy);
  124.     return(SUCCEEDED(hr));
  125. }
  126. void UninitializeMallocSpy()
  127. {
  128.     CoRevokeMallocSpy();
  129. }
  130. //+---------------------------------------------------------------------------
  131. //
  132. //  Function:   CbUserFromCbActual
  133. //
  134. //  Synopsis:   adjusts the size to account for the header and footer
  135. //
  136. //  Arguments:  [cbActual] - actual size of the memory block
  137. //
  138. //  Returns:    size reported to the user
  139. //
  140. //----------------------------------------------------------------------------
  141. ULONG CbUserFromCbActual(ULONG cbActual)
  142. {
  143.     return(cbActual - (sizeof(HEADER) + sizeof(UINT)));
  144. }
  145. //+---------------------------------------------------------------------------
  146. //
  147. //  Function:   CbActualFromCbUser
  148. //
  149. //  Synopsis:   adjusts the size to account for the header and footer
  150. //
  151. //  Arguments:  [cbUser] - size reported to the user
  152. //
  153. //  Returns:    actual size of the memory block
  154. //
  155. //----------------------------------------------------------------------------
  156. ULONG CbActualFromCbUser(ULONG cbUser)
  157. {
  158.     return(DWORDALIGN(cbUser) + sizeof(HEADER) + sizeof(UINT));
  159. }
  160. //+---------------------------------------------------------------------------
  161. //
  162. //  Function:   PActualFromPUser
  163. //
  164. //  Synopsis:   adjusts the pointer to account for the header, verifying
  165. //              the memory integrity in the process
  166. //
  167. //  Arguments:  [pUser] - pointer reported to the user
  168. //
  169. //  Returns:    acutal pointer to the memory block
  170. //
  171. //----------------------------------------------------------------------------
  172. void * PActualFromPUser(void * pUser)
  173. {
  174.     HEADER * pHeader;
  175.     UINT * puiFooter;
  176.     pHeader = ((LPHEADER)pUser) - 1;
  177.     puiFooter = (UINT *)(((BYTE *)pUser) + DWORDALIGN(pHeader->cbSize));
  178.     OleDbgAssertSz(TOKEN == pHeader->uiTag, "Illegal memory block.");
  179.     OleDbgAssertSz(TOKEN == *puiFooter, "Memory block was overrun.");
  180.     if (TOKEN != pHeader->uiTag)
  181.     {
  182.         // Just to be safe, if we don't find the TOKEN we'll not adjust the
  183.         // pointer
  184.         return(pUser);
  185.     }
  186.     return ((void *) (pHeader));
  187. }
  188. //+---------------------------------------------------------------------------
  189. //
  190. //  Function:   PUserFromPActual
  191. //
  192. //  Synopsis:   adjusts the pointer to account for the header, initializing
  193. //              the header and footer in the process to allow verification of
  194. //              memory integrity
  195. //
  196. //  Arguments:  [pActual]    - actual pointer to the memory block
  197. //              [cbDataSize] - size of the memory block requested by the user
  198. //
  199. //  Returns:    pointer to the data which the user may modify
  200. //
  201. //----------------------------------------------------------------------------
  202. void * PUserFromPActual(void * pActual, ULONG cbDataSize)
  203. {
  204.     // Mark the block with a TOKEN at the front and the end
  205.     // and its size so we can tell if it is bogus
  206.     LPHEADER pHeader = pActual;
  207.     UINT* puiFooter;
  208.     pHeader->uiTag = TOKEN;
  209.     pHeader->cbSize = cbDataSize;
  210.     pActual = (void *)(pHeader + 1);
  211.     puiFooter = (UINT *)(((BYTE *) pActual) + DWORDALIGN(pHeader->cbSize));
  212.     *puiFooter = TOKEN;
  213.     return(pActual);
  214. }
  215. STDMETHODIMP MallocSpy_QueryInterface(
  216.       LPMALLOCSPY  this,
  217.       REFIID riid,
  218.       LPVOID *                ppUnk)
  219. {
  220.     HRESULT hr = S_OK;
  221.     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMallocSpy))
  222.     {
  223.         *ppUnk = this;
  224.     }
  225.     else
  226.     {
  227.         *ppUnk = NULL;
  228.         hr =  E_NOINTERFACE;
  229.     }
  230.     this->lpVtbl->AddRef((LPMALLOCSPY)this);
  231.     return hr;
  232. }
  233. STDMETHODIMP_(ULONG) MallocSpy_AddRef(
  234.     LPMALLOCSPY this)
  235. {
  236.     return ++(((LPCMALLOCSPY)this)->m_cRef);
  237. }
  238. STDMETHODIMP_(ULONG) MallocSpy_Release(
  239.     LPMALLOCSPY this)
  240. {
  241.     ULONG cRef;
  242.     cRef = --(((LPCMALLOCSPY)this)->m_cRef);
  243.     if (cRef == 0)
  244.     {
  245.         free(this);
  246.     }
  247.     return cRef;
  248. }
  249. //+---------------------------------------------------------------------
  250. //
  251. //  Member:     CMallocSpy::PreAlloc
  252. //
  253. //  Synopsis:   Called prior to OLE calling IMalloc::Alloc
  254. //
  255. //  Arguments:  [cbRequest] -- The number of bytes the caller of
  256. //                             is requesting IMalloc::Alloc
  257. //
  258. //  Returns:    The count of bytes to actually allocate
  259. //
  260. //----------------------------------------------------------------------
  261. STDMETHODIMP_(ULONG) MallocSpy_PreAlloc(
  262.     LPMALLOCSPY this,
  263.     ULONG cbRequest)
  264. {
  265.     ((LPCMALLOCSPY)this)->m_cbRequested = cbRequest;
  266.     return CbActualFromCbUser(cbRequest);
  267. }
  268. #ifdef TRACEMEM
  269. char szScratch[256];
  270. #endif
  271. //+---------------------------------------------------------------------
  272. //
  273. //  Member:     CMallocSpy::PostAlloc
  274. //
  275. //  Synopsis:   Called after OLE calls IMalloc::Alloc
  276. //
  277. //  Arguments:  [pActual] -- The allocation returned by IMalloc::Alloc
  278. //
  279. //  Returns:    The allocation pointer to return to the caller of
  280. //              IMalloc::Alloc
  281. //
  282. //----------------------------------------------------------------------
  283. STDMETHODIMP_(void *) MallocSpy_PostAlloc(
  284.     LPMALLOCSPY this,
  285.     void *pActual)
  286. {
  287.     void * pUser = PUserFromPActual(pActual, ((LPCMALLOCSPY)this)->m_cbRequested);
  288. #ifdef TRACEMEM
  289.     wsprintf(szScratch, "IMalloc: 0x%08lX allocatedn", pUser);
  290.     OleDbgOut1(szScratch);
  291. #endif
  292.     return(pUser);
  293. }
  294. //+---------------------------------------------------------------------
  295. //
  296. //  Member:     CMallocSpy::PreFree
  297. //
  298. //  Synopsis:   Called prior to OLE calling IMalloc::Free
  299. //
  300. //  Arguments:  [pRequest] -- The allocation to be freed
  301. //              [fSpyed]   -- Whether it was allocated with a spy active
  302. //
  303. //----------------------------------------------------------------------
  304. STDMETHODIMP_(void *) MallocSpy_PreFree(
  305.     LPMALLOCSPY this,
  306.     void *pRequest, BOOL fSpyed)
  307. {
  308.     // Check for NULL
  309.     if (pRequest == NULL)
  310.     {
  311.         return NULL;
  312.     }
  313. #ifdef TRACEMEM
  314.     wsprintf(szScratch, "IMalloc: 0x%08lX freeingn", pRequest);
  315.     OleDbgOut1(szScratch);
  316. #endif
  317.     // Undo the offset
  318.     if (fSpyed)
  319.     {
  320.         return(PActualFromPUser(pRequest));
  321.     }
  322.     else
  323.     {
  324.         return pRequest;
  325.     }
  326. }
  327. //+---------------------------------------------------------------------
  328. //
  329. //  Member:     CMallocSpy::PostFree
  330. //
  331. //  Synopsis:   Called after OLE calls IMalloc::Free
  332. //
  333. //  Arguments:  [fSpyed]   -- Whether it was allocated with a spy active
  334. //
  335. //  Returns:
  336. //
  337. //----------------------------------------------------------------------
  338. STDMETHODIMP_(void) MallocSpy_PostFree(
  339.     LPMALLOCSPY this,
  340.     BOOL fSpyed)
  341. {
  342.     return;
  343. }
  344. //+---------------------------------------------------------------------
  345. //
  346. //  Member:     CMallocSpy::PreRealloc
  347. //
  348. //  Synopsis:   Called prior to OLE calling IMalloc::Realloc
  349. //
  350. //  Arguments:  [pRequest]     -- The buffer to be reallocated
  351. //              [cbRequest]    -- The requested new size of the buffer
  352. //              [ppNewRequest] -- Where to store the new buffer pointer
  353. //                                to be reallocated
  354. //              [fSpyed]       -- Whether it was allocated with a spy active
  355. //
  356. //  Returns:    The new size to actually be allocated
  357. //
  358. //----------------------------------------------------------------------
  359. STDMETHODIMP_(ULONG) MallocSpy_PreRealloc(
  360.     LPMALLOCSPY this,
  361.     void *pRequest,
  362.     ULONG cbRequest,
  363.     void **ppNewRequest,
  364.     BOOL fSpyed)
  365. {
  366. #ifdef TRACEMEM
  367.     wsprintf(szScratch, "IMalloc: 0x%08lX realocatingn", pRequest);
  368.     OleDbgOut1(szScratch);
  369. #endif
  370.     if (fSpyed)
  371.     {
  372.         *ppNewRequest = PActualFromPUser(pRequest);
  373.         ((LPCMALLOCSPY)this)->m_cbRequested = cbRequest;
  374.         return CbActualFromCbUser(cbRequest);
  375.     }
  376.     else
  377.     {
  378.         *ppNewRequest = pRequest;
  379.         return cbRequest;
  380.     }
  381. }
  382. //+---------------------------------------------------------------------
  383. //
  384. //  Member:     CMallocSpy::PostRealloc
  385. //
  386. //  Synopsis:   Called after OLE calls IMalloc::Realloc
  387. //
  388. //  Arguments:  [pActual] -- Pointer to the reallocated buffer
  389. //              [fSpyed]  -- Whether it was allocated with a spy active
  390. //
  391. //  Returns:    The buffer pointer to return
  392. //
  393. //----------------------------------------------------------------------
  394. STDMETHODIMP_(void *) MallocSpy_PostRealloc(
  395.     LPMALLOCSPY this,
  396.     void *pActual,
  397.     BOOL fSpyed)
  398. {
  399.     void * pUser;
  400.     if (fSpyed)
  401.     {
  402.         pUser = PUserFromPActual(pActual, ((LPCMALLOCSPY)this)->m_cbRequested);
  403.     }
  404.     else
  405.     {
  406.         pUser = pActual;
  407.     }
  408. #ifdef TRACEMEM
  409.     wsprintf(szScratch, "IMalloc: 0x%08lX reallocatedn", pUser);
  410.     OleDbgOut1(szScratch);
  411. #endif
  412.     return(pUser);
  413. }
  414. //+---------------------------------------------------------------------
  415. //
  416. //  Member:     CMallocSpy::PreGetSize
  417. //
  418. //  Synopsis:   Called prior to OLE calling IMalloc::GetSize
  419. //
  420. //  Arguments:  [pRequest] -- The buffer whose size is to be returned
  421. //              [fSpyed]   -- Whether it was allocated with a spy active
  422. //
  423. //  Returns:    The actual buffer with which to call IMalloc::GetSize
  424. //
  425. //----------------------------------------------------------------------
  426. STDMETHODIMP_(void *) MallocSpy_PreGetSize(
  427.     LPMALLOCSPY this,
  428.     void *pRequest,
  429.     BOOL fSpyed)
  430. {
  431.     if (fSpyed)
  432.     {
  433.         return(PActualFromPUser(pRequest));
  434.     }else
  435.     {
  436.         return pRequest;
  437.     }
  438. }
  439. //+---------------------------------------------------------------------
  440. //
  441. //  Member:     CMallocSpy::PostGetSize
  442. //
  443. //  Synopsis:   Called after OLE calls IMalloc::GetSize
  444. //
  445. //  Arguments:  [cbActual] -- The result of IMalloc::GetSize
  446. //              [fSpyed]   -- Whether it was allocated with a spy active
  447. //
  448. //  Returns:    The size to return to the IMalloc::GetSize caller
  449. //
  450. //----------------------------------------------------------------------
  451. STDMETHODIMP_(ULONG) MallocSpy_PostGetSize(
  452.     LPMALLOCSPY this,
  453.     ULONG cbActual,
  454.     BOOL fSpyed)
  455. {
  456.     if (fSpyed)
  457.     {
  458.         return CbUserFromCbActual(cbActual);
  459.     }
  460.     else
  461.     {
  462.         return cbActual;
  463.     }
  464. }
  465. //+---------------------------------------------------------------------
  466. //
  467. //  Member:     CMallocSpy::PreDidAlloc
  468. //
  469. //  Synopsis:   Called prior to OLE calling IMalloc::DidAlloc
  470. //
  471. //  Arguments:  [pRequest] -- The buffer whose allocation is being tested
  472. //              [fSpyed]   -- Whether it was allocated with a spy active
  473. //
  474. //  Returns:    The buffer whose allocation is actually to be tested
  475. //
  476. //----------------------------------------------------------------------
  477. STDMETHODIMP_(void *) MallocSpy_PreDidAlloc(
  478.     LPMALLOCSPY this,
  479.     void *pRequest,
  480.     BOOL fSpyed)
  481. {
  482.     if (fSpyed)
  483.     {
  484.         return(PActualFromPUser(pRequest));
  485.     }
  486.     else
  487.     {
  488.         return pRequest;
  489.     }
  490. }
  491. //+---------------------------------------------------------------------
  492. //
  493. //  Function:   PostDidAlloc
  494. //
  495. //  Synopsis:   Called after OLE calls the IMalloc::DidAlloc
  496. //
  497. //  Arguments:  [pRequest] -- The passed allocation
  498. //              [fSpyed]   -- Whether it was allocated with a spy active
  499. //              [fActual]  -- The result of IMalloc::DidAlloc
  500. //
  501. //  Returns:    The result of IMalloc::DidAlloc
  502. //
  503. //----------------------------------------------------------------------
  504. STDMETHODIMP_(BOOL) MallocSpy_PostDidAlloc(
  505.     LPMALLOCSPY this,
  506.     void *pRequest,
  507.     BOOL fSpyed,
  508.     BOOL fActual)
  509. {
  510.     return fActual;
  511. }
  512. //+---------------------------------------------------------------------
  513. //
  514. //  Member:     CMallocSpy::PreHeapMinimize
  515. //
  516. //  Synopsis:   Called prior to OLE calling the IMalloc::HeapMinimize
  517. //
  518. //  Returns:
  519. //
  520. //----------------------------------------------------------------------
  521. STDMETHODIMP_(void) MallocSpy_PreHeapMinimize(
  522.     LPMALLOCSPY this)
  523. {
  524.     return;
  525. }
  526. //+---------------------------------------------------------------------
  527. //
  528. //  Member:     CMallocSpy::PostHeapMinimize
  529. //
  530. //  Synopsis:   Called after OLE calls the IMalloc::HeapMinimize
  531. //
  532. //  Returns:
  533. //
  534. //----------------------------------------------------------------------
  535. STDMETHODIMP_(void) MallocSpy_PostHeapMinimize(
  536.     LPMALLOCSPY this)
  537. {
  538.     return;
  539. }