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.

521 lines
12 KiB

  1. /*++
  2. Copyright (C) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. // WMI Debugging DLL -- Kernel33 wrapper for memory allocations
  8. #include <windows.h>
  9. #include <kernel33.h>
  10. #include <stktrace.h>
  11. PFN_HeapAlloc pfnHeapAlloc = 0;
  12. PFN_HeapReAlloc pfnHeapReAlloc = 0;
  13. PFN_HeapFree pfnHeapFree = 0;
  14. PFN_HeapSize pfnHeapSize = 0;
  15. CRITICAL_SECTION cs;
  16. CRITICAL_SECTION s_cs;
  17. void _strcat(char *p1, char *p2)
  18. {
  19. while (*++p1);
  20. while (*p2) *p1++=*p2++;
  21. *p1 = 0;
  22. }
  23. void TrackingInit();
  24. void TrackBlock(
  25. size_t nSize,
  26. LPVOID pAddr
  27. );
  28. HMODULE hLib = 0;
  29. void Setup();
  30. BOOL g_bMemTracking = FALSE;
  31. BOOL UntrackBlock(LPVOID pBlock);
  32. BOOL TestForWinMgmt();
  33. BOOL g_bWinMgmt = FALSE;
  34. ///////////////////////////////////////////////////////////////////////////////////
  35. BOOL WINAPI DllEntry(
  36. HINSTANCE hinstDLL,
  37. DWORD dwReason,
  38. LPVOID lpReserved
  39. )
  40. {
  41. static BOOL bInit = FALSE;
  42. if (dwReason == DLL_PROCESS_ATTACH)
  43. {
  44. if (bInit == FALSE)
  45. {
  46. bInit = TRUE;
  47. BOOL bWinMgmt = TestForWinMgmt();
  48. char buf[256];
  49. *buf = 0;
  50. GetSystemDirectory(buf, 256);
  51. _strcat(buf, "\\kernel32.dll");
  52. hLib = LoadLibrary(buf);
  53. InitializeCriticalSection(&cs);
  54. if (bWinMgmt)
  55. TrackingInit();
  56. pfnHeapAlloc = (PFN_HeapAlloc) GetProcAddress(hLib, "HeapAlloc");
  57. pfnHeapReAlloc = (PFN_HeapReAlloc) GetProcAddress(hLib, "HeapReAlloc");
  58. pfnHeapFree = (PFN_HeapFree) GetProcAddress(hLib, "HeapFree");
  59. pfnHeapSize = (PFN_HeapSize) GetProcAddress(hLib, "HeapSize");
  60. if (bWinMgmt)
  61. Setup();
  62. bInit = TRUE;
  63. }
  64. }
  65. else if (dwReason == DLL_PROCESS_DETACH)
  66. {
  67. DeleteCriticalSection(&cs);
  68. }
  69. return TRUE;
  70. }
  71. extern "C"
  72. LPVOID WINAPI HeapAlloc(
  73. IN HANDLE hHeap,
  74. IN DWORD dwFlags,
  75. IN SIZE_T dwBytes
  76. )
  77. {
  78. LPVOID p = pfnHeapAlloc(hHeap, dwFlags, dwBytes);
  79. if (p && g_bMemTracking)
  80. {
  81. TrackBlock(dwBytes, p);
  82. }
  83. return p;
  84. }
  85. extern "C"
  86. LPVOID WINAPI HeapReAlloc(
  87. IN HANDLE hHeap,
  88. IN DWORD dwFlags,
  89. IN LPVOID lpMem,
  90. IN SIZE_T dwBytes
  91. )
  92. {
  93. if (g_bMemTracking)
  94. UntrackBlock(lpMem);
  95. LPVOID p = pfnHeapReAlloc(hHeap, dwFlags, lpMem, dwBytes);
  96. if (p && g_bMemTracking)
  97. TrackBlock(dwBytes, p);
  98. return p;
  99. }
  100. extern "C"
  101. BOOL WINAPI HeapFree(
  102. IN HANDLE hHeap,
  103. IN DWORD dwFlags,
  104. IN LPVOID lpMem
  105. )
  106. {
  107. if (g_bMemTracking)
  108. UntrackBlock(lpMem);
  109. return pfnHeapFree(hHeap, dwFlags, lpMem);
  110. }
  111. //***************************************************************************
  112. //
  113. //***************************************************************************
  114. struct TrackingLink
  115. {
  116. TrackingLink *pNext;
  117. DWORD dwThreadId;
  118. size_t nSize;
  119. DWORD dwSysTime;
  120. StackTrace *pTrace;
  121. void *pBlock;
  122. };
  123. TrackingLink *s_pHead;
  124. HANDLE s_hTrackingHeap;
  125. //******************************************************************************
  126. //
  127. //******************************************************************************
  128. void TrackingInit()
  129. {
  130. InitializeCriticalSection(&s_cs);
  131. EnterCriticalSection(&s_cs);
  132. s_hTrackingHeap = HeapCreate(0, 0x8000, 0);
  133. s_pHead = 0;
  134. LeaveCriticalSection(&s_cs);
  135. }
  136. //******************************************************************************
  137. //
  138. //******************************************************************************
  139. void TrackingReset()
  140. {
  141. EnterCriticalSection(&s_cs);
  142. TrackingLink *pTracer, *pTemp;
  143. for (pTracer = s_pHead; pTracer; pTracer = pTemp)
  144. {
  145. pTemp = pTracer->pNext;
  146. //if (pTracer->pTrace)
  147. // pTracer->pTrace->Delete();
  148. pfnHeapFree(s_hTrackingHeap, 0, pTracer);
  149. }
  150. s_pHead = 0;
  151. LeaveCriticalSection(&s_cs);
  152. }
  153. //******************************************************************************
  154. //
  155. //******************************************************************************
  156. void TrackBlock(
  157. size_t nSize,
  158. LPVOID pAddr
  159. )
  160. {
  161. EnterCriticalSection(&s_cs);
  162. // Allocate new memory blocks.
  163. TrackingLink *pNew = (TrackingLink *) pfnHeapAlloc(s_hTrackingHeap, HEAP_ZERO_MEMORY,
  164. sizeof(TrackingLink));
  165. if (!pNew)
  166. {
  167. LeaveCriticalSection(&s_cs);
  168. return;
  169. }
  170. StackTrace *pTrace = StackTrace__NewTrace();
  171. // Attach to list.
  172. // ===============
  173. pNew->nSize = nSize;
  174. pNew->pTrace = pTrace;
  175. pNew->pNext = s_pHead;
  176. pNew->pBlock = pAddr;
  177. pNew->dwSysTime = GetCurrentTime();
  178. pNew->dwThreadId = GetCurrentThreadId();
  179. s_pHead = pNew;
  180. LeaveCriticalSection(&s_cs);
  181. }
  182. BOOL UntrackBlock(LPVOID pBlock)
  183. {
  184. if (!pBlock)
  185. return FALSE;
  186. // Special case the head.
  187. // ======================
  188. EnterCriticalSection(&s_cs);
  189. if (s_pHead == 0)
  190. {
  191. LeaveCriticalSection(&s_cs);
  192. return FALSE;
  193. };
  194. if (s_pHead->pBlock == pBlock)
  195. {
  196. TrackingLink *pTemp = s_pHead;
  197. s_pHead = s_pHead->pNext;
  198. if (pTemp->pTrace)
  199. StackTrace_Delete(pTemp->pTrace);
  200. pfnHeapFree(s_hTrackingHeap, 0, pTemp);
  201. LeaveCriticalSection(&s_cs);
  202. return TRUE;
  203. }
  204. TrackingLink *pTracer , *pPrevious = 0;
  205. for (pTracer = s_pHead; pTracer; pTracer = pTracer->pNext)
  206. {
  207. if (pTracer->pBlock == pBlock)
  208. {
  209. pPrevious->pNext = pTracer->pNext;
  210. if (pTracer->pTrace)
  211. StackTrace_Delete(pTracer->pTrace);
  212. pfnHeapFree(s_hTrackingHeap, 0, pTracer);
  213. LeaveCriticalSection(&s_cs);
  214. return TRUE;
  215. }
  216. pPrevious = pTracer;
  217. }
  218. LeaveCriticalSection(&s_cs);
  219. return FALSE;
  220. }
  221. extern "C" VOID WINAPI StartHeapTracking()
  222. {
  223. StackTrace_Init();
  224. }
  225. extern "C" DWORD WINAPI GetTotalHeap()
  226. {
  227. EnterCriticalSection(&s_cs);
  228. TrackingLink *pTracer;
  229. DWORD dwTotal = 0;
  230. for (pTracer = s_pHead; pTracer; pTracer = pTracer->pNext)
  231. dwTotal += pTracer->nSize;
  232. LeaveCriticalSection(&s_cs);
  233. return dwTotal;
  234. }
  235. extern "C" DWORD WINAPI DumpHeapStacks()
  236. {
  237. HANDLE hFile = CreateFile("c:\\temp\\heap.log", GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  238. if (hFile == INVALID_HANDLE_VALUE)
  239. {
  240. return 0;
  241. }
  242. SetFilePointer(hFile, 0, 0, FILE_END);
  243. DWORD dwWritten;
  244. char *pStr = "*************** Dump *******************\r\n";
  245. WriteFile(hFile, pStr, lstrlen(pStr), &dwWritten, 0);
  246. EnterCriticalSection(&s_cs);
  247. TrackingLink *pTracer;
  248. DWORD dwTotal = 0;
  249. for (pTracer = s_pHead; pTracer; pTracer = pTracer->pNext)
  250. {
  251. char *pStr = " --Block ";
  252. WriteFile(hFile, pStr, lstrlen(pStr), &dwWritten, 0);
  253. char Buf[256];
  254. wsprintf(Buf, " Size=%d Address=0x%X Thread=%d Time=%d\r\n",
  255. pTracer->nSize, pTracer->pBlock, pTracer->dwThreadId,
  256. pTracer->dwSysTime
  257. );
  258. WriteFile(hFile, Buf, lstrlen(Buf), &dwWritten, 0);
  259. StackTrace *pTrace = pTracer->pTrace;
  260. char *pDump = 0;
  261. if (pTrace)
  262. pDump = StackTrace_Dump(pTrace);
  263. if (pDump)
  264. {
  265. WriteFile(hFile, pDump, lstrlen(pDump), &dwWritten, 0);
  266. }
  267. }
  268. CloseHandle(hFile);
  269. LeaveCriticalSection(&s_cs);
  270. return 0;
  271. }
  272. typedef enum { H_ENABLE_LEAK_TRACKING = 0,
  273. H_DISABLE_LEAK_TRACKING = 1,
  274. H_RESET_LEAK_TRACKING = 2,
  275. H_DUMP_LEAK_TRACKING = 3,
  276. H_FAIL_ALLOCATOR = 4,
  277. H_RESTORE_ALLOCATOR = 5,
  278. H_FAIL_NEXT_ALLOC = 6,
  279. H_ENABLE_EXCEPTION_TRACKING = 7,
  280. H_DISABLE_EXCEPTION_TRACKING = 8,
  281. H_ENABLE_OBJECT_VALIDATION = 9,
  282. H_DISABLE_OBJECT_VALIDATION = 10,
  283. H_DEBUG_BREAK = 11,
  284. H_LAST
  285. } eTypes;
  286. static HANDLE m_hArray[H_LAST];
  287. static DWORD WINAPI ThreadProc(LPVOID pArg);
  288. void Setup()
  289. {
  290. PSECURITY_DESCRIPTOR pSD;
  291. // Initialize a security descriptor.
  292. pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
  293. SECURITY_DESCRIPTOR_MIN_LENGTH); // defined in WINNT.H
  294. if (pSD == NULL)
  295. return;
  296. SECURITY_ATTRIBUTES sa;
  297. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  298. sa.lpSecurityDescriptor = pSD;
  299. sa.bInheritHandle = FALSE;
  300. if (!InitializeSecurityDescriptor(pSD,
  301. SECURITY_DESCRIPTOR_REVISION))
  302. return;
  303. // Add a NULL disc. ACL to the security descriptor.
  304. if (!SetSecurityDescriptorDacl(pSD,
  305. TRUE, // specifying a disc. ACL
  306. (PACL) NULL,
  307. FALSE))
  308. return;
  309. // Set up the IPC signals.
  310. // =======================
  311. m_hArray[H_ENABLE_LEAK_TRACKING] =
  312. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_ENABLE_LEAK_TRACKING");
  313. m_hArray[H_DISABLE_LEAK_TRACKING] =
  314. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DISABLE_LEAK_TRACKING");
  315. m_hArray[H_RESET_LEAK_TRACKING] =
  316. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_RESET_LEAK_TRACKING");
  317. m_hArray[H_DUMP_LEAK_TRACKING] =
  318. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DUMP_LEAK_TRACKING");
  319. m_hArray[H_FAIL_ALLOCATOR] =
  320. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_FAIL_ALLOCATOR");
  321. m_hArray[H_RESTORE_ALLOCATOR] =
  322. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_RESTORE_ALLOCATOR");
  323. m_hArray[H_FAIL_NEXT_ALLOC] =
  324. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_FAIL_NEXT_ALLOCATION");
  325. m_hArray[H_ENABLE_EXCEPTION_TRACKING] =
  326. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_ENABLE_EXCEPTION_TRACKING");
  327. m_hArray[H_DISABLE_EXCEPTION_TRACKING] =
  328. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DISABLE_EXCEPTION_TRACKING");
  329. m_hArray[H_ENABLE_OBJECT_VALIDATION] =
  330. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_ENABLE_OBJECT_VALIDATION");
  331. m_hArray[H_DISABLE_OBJECT_VALIDATION] =
  332. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DISABLE_OBJECT_VALIDATION");
  333. m_hArray[H_DEBUG_BREAK] =
  334. CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DEBUG_BREAK");
  335. // Create the waiting thread.
  336. // ==========================
  337. DWORD dwId;
  338. HANDLE hThread = CreateThread(0, 0, ThreadProc, 0, 0, &dwId);
  339. CloseHandle(hThread);
  340. LocalFree(pSD);
  341. }
  342. //***************************************************************************
  343. //
  344. //***************************************************************************
  345. static DWORD WINAPI ThreadProc(LPVOID pArg)
  346. {
  347. static bool bInitialized = false;
  348. if (g_bWinMgmt == FALSE)
  349. {
  350. return 0;
  351. }
  352. for (;;)
  353. {
  354. DWORD dwRes = WaitForMultipleObjects(H_LAST, m_hArray, FALSE, INFINITE);
  355. dwRes -= WAIT_OBJECT_0;
  356. switch(dwRes)
  357. {
  358. case H_ENABLE_LEAK_TRACKING:
  359. if (!bInitialized)
  360. {
  361. StartHeapTracking();
  362. bInitialized = true;
  363. }
  364. g_bMemTracking = true;
  365. break;
  366. case H_DUMP_LEAK_TRACKING:
  367. if (g_bMemTracking)
  368. DumpHeapStacks();
  369. break;
  370. }
  371. }
  372. return 0;
  373. }
  374. BOOL TestForWinMgmt()
  375. {
  376. char mod[128];
  377. GetModuleFileName(0, mod, 128);
  378. // Upcase.
  379. char *p = mod;
  380. while (*p)
  381. {
  382. if (*p >= 'a' && *p <= 'z')
  383. {
  384. *p -= 32;
  385. }
  386. p++;
  387. }
  388. // Ensure WINMGMT.EXE
  389. p = mod;
  390. while (*p)
  391. {
  392. if ( p[0] != 0 && p[0] == 'W'
  393. && p[1] != 0 && p[1] == 'I'
  394. && p[2] != 0 && p[2] == 'N'
  395. && p[3] != 0 && p[3] == 'M'
  396. && p[4] != 0 && p[4] == 'G'
  397. && p[5] != 0 && p[5] == 'M'
  398. && p[6] != 0 && p[6] == 'T'
  399. )
  400. {
  401. g_bWinMgmt = TRUE;
  402. return TRUE;
  403. }
  404. p++;
  405. }
  406. return FALSE;
  407. }