home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / oledb / tablecopy / spy.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-12  |  14.1 KB  |  494 lines

  1. //-----------------------------------------------------------------------------
  2. // Microsoft OLE DB TABLECOPY Sample
  3. // Copyright (C) 1995-1998 Microsoft Corporation
  4. //
  5. // @doc
  6. //
  7. // @module SPY.CPP
  8. //
  9. //-----------------------------------------------------------------------------------
  10.  
  11. /////////////////////////////////////////////////////////////////////////////
  12. // Includes
  13. //
  14. /////////////////////////////////////////////////////////////////////////////
  15. #include "common.h"
  16. #include "spy.h"
  17.          
  18.  
  19. /////////////////////////////////////////////////////////////////////////////
  20. // Defines
  21. //
  22. /////////////////////////////////////////////////////////////////////////////
  23.  
  24. // HEADER + BUFFER + FOOTER
  25. // HEADER = HEADSIGNITURE + BUFFERSIZE + BUFFERID
  26. // FOOTER = TAILSIGNITURE
  27.  
  28. //All the header info must be ULONGs,
  29. //so that the user buffer falls on a word boundary
  30. //The tail must be a byte, since if it was a ULONG it would
  31. //also require a word boundary, but the users buffer could
  32. //be an odd number of bytes, so instead of rounding up, just use BYTE
  33.  
  34. const ULONG HEADSIZE    = sizeof(ULONG);  //HEADSIGNITURE
  35. const ULONG LENGTHSIZE    = sizeof(ULONG);  //BUFFERSIZE
  36. const ULONG IDSIZE        = sizeof(ULONG);  //BUFFERIF
  37. const ULONG TAILSIZE    = sizeof(BYTE);      //TAILSIGNITURE
  38.  
  39. const ULONG HEADERSIZE = ROUNDUP(HEADSIZE + LENGTHSIZE + IDSIZE);
  40. const ULONG FOOTERSIZE = TAILSIZE;
  41.  
  42. const BYTE  HEADSIGN = '{';
  43. const BYTE  TAILSIGN = '}';
  44.  
  45. const BYTE  ALLOCSIGN = '$';
  46. const BYTE  FREESIGN  = 'Z';
  47.  
  48. #define HEAD_OFFSET(pActual)        ((BYTE*)pActual)
  49. #define TAIL_OFFSET(pActual)        (USERS_OFFSET(pActual)+BUFFER_LENGTH(pActual))
  50.  
  51. #define USERS_OFFSET(pActual)        (HEAD_OFFSET(pActual) + HEADERSIZE)
  52. #define HEADER_OFFSET(pRequest)     ((BYTE*)(pRequest) - HEADERSIZE)    
  53.  
  54. #define LENGTH_OFFSET(pActual)        (HEAD_OFFSET(pActual) + HEADSIZE)    
  55. #define BUFFER_LENGTH(pActual)        (*(ULONG*)LENGTH_OFFSET(pActual))
  56.  
  57. #define ID_OFFSET(pActual)            (LENGTH_OFFSET(pActual) + LENGTHSIZE)
  58. #define BUFFER_ID(pActual)            (*(ULONG*)ID_OFFSET(pActual))
  59.  
  60. #define HEAD_SIGNITURE(pActual)        (*(ULONG*)HEAD_OFFSET(pActual))
  61. #define TAIL_SIGNITURE(pActual)        (*(BYTE*)TAIL_OFFSET(pActual))
  62.  
  63.  
  64. /////////////////////////////////////////////////////////////////////////////
  65. // CMallocSpy::CMallocSpy()
  66. //
  67. /////////////////////////////////////////////////////////////////////////////
  68. CMallocSpy::CMallocSpy()
  69. {
  70.     m_cRef = 0;
  71.     m_cbRequest = 0;
  72.  
  73.     //Have constructor AddRef, so ref count is init 1
  74.     //Release() is required
  75.     AddRef();
  76. }
  77.  
  78. /////////////////////////////////////////////////////////////////////////////
  79. // CMallocSpy::~CMallocSpy()
  80. //
  81. /////////////////////////////////////////////////////////////////////////////
  82. CMallocSpy::~CMallocSpy()
  83. {
  84.     //Remove all the elements of the list
  85.     CAllocList.RemoveAll();
  86. }
  87.  
  88.  
  89. /////////////////////////////////////////////////////////////////////////////
  90. // HRESULT CMallocSpy::AddToList
  91. //
  92. /////////////////////////////////////////////////////////////////////////////
  93. HRESULT CMallocSpy::AddToList(void* pv)
  94. {
  95.     ASSERT(pv);
  96.  
  97.     //Add this element to the list
  98.     CAllocList.AddTail(pv);
  99.     return S_OK;
  100. }
  101.  
  102.  
  103. /////////////////////////////////////////////////////////////////////////////
  104. // HRESULT CMallocSpy::RemoveFromList
  105. //
  106. /////////////////////////////////////////////////////////////////////////////
  107. HRESULT CMallocSpy::RemoveFromList(void* pv)
  108. {
  109.     ASSERT(pv);
  110.     
  111.     //Remove this element from the list
  112.     LISTPOS pos = CAllocList.Find(pv);
  113.     if(pos)
  114.         CAllocList.RemoveAt(pos);
  115.     return S_OK;
  116. }
  117.  
  118. /////////////////////////////////////////////////////////////////////////////
  119. // HRESULT CMallocSpy::DumpLeaks
  120. //
  121. /////////////////////////////////////////////////////////////////////////////
  122. HRESULT CMallocSpy::DumpLeaks()
  123. {
  124.     ULONG ulTotalLeaked = 0;
  125.  
  126.     //Display Leaks to the Output Window
  127.     while(!CAllocList.IsEmpty())
  128.     {    
  129.         //Obtain the pointer to the leaked memory
  130.         void* pRequest = CAllocList.RemoveHead();
  131.         ASSERT(pRequest);
  132.         
  133.         void* pActual = HEADER_OFFSET(pRequest);
  134.         ASSERT(pActual);
  135.  
  136.         //Make sure that the head/tail signitures are intact
  137.         if(HEAD_SIGNITURE(pActual) != HEADSIGN)
  138.             TRACE(L"-- IMallocSpy HeadSigniture Corrupted! - 0x%08x, ID=%08lu, %lu bytes\n", pRequest, BUFFER_ID(pActual), BUFFER_LENGTH(pActual));
  139.  
  140.         if(TAIL_SIGNITURE(pActual) != TAILSIGN)
  141.             TRACE(L"-- IMallocSpy TailSigniture Corrupted! - 0x%08x, ID=%08lu, %lu bytes\n", pRequest, BUFFER_ID(pActual), BUFFER_LENGTH(pActual));
  142.  
  143.         ULONG ulSize = BUFFER_LENGTH(pActual);
  144.         ULONG ulID     = BUFFER_ID(pActual);
  145.         
  146.         TRACE(L"-- IMallocSpy LEAK! - 0x%08x, ID=%08lu, %lu bytes\n", pRequest, ulID, ulSize);
  147.         ulTotalLeaked += ulSize;
  148.  
  149.         //Free the Leak
  150.         //You really cant free the leak since the app could be potentially still
  151.         //using it.  Or the DLL may still be in use or have attached threads...
  152.         //SAFE_FREE(pActual);
  153.     }
  154.  
  155.     if(ulTotalLeaked)
  156.         TRACE(L"-- IMallocSpy Total LEAKED! - %lu bytes\n", ulTotalLeaked);
  157.  
  158.     return S_OK;
  159. }
  160.  
  161. /////////////////////////////////////////////////////////////////////////////
  162. // HRESULT CMallocSpy::QueryInterface
  163. //
  164. /////////////////////////////////////////////////////////////////////////////
  165. HRESULT CMallocSpy::QueryInterface(REFIID riid, void** ppIUnknown)
  166. {
  167.     if(!ppIUnknown)
  168.         return E_INVALIDARG;
  169.     
  170.     *ppIUnknown = NULL;
  171.  
  172.     //IID_IUnknown
  173.     if(riid == IID_IUnknown)
  174.         *ppIUnknown = this;
  175.     //IDD_IMallocSpy
  176.     else if(riid == IID_IMallocSpy)
  177.          *ppIUnknown =  this;
  178.     
  179.     if(*ppIUnknown)
  180.     {
  181.         ((IUnknown*)*ppIUnknown)->AddRef();
  182.         return S_OK;
  183.     }
  184.  
  185.     return E_NOINTERFACE;
  186. }
  187.  
  188. /////////////////////////////////////////////////////////////////////////////
  189. // ULONG CMallocSpy::AddRef
  190. //
  191. /////////////////////////////////////////////////////////////////////////////
  192. ULONG CMallocSpy::AddRef()
  193. {
  194.     return ++m_cRef;
  195. }
  196.  
  197. /////////////////////////////////////////////////////////////////////////////
  198. // ULONG CMallocSpy::Release
  199. //
  200. /////////////////////////////////////////////////////////////////////////////
  201. ULONG CMallocSpy::Release()
  202. {
  203.     if(--m_cRef)
  204.         return m_cRef;
  205.  
  206.     TRACE(L"Releasing IMallocSpy\n");
  207.  
  208.     delete this;
  209.     return 0;
  210. }
  211.  
  212.  
  213. /////////////////////////////////////////////////////////////////////////////
  214. // ULONG CMallocSpy::PreAlloc
  215. //
  216. /////////////////////////////////////////////////////////////////////////////
  217. ULONG CMallocSpy::PreAlloc(ULONG cbRequest)
  218. {
  219.     //cbRequest is the orginal number of bytes requested by the user
  220.     //Store the users requested size
  221.     m_cbRequest = cbRequest;
  222.  
  223.     //Return the total size requested, plus extra for header/footer
  224.     return (m_cbRequest + HEADERSIZE + FOOTERSIZE);
  225. }
  226.  
  227. /////////////////////////////////////////////////////////////////////////////
  228. // void* CMallocSpy::PostAlloc
  229. //
  230. /////////////////////////////////////////////////////////////////////////////
  231. void* CMallocSpy::PostAlloc(void* pActual)
  232. {
  233.     //pActual is the pointer to the head of the buffer, including the header
  234.     //Add the users pointer to the list
  235.     AddToList(USERS_OFFSET(pActual));
  236.  
  237.     //Place the HeadSigniture in the HEADER
  238.     HEAD_SIGNITURE(pActual) = HEADSIGN;
  239.     
  240.     //Place the Size in the HEADER
  241.     BUFFER_LENGTH(pActual) = m_cbRequest;
  242.  
  243.     //Place the ID in the HEADER
  244.     static ULONG ulID = 0;
  245.     BUFFER_ID(pActual) = ++ulID;
  246.  
  247.     //Set the UsersBuffer to a known char
  248.     memset(USERS_OFFSET(pActual), ALLOCSIGN, m_cbRequest);
  249.  
  250.     //Place the TailSigniture in the HEADER
  251.     TAIL_SIGNITURE(pActual) = TAILSIGN;
  252.  
  253. #ifdef FINDLEAKS
  254.     TRACE(L"-- IMallocSpy Alloc - 0x%08x, ID=%08lu, %lu bytes\n", USERS_OFFSET(pActual), ulID, m_cbRequest);
  255. #endif // FINDLEAKS
  256.  
  257.     // Return the actual users buffer
  258.     return USERS_OFFSET(pActual);
  259. }
  260.  
  261. /////////////////////////////////////////////////////////////////////////////
  262. // void* CMallocSpy::PreFree
  263. //
  264. /////////////////////////////////////////////////////////////////////////////
  265. void* CMallocSpy::PreFree(void* pRequest, BOOL fSpyed)
  266. {
  267.     //pRequest is the users pointer to thier buffer, not the header
  268.  
  269.     // Check for NULL
  270.     if(pRequest == NULL)
  271.         return NULL;
  272.  
  273.     //If this memory was alloced under IMallocSpy, need to remove it
  274.     if(fSpyed)
  275.     {
  276.         //Remove this pointer from the list
  277.         RemoveFromList(pRequest);
  278.     
  279.         void* pActual = HEADER_OFFSET(pRequest);
  280.         
  281.         //Make sure that the head/tail signitures are intact
  282.         if(HEAD_SIGNITURE(pActual) != HEADSIGN)
  283.             TRACE(L"-- IMallocSpy HeadSigniture Corrupted! - 0x%08x, ID=%08lu, %lu bytes\n", pRequest, BUFFER_ID(pActual), BUFFER_LENGTH(pActual));
  284.  
  285.         if(TAIL_SIGNITURE(pActual) != TAILSIGN)
  286.             TRACE(L"-- IMallocSpy TailSigniture Corrupted! - 0x%08x, ID=%08lu, %lu bytes\n", pRequest, BUFFER_ID(pActual), BUFFER_LENGTH(pActual));
  287.  
  288.         //Set the UsersBuffer to a known char
  289.         memset(pRequest, FREESIGN, BUFFER_LENGTH(pActual));
  290.  
  291.         //Need to return the actual header pointer to
  292.         //free the entire buffer including the heading
  293.         return pActual;
  294.     }
  295.  
  296.     //else
  297.     return pRequest;
  298. }
  299.  
  300.  
  301. /////////////////////////////////////////////////////////////////////////////
  302. // void CMallocSpy::PostFree
  303. //
  304. /////////////////////////////////////////////////////////////////////////////
  305. void CMallocSpy::PostFree(BOOL fSpyed)
  306. {
  307.     // Note the free or whatever
  308.     return;
  309. }
  310.  
  311.  
  312. /////////////////////////////////////////////////////////////////////////////
  313. // ULONG CMallocSpy::PreRealloc
  314. //
  315. /////////////////////////////////////////////////////////////////////////////
  316. ULONG CMallocSpy::PreRealloc(void* pRequest, ULONG cbRequest,
  317.                              void** ppNewRequest, BOOL fSpyed)
  318. {
  319.     ASSERT(pRequest && ppNewRequest);
  320.     
  321.     //If this was alloced under IMallocSpy we need to adjust
  322.     //the size stored in the header
  323.     if(fSpyed)
  324.     {
  325.         //Remove the original pRequest pointer from the list
  326.         //Since Realloc could change the original pointer
  327.         RemoveFromList(pRequest);
  328.     
  329.         //Find the start 
  330.         *ppNewRequest = HEADER_OFFSET(pRequest);
  331.         
  332.         //Store the new desired size
  333.         m_cbRequest = cbRequest;
  334.         
  335.         //Return the total size, including extra
  336.         return (m_cbRequest + HEADERSIZE + FOOTERSIZE);
  337.     }
  338.  
  339.     //else
  340.     *ppNewRequest = pRequest;
  341.     return cbRequest;
  342. }
  343.  
  344.  
  345. /////////////////////////////////////////////////////////////////////////////
  346. // void* CMallocSpy::PostRealloc
  347. //
  348. /////////////////////////////////////////////////////////////////////////////
  349. void* CMallocSpy::PostRealloc(void* pActual, BOOL fSpyed)
  350. {
  351.     //If this buffer was alloced under IMallocSpy
  352.     if(fSpyed)
  353.     {
  354.         //pActual is the pointer to header
  355.         //Add the new pointer to the list
  356.         AddToList(USERS_OFFSET(pActual));
  357.  
  358.         //HeadSigniture should still be intact
  359.         if(HEAD_SIGNITURE(pActual) != HEADSIGN)
  360.             TRACE(L"-- IMallocSpy HeadSigniture Corrupted! - 0x%08x, ID=%08lu, %lu bytes\n", USERS_OFFSET(pActual), BUFFER_ID(pActual), BUFFER_LENGTH(pActual));
  361.         
  362.         //ID should still be intact
  363.  
  364.         //Place the new Size in the HEADER
  365.         BUFFER_LENGTH(pActual) = m_cbRequest;
  366.  
  367.         //Need to place the tail signiture again, 
  368.         //since it will be over written by the realloc
  369.         TAIL_SIGNITURE(pActual) = TAILSIGN;
  370.  
  371. #ifdef FINDLEAKS
  372.         TRACE(L"-- IMallocSpy Realloc - 0x%08x, ID=%08lu, %lu bytes\n", USERS_OFFSET(pActual), BUFFER_ID(pActual), m_cbRequest);
  373. #endif // FINDLEAKS
  374.  
  375.         //Return the actual "user" buffer
  376.         return USERS_OFFSET(pActual);
  377.     }
  378.     
  379.     //else
  380.     return pActual;
  381. }
  382.  
  383.  
  384. /////////////////////////////////////////////////////////////////////////////
  385. // void* CMallocSpy::PreGetSize
  386. //
  387. /////////////////////////////////////////////////////////////////////////////
  388. void* CMallocSpy::PreGetSize(void* pRequest, BOOL fSpyed)
  389. {
  390.     if (fSpyed)
  391.         return HEADER_OFFSET(pRequest);
  392.  
  393.     return pRequest;
  394. }
  395.  
  396.  
  397.  
  398. /////////////////////////////////////////////////////////////////////////////
  399. // ULONG CMallocSpy::PostGetSize
  400. //
  401. /////////////////////////////////////////////////////////////////////////////
  402. ULONG CMallocSpy::PostGetSize(ULONG cbActual, BOOL fSpyed)
  403. {
  404.     if (fSpyed)
  405.         return cbActual - HEADERSIZE - FOOTERSIZE;
  406.  
  407.     return cbActual;
  408. }
  409.  
  410.  
  411.  
  412.  
  413. /////////////////////////////////////////////////////////////////////////////
  414. // void* CMallocSpy::PreDidAlloc
  415. //
  416. /////////////////////////////////////////////////////////////////////////////
  417. void* CMallocSpy::PreDidAlloc(void* pRequest, BOOL fSpyed)
  418. {
  419.     if (fSpyed)
  420.         return HEADER_OFFSET(pRequest);
  421.  
  422.     return pRequest;
  423. }
  424.  
  425.  
  426. /////////////////////////////////////////////////////////////////////////////
  427. // BOOL CMallocSpy::PostDidAlloc
  428. //
  429. /////////////////////////////////////////////////////////////////////////////
  430. BOOL CMallocSpy::PostDidAlloc(void* pRequest, BOOL fSpyed, BOOL fActual)
  431. {
  432.     return fActual;
  433. }
  434.  
  435.  
  436.  
  437. /////////////////////////////////////////////////////////////////////////////
  438. // void CMallocSpy::PreHeapMinimize
  439. //
  440. /////////////////////////////////////////////////////////////////////////////
  441. void CMallocSpy::PreHeapMinimize()
  442. {
  443.     // We don't do anything here
  444.     return;
  445. }
  446.  
  447.  
  448. /////////////////////////////////////////////////////////////////////////////
  449. // void CMallocSpy::PostHeapMinimize
  450. //
  451. /////////////////////////////////////////////////////////////////////////////
  452. void CMallocSpy::PostHeapMinimize()
  453. {
  454.     // We don't do anything here
  455.     return;
  456. }
  457.  
  458. /////////////////////////////////////////////////////////////////////////////
  459. // Resgistration
  460. //
  461. /////////////////////////////////////////////////////////////////////////////
  462.  
  463. #ifdef _DEBUG
  464. HRESULT MallocSpyRegister(CMallocSpy** ppCMallocSpy)
  465. {
  466.     ASSERT(ppCMallocSpy);
  467.     
  468.     //Allocate Interface
  469.     *ppCMallocSpy = new CMallocSpy(); //Constructor AddRef's
  470.     
  471.     //Regisiter Interface
  472.     return CoRegisterMallocSpy(*ppCMallocSpy); // Does an AddRef on Object
  473. }
  474.  
  475. HRESULT MallocSpyUnRegister(CMallocSpy* pCMallocSpy)
  476. {
  477.     ASSERT(pCMallocSpy);
  478.     return CoRevokeMallocSpy(); //Does a Release on Object
  479. }
  480.  
  481. HRESULT MallocSpyDump(CMallocSpy* pCMallocSpy)
  482. {
  483.     ASSERT(pCMallocSpy);
  484.     return pCMallocSpy->DumpLeaks(); 
  485. }
  486.  
  487. #else
  488. HRESULT MallocSpyRegister(CMallocSpy** ppCMallocSpy) {    return S_OK; };
  489. HRESULT MallocSpyUnRegister(CMallocSpy* pCMallocSpy) {    return S_OK; };
  490. HRESULT MallocSpyDump(CMallocSpy* pCMallocSpy)          { return S_OK; };
  491. #endif //DEBUG
  492.  
  493.  
  494.