Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

544 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Net Library System
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997.
  5. //
  6. // File: spy.cxx
  7. //
  8. // Contents: This file contains the implementation of the IMalloc Spy
  9. // interface that uses the memory leak tracking stuff ported
  10. // from Content Index to give stack traces of OLE memory
  11. // allocations that are not freed. This class has been
  12. // modified after copying from the TABLECOPY sample in oledb
  13. // samples to make use of Content Index's heap tracking
  14. // software.
  15. //
  16. // History: 10-05-97 srikants Created
  17. //
  18. //----------------------------------------------------------------------------
  19. #include <pch.cxx>
  20. #pragma hdrstop
  21. /////////////////////////////////////////////////////////////////////////////
  22. // Includes
  23. //
  24. /////////////////////////////////////////////////////////////////////////////
  25. #include <spy.hxx>
  26. #include <tracheap.h>
  27. #include <alocdbg.hxx>
  28. #if CIDBG==1 || DBG==1
  29. DECLARE_DEBUG( heap );
  30. #define heapDebugOut(x) heapInlineDebugOut x
  31. /////////////////////////////////////////////////////////////////////////////
  32. // Defines
  33. //
  34. /////////////////////////////////////////////////////////////////////////////
  35. // AHeader + BUFFER + FOOTER
  36. // FOOTER = TAILSIGNITURE
  37. //All the header info must be ULONGs,
  38. //so that the user buffer falls on a word boundary
  39. //The tail must be a byte, since if it was a ULONG it would
  40. //also require a word boundary, but the users buffer could
  41. //be an odd number of bytes, so instead of rounding up, just use BYTE
  42. const ULONG HEADSIZE = sizeof(AHeader); //HEADSIGNITURE
  43. const ULONG TAILSIZE = sizeof(BYTE); //TAILSIGNITURE
  44. const ULONG HEADERSIZE = ROUNDUP(HEADSIZE);
  45. const ULONG FOOTERSIZE = TAILSIZE;
  46. const BYTE ALLOCSIGN = '$';
  47. const BYTE FREESIGN = 'Z';
  48. #define HEAD_OFFSET(pHeader) ((BYTE*)pHeader)
  49. #define TAIL_OFFSET(pHeader) (USERS_OFFSET(pHeader)+ (AHeader *)pHeader->size)
  50. #define USERS_OFFSET(pHeader) (HEAD_OFFSET(pHeader) + HEADERSIZE)
  51. #define HEADER_OFFSET(pUserBuffer) ((BYTE*)(pUserBuffer) - HEADERSIZE)
  52. #define TAIL_SIGNITURE(pHeader) (*(BYTE*)TAIL_OFFSET(pHeader))
  53. static AllocArena * pAllocArena = (AllocArena *) -1;
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CMallocSpy::CMallocSpy()
  56. //
  57. /////////////////////////////////////////////////////////////////////////////
  58. CMallocSpy::CMallocSpy() :
  59. m_cRef( 1 ), // implicit AddRef()
  60. m_cbRequest( 0 )
  61. {
  62. }
  63. /////////////////////////////////////////////////////////////////////////////
  64. // CMallocSpy::~CMallocSpy()
  65. //
  66. /////////////////////////////////////////////////////////////////////////////
  67. CMallocSpy::~CMallocSpy()
  68. {
  69. //Remove all the elements of the list
  70. //CAllocList.RemoveAll();
  71. }
  72. /////////////////////////////////////////////////////////////////////////////
  73. // BOOL CMallocSpy::Add
  74. //
  75. /////////////////////////////////////////////////////////////////////////////
  76. BOOL CMallocSpy::Add(void* pv)
  77. {
  78. Win4Assert(pv);
  79. //Add this element to the list
  80. //CAllocList.AddTail(pv);
  81. return TRUE;
  82. }
  83. /////////////////////////////////////////////////////////////////////////////
  84. // BOOL CMallocSpy::Remove
  85. //
  86. /////////////////////////////////////////////////////////////////////////////
  87. BOOL CMallocSpy::Remove(void* pv)
  88. {
  89. Win4Assert(pv);
  90. //Remove this element from the list
  91. //CAllocList.RemoveAt(CAllocList.Find(pv));
  92. return TRUE;
  93. }
  94. /////////////////////////////////////////////////////////////////////////////
  95. // BOOL CMallocSpy::DumpLeaks
  96. //
  97. /////////////////////////////////////////////////////////////////////////////
  98. BOOL CMallocSpy::DumpLeaks()
  99. {
  100. #if 0
  101. ULONG ulTotalLeaked = 0;
  102. //Display Leaks to the Output Window
  103. while(!CAllocList.IsEmpty())
  104. {
  105. //Obtain the pointer to the leaked memory
  106. void* pUsersBuffer = CAllocList.RemoveHead();
  107. Win4Assert(pUsersBuffer);
  108. void* pHeader = HEADER_OFFSET(pUsersBuffer);
  109. Win4Assert(pHeader);
  110. //Make sure that the head/tail signitures are intact
  111. if(HEAD_SIGNITURE(pHeader) != HEADSIGN)
  112. heapDebugOut((DEB_ERROR, "-- IMallocSpy HeadSigniture Corrupted! - 0x%08x, ID=%08lu, %lu bytes\n",
  113. pUsersBuffer,
  114. BUFFER_ID(pHeader),
  115. BUFFER_LENGTH(pHeader)));
  116. if(TAIL_SIGNITURE(pHeader) != TAILSIGN)
  117. heapDebugOut((DEB_ERROR, "-- IMallocSpy TailSigniture Corrupted! - 0x%08x, ID=%08lu, %lu bytes\n",
  118. pUsersBuffer, BUFFER_ID(pHeader), BUFFER_LENGTH(pHeader)) );
  119. ULONG ulSize = BUFFER_LENGTH(pHeader);
  120. ULONG ulID = BUFFER_ID(pHeader);
  121. heapDebugOut(( DEB_ERROR, "-- IMallocSpy LEAK! - 0x%08x, ID=%08lu, %lu bytes\n",
  122. pUsersBuffer, ulID, ulSize));
  123. ulTotalLeaked += ulSize;
  124. }
  125. if(ulTotalLeaked)
  126. heapDebugOut(( DEB_ERROR, "-- IMallocSpy Total LEAKED! - %lu bytes\n", ulTotalLeaked));
  127. #endif // 0
  128. return TRUE;
  129. }
  130. /////////////////////////////////////////////////////////////////////////////
  131. // HRESULT CMallocSpy::QueryInterface
  132. //
  133. /////////////////////////////////////////////////////////////////////////////
  134. HRESULT CMallocSpy::QueryInterface(REFIID riid, void** ppIUnknown)
  135. {
  136. if(!ppIUnknown)
  137. return E_INVALIDARG;
  138. *ppIUnknown = NULL;
  139. //IID_IUnknown
  140. if(riid == IID_IUnknown)
  141. *ppIUnknown = this;
  142. //IDD_IMallocSpy
  143. else if(riid == IID_IMallocSpy)
  144. *ppIUnknown = this;
  145. if(*ppIUnknown)
  146. {
  147. ((IUnknown*)*ppIUnknown)->AddRef();
  148. return S_OK;
  149. }
  150. return E_NOINTERFACE;
  151. }
  152. /////////////////////////////////////////////////////////////////////////////
  153. // ULONG CMallocSpy::AddRef
  154. //
  155. /////////////////////////////////////////////////////////////////////////////
  156. ULONG CMallocSpy::AddRef()
  157. {
  158. return ++m_cRef;
  159. }
  160. /////////////////////////////////////////////////////////////////////////////
  161. // ULONG CMallocSpy::Release
  162. //
  163. /////////////////////////////////////////////////////////////////////////////
  164. ULONG CMallocSpy::Release()
  165. {
  166. if(--m_cRef)
  167. return m_cRef;
  168. heapDebugOut(( DEB_TRACE, "Releasing IMallocSpy\n" ));
  169. delete this;
  170. return 0;
  171. }
  172. /////////////////////////////////////////////////////////////////////////////
  173. // ULONG CMallocSpy::PreAlloc
  174. //
  175. /////////////////////////////////////////////////////////////////////////////
  176. SIZE_T CMallocSpy::PreAlloc(SIZE_T cbRequest)
  177. {
  178. //cbRequest is the orginal number of bytes requested by the user
  179. //Store the users requested size
  180. m_cbRequest = cbRequest;
  181. //Return the total size requested, plus extra for header/footer
  182. return (m_cbRequest + sizeof AHeader + 1);
  183. }
  184. /////////////////////////////////////////////////////////////////////////////
  185. // void* CMallocSpy::PostAlloc
  186. //
  187. /////////////////////////////////////////////////////////////////////////////
  188. void* CMallocSpy::PostAlloc(void* pHeader)
  189. {
  190. //pHeader is the pointer to the head of the buffer, including the header
  191. if (pHeader)
  192. {
  193. //Place the Size in the HEADER
  194. ((AHeader *)pHeader)->size = m_cbRequest;
  195. ((AHeader *)pHeader)->p = AllocArenaRecordAlloc( pAllocArena, m_cbRequest );
  196. pHeader = (AHeader *)pHeader + 1;
  197. //Place the TailSigniture in the HEADER
  198. *((char *)pHeader + m_cbRequest ) = ALLOC_SIGNATURE;
  199. //Set the UsersBuffer to a known char
  200. memset(pHeader, ALLOCSIGN, m_cbRequest);
  201. #ifdef FINDLEAKS
  202. heapDebugOut((DEB_ITRACE, "-- IMallocSpy Alloc - 0x%08x, ID=%08lu, %lu bytes\n", pHeader, ulID, m_cbRequest));
  203. #endif // FINDLEAKS
  204. }
  205. // Return the actual users buffer
  206. return pHeader;
  207. }
  208. /////////////////////////////////////////////////////////////////////////////
  209. // void* CMallocSpy::PreFree
  210. //
  211. /////////////////////////////////////////////////////////////////////////////
  212. void* CMallocSpy::PreFree(void* pUsersBuffer, BOOL fSpyed)
  213. {
  214. //pUsersBuffer is the users pointer to thier buffer, not the header
  215. // Check for NULL
  216. if(pUsersBuffer == NULL)
  217. return NULL;
  218. //If this memory was alloced under IMallocSpy, need to remove it
  219. if(fSpyed)
  220. {
  221. //Remove this pointer form the list
  222. //Remove(pUsersBuffer);
  223. AHeader *ap = (AHeader *)pUsersBuffer - 1;
  224. switch( *((char *)pUsersBuffer + ap->size) )
  225. {
  226. case ALLOC_SIGNATURE:
  227. break;
  228. case FREE_SIGNATURE:
  229. heapDebugOut((DEB_WARN, "Double deleted memory at %#x\n", pUsersBuffer ));
  230. AllocArenaDumpRecord( ap->p );
  231. Win4Assert( !"Probable double delete" );
  232. break;
  233. default:
  234. heapDebugOut((DEB_WARN, "Overrun memory at %#x\n", pUsersBuffer ));
  235. AllocArenaDumpRecord( ap->p );
  236. Win4Assert( !"Probable overrun heap block" );
  237. break;
  238. }
  239. *((char *)pUsersBuffer + ap->size) = FREE_SIGNATURE;
  240. if ( 0 != ap->p )
  241. AllocArenaRecordFree( ap->p, ap->size );
  242. // memset( pUsersBuffer, FREESIGN, ap->size + HEADERSIZE );
  243. pUsersBuffer = (void *) ap;
  244. }
  245. //else
  246. return pUsersBuffer;
  247. }
  248. /////////////////////////////////////////////////////////////////////////////
  249. // void CMallocSpy::PostFree
  250. //
  251. /////////////////////////////////////////////////////////////////////////////
  252. void CMallocSpy::PostFree(BOOL fSpyed)
  253. {
  254. // Note the free or whatever
  255. return;
  256. }
  257. /////////////////////////////////////////////////////////////////////////////
  258. // ULONG CMallocSpy::PreRealloc
  259. //
  260. /////////////////////////////////////////////////////////////////////////////
  261. SIZE_T CMallocSpy::PreRealloc( void* pUsersBuffer, SIZE_T cbRequest,
  262. void** ppNewRequest, BOOL fSpyed)
  263. {
  264. Win4Assert(pUsersBuffer && ppNewRequest);
  265. //If this was alloced under IMallocSpy we need to adjust
  266. //the size stored in the header
  267. if(fSpyed)
  268. {
  269. AHeader *ap = (AHeader *)pUsersBuffer - 1;
  270. //Find the start
  271. *ppNewRequest = (void *) ap;
  272. //Store the new desired size
  273. m_cbRequest = cbRequest;
  274. //Return the total size, including extra
  275. return (m_cbRequest + sizeof AHeader + 1);
  276. }
  277. //else
  278. *ppNewRequest = pUsersBuffer;
  279. return cbRequest;
  280. }
  281. /////////////////////////////////////////////////////////////////////////////
  282. // void* CMallocSpy::PostRealloc
  283. //
  284. /////////////////////////////////////////////////////////////////////////////
  285. void* CMallocSpy::PostRealloc(void* pHeader, BOOL fSpyed)
  286. {
  287. //If this buffer was alloced under IMallocSpy
  288. if(fSpyed)
  289. {
  290. AHeader *ap = (AHeader *)pHeader;
  291. void * pUsersBuffer = (AHeader *)pHeader + 1;
  292. if ( m_cbRequest >= ap->size )
  293. {
  294. switch( *((char *)pUsersBuffer + ap->size) )
  295. {
  296. case ALLOC_SIGNATURE:
  297. break;
  298. case FREE_SIGNATURE:
  299. heapDebugOut((DEB_WARN, "Double deleted memory at %#x\n", pUsersBuffer ));
  300. AllocArenaDumpRecord( ap->p );
  301. Win4Assert( !"Probable double delete" );
  302. break;
  303. default:
  304. heapDebugOut((DEB_WARN, "Overrun memory at %#x\n", pUsersBuffer ));
  305. AllocArenaDumpRecord( ap->p );
  306. Win4Assert( !"Probable overrun heap block" );
  307. break;
  308. }
  309. }
  310. if ( 0 != ap->p )
  311. AllocArenaRecordReAlloc( ap->p, ap->size, m_cbRequest );
  312. ap->size = m_cbRequest;
  313. // Position for the user's buffer.
  314. pHeader = pUsersBuffer;
  315. //Place the TailSigniture in the HEADER
  316. *((char *)pHeader + m_cbRequest ) = ALLOC_SIGNATURE;
  317. }
  318. //else
  319. return pHeader;
  320. }
  321. /////////////////////////////////////////////////////////////////////////////
  322. // void* CMallocSpy::PreGetSize
  323. //
  324. /////////////////////////////////////////////////////////////////////////////
  325. void* CMallocSpy::PreGetSize(void* pUsersBuffer, BOOL fSpyed)
  326. {
  327. if (fSpyed)
  328. {
  329. AHeader *ap = (AHeader *)pUsersBuffer - 1;
  330. return ap;
  331. }
  332. return pUsersBuffer;
  333. }
  334. /////////////////////////////////////////////////////////////////////////////
  335. // ULONG CMallocSpy::PostGetSize
  336. //
  337. /////////////////////////////////////////////////////////////////////////////
  338. SIZE_T CMallocSpy::PostGetSize(SIZE_T cbActual, BOOL fSpyed)
  339. {
  340. if (fSpyed)
  341. {
  342. return cbActual - HEADERSIZE - FOOTERSIZE;
  343. }
  344. return cbActual;
  345. }
  346. /////////////////////////////////////////////////////////////////////////////
  347. // void* CMallocSpy::PreDidAlloc
  348. //
  349. /////////////////////////////////////////////////////////////////////////////
  350. void* CMallocSpy::PreDidAlloc(void* pUsersBuffer, BOOL fSpyed)
  351. {
  352. if (fSpyed)
  353. {
  354. AHeader *ap = (AHeader *)pUsersBuffer - 1;
  355. return ap;
  356. }
  357. return pUsersBuffer;
  358. }
  359. /////////////////////////////////////////////////////////////////////////////
  360. // BOOL CMallocSpy::PostDidAlloc
  361. //
  362. /////////////////////////////////////////////////////////////////////////////
  363. BOOL CMallocSpy::PostDidAlloc(void* pRequest, BOOL fSpyed, BOOL fActual)
  364. {
  365. return fActual;
  366. }
  367. /////////////////////////////////////////////////////////////////////////////
  368. // void CMallocSpy::PreHeapMinimize
  369. //
  370. /////////////////////////////////////////////////////////////////////////////
  371. void CMallocSpy::PreHeapMinimize()
  372. {
  373. // We don't do anything here
  374. return;
  375. }
  376. /////////////////////////////////////////////////////////////////////////////
  377. // void CMallocSpy::PostHeapMinimize
  378. //
  379. /////////////////////////////////////////////////////////////////////////////
  380. void CMallocSpy::PostHeapMinimize()
  381. {
  382. // We don't do anything here
  383. return;
  384. }
  385. /////////////////////////////////////////////////////////////////////////////
  386. // Resgistration
  387. //
  388. /////////////////////////////////////////////////////////////////////////////
  389. void MallocSpyRegister(CMallocSpy** ppCMallocSpy)
  390. {
  391. // CoInitializeEx(NULL, COINIT_MULTITHREADED);
  392. Win4Assert(ppCMallocSpy);
  393. // Win4Assert( !"Break In" );
  394. //Allocate Interface
  395. *ppCMallocSpy = new CMallocSpy(); //Constructor AddRef's
  396. //Regisiter Interface
  397. HRESULT hr = CoRegisterMallocSpy(*ppCMallocSpy); // Does an AddRef on Object
  398. heapDebugOut(( DEB_WARN, "CoRegisterMallocSpy returned 0x%X\n", hr ));
  399. if ( FAILED(hr) )
  400. {
  401. (*ppCMallocSpy)->Release();
  402. *ppCMallocSpy = 0;
  403. return;
  404. }
  405. Win4Assert( pAllocArena == (AllocArena *) -1 );
  406. if ( pAllocArena == (AllocArena *) -1 )
  407. {
  408. pAllocArena = AllocArenaCreate( MEMCTX_TASK,
  409. "IMalloc allocator");
  410. // atexit( HeapExit );
  411. }
  412. // CoUninitialize();
  413. }
  414. void MallocSpyUnRegister(CMallocSpy* pCMallocSpy)
  415. {
  416. // CoInitializeEx(NULL, COINIT_MULTITHREADED);
  417. // Win4Assert();
  418. CoRevokeMallocSpy(); //Does a Release on Object
  419. // CoUninitialize();
  420. }
  421. void MallocSpyDump(CMallocSpy* pCMallocSpy)
  422. {
  423. Win4Assert(pCMallocSpy);
  424. pCMallocSpy->DumpLeaks();
  425. }
  426. #else
  427. void MallocSpyRegister(CMallocSpy** ppCMallocSpy) { return; };
  428. void MallocSpyUnRegister(CMallocSpy* pCMallocSpy) { return; };
  429. void MallocSpyDump(CMallocSpy* pCMallocSpy) { return; };
  430. #endif //CIDBG==1 || DBG==1