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.

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