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

Windows编程

开发平台:

Visual C++

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