Source code of Windows XP (NT5)
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.

1221 lines
22 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: alloc.cpp
  7. //
  8. // Contents: Cert Server debug implementation
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include <assert.h>
  14. #define __dwFILE__ __dwFILE_CERTCLIB_ALLOC_CPP__
  15. #if DBG_CERTSRV
  16. #undef FormatMessageW
  17. #undef LocalAlloc
  18. #undef LocalReAlloc
  19. #undef LocalFree
  20. #undef CoTaskMemAlloc
  21. #undef CoTaskMemRealloc
  22. #undef CoTaskMemFree
  23. #undef StringFromCLSID
  24. #undef StringFromIID
  25. #undef SysAllocString
  26. #undef SysReAllocString
  27. #undef SysAllocStringLen
  28. #undef SysReAllocStringLen
  29. #undef SysFreeString
  30. #undef SysAllocStringByteLen
  31. #undef PropVariantClear
  32. #undef VariantClear
  33. #undef VariantChangeType
  34. #undef VariantChangeTypeEx
  35. DWORD g_MemTrack = 0;
  36. #define MTF_UNREGISTERED 0x00000002
  37. #define MTF_ALLOCTRACE 0x00000004
  38. #define MTF_FREETRACE 0x00000008
  39. #define MTF_STACKTRACE 0x00000010
  40. typedef struct _RMALLOC
  41. {
  42. LONG cAlloc;
  43. LONG cAllocTotal;
  44. } RMALLOC;
  45. RMALLOC g_armAlloc[CSM_MAX];
  46. #define C_BP_FRAME 16
  47. #define C_BACK_TRACE_CHUNK 100
  48. #define C_MEM_HEADER_CHUNK 100
  49. typedef struct _BACKTRACE
  50. {
  51. LONG cAlloc; // count of outstanding allocations
  52. LONG cAllocTotal; // count of total allocations
  53. LONG cbAlloc; // size of outstanding allocations
  54. LONG cbAllocTotal; // size of total allocations
  55. ULONG apCaller[C_BP_FRAME]; // stack trace
  56. } BACKTRACE;
  57. typedef struct _MEMHEADER
  58. {
  59. DWORD iBackTrace; // backtrace index
  60. VOID const *pvMemory; // Pointer to memory block allocated
  61. LONG cbMemory; // Size of memory block allocated
  62. DWORD Flags; // Allocator flags
  63. } MEMHEADER;
  64. // critical section around myRegister APIs since they
  65. // operate on global data structures
  66. CRITICAL_SECTION g_critsecRegisterMemory;
  67. BOOL g_fRegisterMemoryCritSecInit = FALSE;
  68. VOID
  69. RegisterMemoryEnterCriticalSection(VOID)
  70. {
  71. HRESULT hr;
  72. __try
  73. {
  74. if (!g_fRegisterMemoryCritSecInit)
  75. {
  76. InitializeCriticalSection(&g_critsecRegisterMemory);
  77. g_fRegisterMemoryCritSecInit = TRUE;
  78. }
  79. EnterCriticalSection(&g_critsecRegisterMemory);
  80. }
  81. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  82. {
  83. }
  84. }
  85. VOID
  86. RegisterMemoryLeaveCriticalSection(VOID)
  87. {
  88. if (g_fRegisterMemoryCritSecInit)
  89. {
  90. LeaveCriticalSection(&g_critsecRegisterMemory);
  91. }
  92. }
  93. BACKTRACE *g_rgbt = NULL;
  94. DWORD g_cbtMax = 0;
  95. DWORD g_cbt = 0;
  96. MEMHEADER *g_rgmh = NULL;
  97. DWORD g_cmhMax = 0;
  98. DWORD g_cmh = 0;
  99. MEMHEADER *
  100. AllocMemHeader()
  101. {
  102. if (g_cmh >= g_cmhMax)
  103. {
  104. DWORD cb = (C_MEM_HEADER_CHUNK + g_cmhMax) * sizeof(g_rgmh[0]);
  105. MEMHEADER *rgmhT;
  106. if (NULL == g_rgmh)
  107. {
  108. rgmhT = (MEMHEADER *) LocalAlloc(LMEM_FIXED, cb);
  109. }
  110. else
  111. {
  112. rgmhT = (MEMHEADER *) LocalReAlloc(g_rgmh, cb, LMEM_MOVEABLE);
  113. }
  114. if (NULL == rgmhT)
  115. {
  116. DBGPRINT((
  117. DBG_SS_CERTLIB,
  118. "Error allocating memtrack header\n"));
  119. return(NULL);
  120. }
  121. g_rgmh = rgmhT;
  122. g_cmhMax += C_MEM_HEADER_CHUNK;
  123. }
  124. return(&g_rgmh[g_cmh++]);
  125. }
  126. MEMHEADER *
  127. LookupMemHeader(
  128. IN VOID const *pv)
  129. {
  130. MEMHEADER *pmh;
  131. MEMHEADER *pmhEnd;
  132. pmh = g_rgmh;
  133. pmhEnd = &g_rgmh[g_cmh];
  134. while (pmh < pmhEnd)
  135. {
  136. if (pv == pmh->pvMemory)
  137. {
  138. return(pmh);
  139. }
  140. pmh++;
  141. }
  142. return(NULL);
  143. }
  144. VOID
  145. FreeMemHeader(
  146. IN MEMHEADER *pmh)
  147. {
  148. MEMHEADER *pmhLast;
  149. assert(1 <= g_cmh);
  150. pmhLast = &g_rgmh[g_cmh - 1];
  151. *pmh = *pmhLast;
  152. g_cmh--;
  153. }
  154. BACKTRACE *
  155. AllocBackTrace(
  156. OUT DWORD *pibt)
  157. {
  158. if (g_cbt >= g_cbtMax)
  159. {
  160. DWORD cb = (C_BACK_TRACE_CHUNK + g_cbtMax) * sizeof(g_rgbt[0]);
  161. BACKTRACE *rgbtT;
  162. if (NULL == g_rgbt)
  163. {
  164. rgbtT = (BACKTRACE *) LocalAlloc(LMEM_FIXED, cb);
  165. }
  166. else
  167. {
  168. rgbtT = (BACKTRACE *) LocalReAlloc(g_rgbt, cb, LMEM_MOVEABLE);
  169. DBGPRINT((
  170. DBG_SS_CERTLIB,
  171. "Realloc'd memtrack backtrace from %x to %x\n",
  172. g_rgbt,
  173. rgbtT));
  174. }
  175. if (NULL == rgbtT)
  176. {
  177. DBGPRINT((
  178. DBG_SS_CERTLIB,
  179. "Error allocating memtrack backtrace\n"));
  180. return(NULL);
  181. }
  182. g_rgbt = rgbtT;
  183. g_cbtMax += C_BACK_TRACE_CHUNK;
  184. }
  185. *pibt = g_cbt + 1;
  186. return(&g_rgbt[g_cbt++]);
  187. }
  188. BACKTRACE *
  189. LookupBackTrace(
  190. IN BACKTRACE *pbtIn,
  191. OUT DWORD *pibt)
  192. {
  193. BACKTRACE *pbt;
  194. BACKTRACE *pbtEnd;
  195. pbt = g_rgbt;
  196. pbtEnd = &g_rgbt[g_cbt];
  197. while (pbt < pbtEnd)
  198. {
  199. if (0 == memcmp(pbt->apCaller, pbtIn->apCaller, sizeof(pbt->apCaller)))
  200. {
  201. *pibt = SAFE_SUBTRACT_POINTERS(pbt, g_rgbt) + 1;
  202. return(pbt);
  203. }
  204. pbt++;
  205. }
  206. return(NULL);
  207. }
  208. BACKTRACE *
  209. BackTraceFromIndex(
  210. IN DWORD ibt)
  211. {
  212. BACKTRACE *pbt = NULL;
  213. if (0 == ibt)
  214. {
  215. DBGPRINT((DBG_SS_CERTLIB, "BackTraceFromIndex(0)\n"));
  216. }
  217. else if (g_cbt < ibt)
  218. {
  219. DBGPRINT((
  220. DBG_SS_CERTLIB,
  221. "BackTraceFromIndex(%u) -- out of range\n",
  222. ibt));
  223. }
  224. else
  225. {
  226. pbt = &g_rgbt[ibt - 1];
  227. }
  228. return(pbt);
  229. }
  230. VOID
  231. ReadEnvironmentFlags(VOID)
  232. {
  233. HRESULT hr;
  234. DWORD MemTrack;
  235. DWORD cb;
  236. DWORD dwDisposition;
  237. DWORD dwType;
  238. HKEY hkey = NULL;
  239. char *pszEnvVar;
  240. pszEnvVar = getenv(szCERTSRV_MEMTRACK);
  241. if (NULL != pszEnvVar)
  242. {
  243. g_MemTrack = (DWORD) strtol(pszEnvVar, NULL, 16);
  244. }
  245. else
  246. {
  247. hr = RegOpenKeyEx(
  248. HKEY_LOCAL_MACHINE,
  249. wszREGKEYCONFIGPATH,
  250. 0,
  251. KEY_READ,
  252. &hkey);
  253. if (S_OK == hr)
  254. {
  255. cb = sizeof(MemTrack);
  256. hr = RegQueryValueEx(
  257. hkey,
  258. wszREGCERTSRVMEMTRACK,
  259. 0,
  260. &dwType,
  261. (BYTE *) &MemTrack,
  262. &cb);
  263. if (S_OK == hr && REG_DWORD == dwType && sizeof(MemTrack) == cb)
  264. {
  265. g_MemTrack = MemTrack;
  266. }
  267. }
  268. }
  269. //error:
  270. if (NULL != hkey)
  271. {
  272. RegCloseKey(hkey);
  273. }
  274. }
  275. VOID
  276. CaptureStackBackTrace(
  277. EXCEPTION_POINTERS *pep,
  278. ULONG cSkip,
  279. ULONG cFrames,
  280. ULONG *aeip)
  281. {
  282. ZeroMemory(aeip, cFrames * sizeof(aeip[0]));
  283. #if i386 == 1
  284. ULONG ieip, *pebp;
  285. ULONG *pebpMax = (ULONG *) MAXLONG; // 2 * 1024 * 1024 * 1024; // 2 gig - 1
  286. ULONG *pebpMin = (ULONG *) (64 * 1024); // 64k
  287. if (pep == NULL)
  288. {
  289. ieip = 0;
  290. cSkip++; // always skip current frame
  291. pebp = ((ULONG *) &pep) - 2;
  292. }
  293. else
  294. {
  295. ieip = 1;
  296. assert(cSkip == 0);
  297. aeip[0] = pep->ContextRecord->Eip;
  298. pebp = (ULONG *) pep->ContextRecord->Ebp;
  299. }
  300. if (pebp >= pebpMin && pebp < pebpMax)
  301. {
  302. __try
  303. {
  304. for ( ; ieip < cSkip + cFrames; ieip++)
  305. {
  306. if (ieip >= cSkip)
  307. {
  308. aeip[ieip - cSkip] = *(pebp + 1); // save an eip
  309. }
  310. ULONG *pebpNext = (ULONG *) *pebp;
  311. if (pebpNext < pebp + 2 ||
  312. pebpNext >= pebpMax - 1 ||
  313. pebpNext >= pebp + (256 * 1024) / sizeof(pebp[0]))
  314. {
  315. break;
  316. }
  317. pebp = pebpNext;
  318. }
  319. }
  320. __except(EXCEPTION_EXECUTE_HANDLER)
  321. {
  322. ;
  323. }
  324. }
  325. #endif // i386 == 1
  326. }
  327. WCHAR const *
  328. wszAllocator(
  329. IN DWORD Flags)
  330. {
  331. WCHAR const *pwsz;
  332. switch (Flags)
  333. {
  334. case CSM_LOCALALLOC: pwsz = L"LocalAlloc"; break;
  335. case CSM_COTASKALLOC: pwsz = L"CoTaskMemAlloc"; break;
  336. case CSM_SYSALLOC: pwsz = L"SysAllocString"; break;
  337. case CSM_MALLOC: pwsz = L"malloc"; break;
  338. case CSM_NEW: pwsz = L"new"; break;
  339. case CSM_NEW | CSM_GLOBALDESTRUCTOR:
  340. pwsz = L"new-global"; break;
  341. default: pwsz = L"???"; break;
  342. }
  343. return(pwsz);
  344. }
  345. WCHAR const *
  346. wszFreeer(
  347. IN DWORD Flags)
  348. {
  349. WCHAR const *pwsz;
  350. switch (Flags)
  351. {
  352. case CSM_LOCALALLOC: pwsz = L"LocalFree"; break;
  353. case CSM_COTASKALLOC: pwsz = L"CoTaskMemFree"; break;
  354. case CSM_SYSALLOC: pwsz = L"SysFreeString"; break;
  355. case CSM_MALLOC: pwsz = L"free"; break;
  356. case CSM_NEW: pwsz = L"delete"; break;
  357. case CSM_NEW | CSM_GLOBALDESTRUCTOR:
  358. pwsz = L"delete-global"; break;
  359. default: pwsz = L"???"; break;
  360. }
  361. return(pwsz);
  362. }
  363. VOID
  364. DumpMemBlock(
  365. IN WCHAR const *pwsz,
  366. IN VOID const *pvMemory,
  367. IN DWORD cbMemory,
  368. IN DWORD Flags,
  369. IN DWORD ibt,
  370. OPTIONAL IN BACKTRACE const *pbt)
  371. {
  372. DBGPRINT((
  373. DBG_SS_CERTLIB,
  374. "%ws%wspv=%-6x cb=%-4x f=%x(%ws) pbt[%d]=%x:\n",
  375. pwsz,
  376. L'\0' != *pwsz? L": " : L"",
  377. pvMemory,
  378. cbMemory,
  379. Flags,
  380. wszAllocator(Flags),
  381. ibt,
  382. pbt));
  383. if (NULL != pbt && DbgIsSSActive(DBG_SS_CERTLIB))
  384. {
  385. DBGPRINT((MAXDWORD, "%d: ", ibt));
  386. for (int i = 0; i < ARRAYSIZE(pbt->apCaller); i++)
  387. {
  388. if (NULL == pbt->apCaller[i])
  389. {
  390. break;
  391. }
  392. DBGPRINT((MAXDWORD, "ln %x;", pbt->apCaller[i]));
  393. }
  394. DBGPRINT((MAXDWORD, "\n"));
  395. }
  396. }
  397. VOID
  398. myRegisterMemDump()
  399. {
  400. MEMHEADER *pmh;
  401. MEMHEADER *pmhEnd;
  402. LONG cTotal;
  403. LONG cbTotal;
  404. cTotal = 0;
  405. cbTotal = 0;
  406. RegisterMemoryEnterCriticalSection();
  407. __try
  408. {
  409. pmh = g_rgmh;
  410. pmhEnd = &g_rgmh[g_cmh];
  411. while (pmh < pmhEnd)
  412. {
  413. if (0 == (CSM_GLOBALDESTRUCTOR & pmh->Flags) ||
  414. (MTF_ALLOCTRACE & g_MemTrack))
  415. {
  416. if (0 == cTotal)
  417. {
  418. if (DbgIsSSActive(DBG_SS_CERTLIB))
  419. {
  420. DBGPRINT((MAXDWORD, "\n"));
  421. }
  422. DBGPRINT((DBG_SS_CERTLIB, "Allocated Memory Blocks:\n"));
  423. }
  424. cTotal++;
  425. cbTotal += pmh->cbMemory;
  426. DumpMemBlock(
  427. L"",
  428. pmh->pvMemory,
  429. pmh->cbMemory,
  430. pmh->Flags,
  431. pmh->iBackTrace,
  432. BackTraceFromIndex(pmh->iBackTrace));
  433. }
  434. pmh++;
  435. }
  436. if (0 != cTotal)
  437. {
  438. DBGPRINT((DBG_SS_CERTLIB, "Total: c=%x cb=%x\n\n", cTotal, cbTotal));
  439. }
  440. }
  441. __except(EXCEPTION_EXECUTE_HANDLER)
  442. {
  443. }
  444. RegisterMemoryLeaveCriticalSection();
  445. }
  446. VOID *
  447. _VariantMemory(
  448. IN PROPVARIANT const *pvar,
  449. OUT DWORD *pFlags,
  450. OPTIONAL OUT DWORD *pcb)
  451. {
  452. VOID *pv = NULL;
  453. DWORD cb = 0;
  454. BOOL fString = FALSE;
  455. *pFlags = CSM_COTASKALLOC;
  456. if (NULL != pcb)
  457. {
  458. *pcb = 0;
  459. }
  460. switch (pvar->vt)
  461. {
  462. case VT_BSTR:
  463. pv = pvar->bstrVal;
  464. fString = TRUE;
  465. *pFlags = CSM_SYSALLOC;
  466. break;
  467. case VT_BYREF | VT_BSTR:
  468. pv = *pvar->pbstrVal;
  469. fString = TRUE;
  470. *pFlags = CSM_SYSALLOC;
  471. break;
  472. case VT_LPWSTR:
  473. pv = pvar->pwszVal;
  474. fString = TRUE;
  475. break;
  476. case VT_BLOB:
  477. pv = pvar->blob.pBlobData;
  478. cb = pvar->blob.cbSize;
  479. break;
  480. }
  481. if (NULL != pcb)
  482. {
  483. if (fString)
  484. {
  485. cb = (wcslen((WCHAR const *) pv) + 1) * sizeof(WCHAR);
  486. }
  487. *pcb = cb;
  488. }
  489. return(pv);
  490. }
  491. VOID
  492. myRegisterMemAlloc(
  493. IN VOID const *pv,
  494. IN LONG cb,
  495. IN DWORD Flags)
  496. {
  497. BACKTRACE bt;
  498. MEMHEADER *pmh;
  499. BACKTRACE *pbt;
  500. if (CSM_VARIANT == Flags)
  501. {
  502. pv = _VariantMemory((PROPVARIANT const *) pv, &Flags, (DWORD *) &cb);
  503. if (NULL == pv)
  504. {
  505. return; // nothing to register
  506. }
  507. }
  508. RegisterMemoryEnterCriticalSection();
  509. __try
  510. {
  511. static BOOL s_fFirst = TRUE;
  512. if (s_fFirst)
  513. {
  514. ReadEnvironmentFlags();
  515. s_fFirst = FALSE;
  516. }
  517. if (0 != g_MemTrack)
  518. {
  519. // Do not register NULL as an allocation
  520. CSASSERT(NULL != pv);
  521. // see if we already have a reference to this memory
  522. pmh = LookupMemHeader(pv);
  523. if (NULL != pmh)
  524. {
  525. DBGPRINT((
  526. DBG_SS_CERTLIB,
  527. "Memory Leak: Tracked memory address reused. Previously allocated:\n"));
  528. DumpMemBlock(
  529. L"Memory leak",
  530. pv,
  531. pmh->cbMemory,
  532. pmh->Flags,
  533. pmh->iBackTrace,
  534. BackTraceFromIndex(pmh->iBackTrace));
  535. CSASSERT(!"Tracked memory address reused");
  536. FreeMemHeader(pmh);
  537. }
  538. pmh = AllocMemHeader();
  539. if (NULL != pmh)
  540. {
  541. DWORD ibt;
  542. CaptureStackBackTrace(NULL, 0, C_BP_FRAME, bt.apCaller);
  543. pbt = LookupBackTrace(&bt, &ibt);
  544. if (NULL != pbt)
  545. {
  546. pbt->cAlloc++;
  547. pbt->cAllocTotal++;
  548. pbt->cbAlloc += cb;
  549. pbt->cbAllocTotal += cb;
  550. }
  551. else
  552. {
  553. pbt = AllocBackTrace(&ibt);
  554. if (NULL != pbt)
  555. {
  556. pbt->cAlloc = 1;
  557. pbt->cAllocTotal = 1;
  558. pbt->cbAlloc = cb;
  559. pbt->cbAllocTotal = cb;
  560. CopyMemory(pbt->apCaller, bt.apCaller, sizeof(pbt->apCaller));
  561. }
  562. }
  563. if (NULL != pbt)
  564. {
  565. pmh->iBackTrace = ibt;
  566. pmh->pvMemory = pv;
  567. pmh->cbMemory = cb;
  568. pmh->Flags = Flags;
  569. CSASSERT(ARRAYSIZE(g_armAlloc) > Flags);
  570. g_armAlloc[Flags].cAlloc++;
  571. g_armAlloc[Flags].cAllocTotal++;
  572. if (MTF_ALLOCTRACE & g_MemTrack)
  573. {
  574. DBGPRINT((
  575. DBG_SS_CERTLIB,
  576. "Alloc: pmh=%x: pv=%x cb=%x f=%x(%ws) -- pbt[%d]=%x: c=%x, cb=%x\n",
  577. pmh,
  578. pmh->pvMemory,
  579. pmh->cbMemory,
  580. pmh->Flags,
  581. wszAllocator(pmh->Flags),
  582. SAFE_SUBTRACT_POINTERS(pbt, g_rgbt),
  583. pbt,
  584. pbt->cAlloc,
  585. pbt->cbAlloc));
  586. if (MTF_STACKTRACE & g_MemTrack)
  587. {
  588. DumpMemBlock(
  589. L"Alloc Trace memory block",
  590. pv,
  591. pmh->cbMemory, // cbMemory
  592. pmh->Flags, // Flags
  593. pmh->iBackTrace, // ibt
  594. pbt);
  595. }
  596. }
  597. }
  598. else
  599. {
  600. FreeMemHeader(pmh);
  601. }
  602. } // if no problem allocating pmh
  603. } // if g_MemTrack
  604. }
  605. __except(EXCEPTION_EXECUTE_HANDLER)
  606. {
  607. }
  608. RegisterMemoryLeaveCriticalSection();
  609. }
  610. VOID
  611. myRegisterMemFree(
  612. IN VOID const *pv,
  613. IN DWORD Flags)
  614. {
  615. MEMHEADER *pmh;
  616. if (CSM_VARIANT == Flags)
  617. {
  618. pv = _VariantMemory((PROPVARIANT const *) pv, &Flags, NULL);
  619. if (NULL == pv)
  620. {
  621. return; // nothing to register
  622. }
  623. }
  624. RegisterMemoryEnterCriticalSection();
  625. CSASSERT(CSM_MAX > (~CSM_GLOBALDESTRUCTOR & Flags));
  626. __try
  627. {
  628. pmh = LookupMemHeader(pv);
  629. if (NULL != pmh)
  630. {
  631. BACKTRACE *pbt = BackTraceFromIndex(pmh->iBackTrace);
  632. if (CSM_GLOBALDESTRUCTOR & Flags)
  633. {
  634. if ((CSM_GLOBALDESTRUCTOR | pmh->Flags) != Flags)
  635. {
  636. BACKTRACE bt;
  637. CaptureStackBackTrace(NULL, 0, C_BP_FRAME, bt.apCaller);
  638. DumpMemBlock(
  639. L"Wrong memory allocator for global destructor",
  640. pv,
  641. MAXDWORD, // cbMemory
  642. MAXDWORD, // Flags
  643. MAXDWORD, // ibt
  644. &bt);
  645. CSASSERT(!"Wrong memory allocator for global destructor");
  646. }
  647. else
  648. {
  649. pmh->Flags |= CSM_GLOBALDESTRUCTOR;
  650. }
  651. }
  652. else
  653. {
  654. g_armAlloc[Flags].cAlloc--;
  655. pbt->cAlloc--;
  656. pbt->cbAlloc -= pmh->cbMemory;
  657. if (CSM_GLOBALDESTRUCTOR & pmh->Flags)
  658. {
  659. Flags |= CSM_GLOBALDESTRUCTOR;
  660. }
  661. if (pmh->Flags != Flags)
  662. {
  663. DBGPRINT((
  664. DBG_SS_CERTLIB,
  665. "Wrong memory allocator: Freed with %ws, Allocated by %ws\n",
  666. wszFreeer(Flags),
  667. wszAllocator(pmh->Flags)));
  668. DumpMemBlock(
  669. L"Wrong memory allocator",
  670. pv,
  671. pmh->cbMemory,
  672. pmh->Flags,
  673. pmh->iBackTrace,
  674. BackTraceFromIndex(pmh->iBackTrace));
  675. CSASSERT(pmh->Flags == Flags);
  676. }
  677. else if (MTF_FREETRACE & g_MemTrack)
  678. {
  679. DBGPRINT((
  680. DBG_SS_CERTLIB,
  681. "Free: pmh=%x: pv=%x cb=%x f=%x(%ws) -- pbt[%d]=%x: c=%x, cb=%x\n",
  682. pmh,
  683. pv,
  684. pmh->cbMemory,
  685. pmh->Flags,
  686. wszAllocator(pmh->Flags),
  687. pmh->iBackTrace,
  688. pbt,
  689. pbt->cAlloc,
  690. pbt->cbAlloc));
  691. if (MTF_STACKTRACE & g_MemTrack)
  692. {
  693. BACKTRACE bt;
  694. CaptureStackBackTrace(NULL, 0, C_BP_FRAME, bt.apCaller);
  695. DumpMemBlock(
  696. L"Free Trace memory block(alloc)",
  697. pv,
  698. pmh->cbMemory, // cbMemory
  699. pmh->Flags, // Flags
  700. pmh->iBackTrace, // ibt
  701. pbt);
  702. DumpMemBlock(
  703. L"Free Trace memory block(free)",
  704. pv,
  705. pmh->cbMemory, // cbMemory
  706. pmh->Flags, // Flags
  707. MAXDWORD, // ibt
  708. &bt);
  709. }
  710. }
  711. FreeMemHeader(pmh);
  712. }
  713. }
  714. else if (MTF_UNREGISTERED & g_MemTrack)
  715. {
  716. BACKTRACE bt;
  717. CaptureStackBackTrace(NULL, 0, C_BP_FRAME, bt.apCaller);
  718. DumpMemBlock(
  719. L"Unregistered memory block",
  720. pv,
  721. MAXDWORD, // cbMemory
  722. MAXDWORD, // Flags
  723. MAXDWORD, // ibt
  724. &bt);
  725. CSASSERT(!"Unregistered memory block");
  726. }
  727. }
  728. __except(EXCEPTION_EXECUTE_HANDLER)
  729. {
  730. }
  731. RegisterMemoryLeaveCriticalSection();
  732. }
  733. DWORD
  734. myFormatMessageW(
  735. IN DWORD dwFlags,
  736. IN LPCVOID lpSource,
  737. IN DWORD dwMessageId,
  738. IN DWORD dwLanguageId,
  739. OUT LPWSTR lpBuffer,
  740. IN DWORD nSize,
  741. IN va_list *Arguments)
  742. {
  743. DWORD cwc;
  744. cwc = FormatMessage(
  745. dwFlags,
  746. lpSource,
  747. dwMessageId,
  748. dwLanguageId,
  749. lpBuffer,
  750. nSize,
  751. Arguments);
  752. if (cwc != 0 && (FORMAT_MESSAGE_ALLOCATE_BUFFER & dwFlags))
  753. {
  754. myRegisterMemAlloc(
  755. *(WCHAR **) lpBuffer,
  756. (cwc + 1) * sizeof(WCHAR),
  757. CSM_LOCALALLOC);
  758. }
  759. return(cwc);
  760. }
  761. HLOCAL
  762. myLocalAlloc(
  763. IN UINT uFlags,
  764. IN UINT uBytes)
  765. {
  766. HLOCAL hMem;
  767. // one of these should always be specified (see LocalAlloc specification)
  768. assert((LMEM_FIXED == (uFlags & LMEM_FIXED)) ||
  769. (LMEM_MOVEABLE == (uFlags & LMEM_MOVEABLE)) );
  770. hMem = LocalAlloc(uFlags, uBytes);
  771. if (NULL != hMem)
  772. {
  773. myRegisterMemAlloc(hMem, uBytes, CSM_LOCALALLOC);
  774. }
  775. return(hMem);
  776. }
  777. HLOCAL
  778. myLocalReAlloc(
  779. IN HLOCAL hMem,
  780. IN UINT uBytes,
  781. IN UINT uFlags)
  782. {
  783. HLOCAL hMemNew;
  784. // if realloc called without MOVEABLE flag, realloc can't relocate allocation
  785. assert(LMEM_MOVEABLE == (uFlags & LMEM_MOVEABLE));
  786. hMemNew = LocalReAlloc(hMem, uBytes, uFlags);
  787. if (NULL != hMemNew)
  788. {
  789. myRegisterMemFree(hMem, CSM_LOCALALLOC);
  790. myRegisterMemAlloc(hMemNew, uBytes, CSM_LOCALALLOC);
  791. }
  792. return(hMemNew);
  793. }
  794. HLOCAL
  795. myLocalFree(
  796. IN HLOCAL hMem)
  797. {
  798. myRegisterMemFree(hMem, CSM_LOCALALLOC);
  799. return(LocalFree(hMem));
  800. }
  801. VOID *
  802. myCoTaskMemAlloc(
  803. IN ULONG cb)
  804. {
  805. VOID *pv;
  806. pv = CoTaskMemAlloc(cb);
  807. if (NULL != pv)
  808. {
  809. myRegisterMemAlloc(pv, cb, CSM_COTASKALLOC);
  810. }
  811. return(pv);
  812. }
  813. VOID *
  814. myCoTaskMemRealloc(
  815. IN VOID *pv,
  816. IN ULONG cb)
  817. {
  818. VOID *pvNew;
  819. pvNew = CoTaskMemRealloc(pv, cb);
  820. if (NULL != pvNew)
  821. {
  822. myRegisterMemFree(pv, CSM_COTASKALLOC);
  823. myRegisterMemAlloc(pvNew, cb, CSM_COTASKALLOC);
  824. }
  825. return(pvNew);
  826. }
  827. VOID
  828. myCoTaskMemFree(
  829. IN VOID *pv)
  830. {
  831. myRegisterMemFree(pv, CSM_COTASKALLOC);
  832. CoTaskMemFree(pv);
  833. }
  834. HRESULT
  835. myStringFromCLSID(
  836. IN REFCLSID rclsid,
  837. OUT LPOLESTR FAR *ppwsz)
  838. {
  839. HRESULT hr;
  840. hr = StringFromCLSID(rclsid, ppwsz);
  841. _JumpIfError(hr, error, "StringFromCLSID");
  842. if (NULL != *ppwsz)
  843. {
  844. myRegisterMemAlloc(
  845. *ppwsz, (wcslen(*ppwsz) + 1) * sizeof(WCHAR),
  846. CSM_COTASKALLOC);
  847. }
  848. error:
  849. return(hr);
  850. }
  851. HRESULT
  852. myStringFromIID(
  853. IN REFIID rclsid,
  854. OUT LPOLESTR FAR *ppwsz)
  855. {
  856. HRESULT hr;
  857. hr = StringFromIID(rclsid, ppwsz);
  858. _JumpIfError(hr, error, "StringFromIID");
  859. if (NULL != *ppwsz)
  860. {
  861. myRegisterMemAlloc(
  862. *ppwsz, (wcslen(*ppwsz) + 1) * sizeof(WCHAR),
  863. CSM_COTASKALLOC);
  864. }
  865. error:
  866. return(hr);
  867. }
  868. BSTR
  869. mySysAllocString(
  870. IN const OLECHAR *pwszIn)
  871. {
  872. BSTR str;
  873. str = SysAllocString(pwszIn);
  874. if (NULL != str)
  875. {
  876. myRegisterMemAlloc(str, (wcslen(pwszIn) + 1) * sizeof(WCHAR), CSM_SYSALLOC);
  877. }
  878. return(str);
  879. }
  880. INT
  881. mySysReAllocString(
  882. IN OUT BSTR *pstr,
  883. IN const OLECHAR *pwszIn)
  884. {
  885. BSTR str = *pstr;
  886. INT i;
  887. i = SysReAllocString(pstr, pwszIn);
  888. if (i)
  889. {
  890. myRegisterMemFree(str, CSM_SYSALLOC);
  891. myRegisterMemAlloc(*pstr, (wcslen(pwszIn) + 1) * sizeof(WCHAR), CSM_SYSALLOC);
  892. }
  893. return(i);
  894. }
  895. BSTR
  896. mySysAllocStringLen(
  897. IN const OLECHAR *pwcIn,
  898. IN UINT cwc)
  899. {
  900. BSTR str;
  901. str = SysAllocStringLen(pwcIn, cwc);
  902. if (NULL != str)
  903. {
  904. myRegisterMemAlloc(str, cwc * sizeof(WCHAR), CSM_SYSALLOC);
  905. }
  906. return(str);
  907. }
  908. INT
  909. mySysReAllocStringLen(
  910. IN OUT BSTR *pstr,
  911. IN const OLECHAR *pwcIn,
  912. IN UINT cwc)
  913. {
  914. BSTR str = *pstr;
  915. INT i;
  916. i = SysReAllocStringLen(pstr, pwcIn, cwc);
  917. if (i)
  918. {
  919. myRegisterMemFree(str, CSM_SYSALLOC);
  920. myRegisterMemAlloc(*pstr, cwc * sizeof(WCHAR), CSM_SYSALLOC);
  921. }
  922. return(i);
  923. }
  924. VOID
  925. mySysFreeString(
  926. IN BSTR str)
  927. {
  928. if (NULL != str)
  929. {
  930. myRegisterMemFree(str, CSM_SYSALLOC);
  931. }
  932. SysFreeString(str);
  933. }
  934. BSTR
  935. mySysAllocStringByteLen(
  936. LPCSTR pszIn,
  937. UINT cb)
  938. {
  939. BSTR str;
  940. str = SysAllocStringByteLen(pszIn, cb);
  941. if (NULL != str)
  942. {
  943. myRegisterMemAlloc(str, cb, CSM_SYSALLOC);
  944. }
  945. return(str);
  946. }
  947. VOID
  948. _RegisterVariantMemAlloc(
  949. IN PROPVARIANT *pvar)
  950. {
  951. VOID *pv;
  952. DWORD Flags;
  953. DWORD cb;
  954. pv = _VariantMemory(pvar, &Flags, &cb);
  955. if (NULL != pv)
  956. {
  957. myRegisterMemAlloc(pv, cb, Flags);
  958. }
  959. }
  960. VOID
  961. _RegisterVariantMemFree(
  962. IN PROPVARIANT *pvar)
  963. {
  964. VOID *pv;
  965. DWORD Flags;
  966. pv = _VariantMemory(pvar, &Flags, NULL);
  967. if (NULL != pv)
  968. {
  969. myRegisterMemFree(pv, Flags);
  970. }
  971. }
  972. HRESULT
  973. myPropVariantClear(
  974. IN PROPVARIANT *pvar)
  975. {
  976. _RegisterVariantMemFree(pvar);
  977. return(PropVariantClear(pvar));
  978. }
  979. HRESULT
  980. myVariantClear(
  981. IN VARIANTARG *pvar)
  982. {
  983. _RegisterVariantMemFree((PROPVARIANT *) pvar);
  984. return(VariantClear(pvar));
  985. }
  986. HRESULT
  987. myVariantChangeType(
  988. OUT VARIANTARG *pvarDest,
  989. IN VARIANTARG *pvarSrc,
  990. IN unsigned short wFlags,
  991. IN VARTYPE vt)
  992. {
  993. HRESULT hr;
  994. // if converting in-place, memory will be freed by the API call
  995. if (pvarDest == pvarSrc)
  996. {
  997. _RegisterVariantMemFree((PROPVARIANT *) pvarSrc);
  998. }
  999. hr = VariantChangeType(pvarDest, pvarSrc, wFlags, vt);
  1000. _RegisterVariantMemAlloc((PROPVARIANT *) pvarDest);
  1001. return(hr);
  1002. }
  1003. HRESULT
  1004. myVariantChangeTypeEx(
  1005. OUT VARIANTARG *pvarDest,
  1006. IN VARIANTARG *pvarSrc,
  1007. IN LCID lcid,
  1008. IN unsigned short wFlags,
  1009. IN VARTYPE vt)
  1010. {
  1011. HRESULT hr;
  1012. // if converting in-place, memory will be freed by the API call
  1013. if (pvarDest == pvarSrc)
  1014. {
  1015. _RegisterVariantMemFree((PROPVARIANT *) pvarSrc);
  1016. }
  1017. hr = VariantChangeTypeEx(pvarDest, pvarSrc, lcid, wFlags, vt);
  1018. _RegisterVariantMemAlloc((PROPVARIANT *) pvarDest);
  1019. return(hr);
  1020. }
  1021. VOID *
  1022. myNew(
  1023. IN size_t size)
  1024. {
  1025. VOID *pv;
  1026. pv = LocalAlloc(LMEM_FIXED, size);
  1027. if (NULL != pv)
  1028. {
  1029. myRegisterMemAlloc(pv, size, CSM_NEW);
  1030. }
  1031. return(pv);
  1032. }
  1033. VOID
  1034. myDelete(
  1035. IN VOID *pv)
  1036. {
  1037. myRegisterMemFree(pv, CSM_NEW);
  1038. LocalFree(pv);
  1039. }
  1040. #endif // DBG_CERTSRV