|
|
/*++
Copyright (C) 1999-2001 Microsoft Corporation
Module Name:
Abstract:
History:
--*/
// WMI Debugging DLL -- Kernel33 wrapper for memory allocations
#include <windows.h>
#include <kernel33.h>
#include <stktrace.h>
PFN_HeapAlloc pfnHeapAlloc = 0; PFN_HeapReAlloc pfnHeapReAlloc = 0; PFN_HeapFree pfnHeapFree = 0; PFN_HeapSize pfnHeapSize = 0;
CRITICAL_SECTION cs; CRITICAL_SECTION s_cs;
void _strcat(char *p1, char *p2) { while (*++p1); while (*p2) *p1++=*p2++; *p1 = 0; }
void TrackingInit(); void TrackBlock( size_t nSize, LPVOID pAddr );
HMODULE hLib = 0; void Setup(); BOOL g_bMemTracking = FALSE;
BOOL UntrackBlock(LPVOID pBlock); BOOL TestForWinMgmt(); BOOL g_bWinMgmt = FALSE;
///////////////////////////////////////////////////////////////////////////////////
BOOL WINAPI DllEntry( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved ) { static BOOL bInit = FALSE;
if (dwReason == DLL_PROCESS_ATTACH) { if (bInit == FALSE) { bInit = TRUE; BOOL bWinMgmt = TestForWinMgmt(); char buf[256]; *buf = 0; GetSystemDirectory(buf, 256); _strcat(buf, "\\kernel32.dll"); hLib = LoadLibrary(buf); InitializeCriticalSection(&cs);
if (bWinMgmt) TrackingInit();
pfnHeapAlloc = (PFN_HeapAlloc) GetProcAddress(hLib, "HeapAlloc"); pfnHeapReAlloc = (PFN_HeapReAlloc) GetProcAddress(hLib, "HeapReAlloc"); pfnHeapFree = (PFN_HeapFree) GetProcAddress(hLib, "HeapFree"); pfnHeapSize = (PFN_HeapSize) GetProcAddress(hLib, "HeapSize");
if (bWinMgmt) Setup();
bInit = TRUE; } } else if (dwReason == DLL_PROCESS_DETACH) { DeleteCriticalSection(&cs); }
return TRUE;
}
extern "C" LPVOID WINAPI HeapAlloc( IN HANDLE hHeap, IN DWORD dwFlags, IN SIZE_T dwBytes ) {
LPVOID p = pfnHeapAlloc(hHeap, dwFlags, dwBytes);
if (p && g_bMemTracking) { TrackBlock(dwBytes, p); }
return p; }
extern "C" LPVOID WINAPI HeapReAlloc( IN HANDLE hHeap, IN DWORD dwFlags, IN LPVOID lpMem, IN SIZE_T dwBytes ) { if (g_bMemTracking) UntrackBlock(lpMem);
LPVOID p = pfnHeapReAlloc(hHeap, dwFlags, lpMem, dwBytes);
if (p && g_bMemTracking) TrackBlock(dwBytes, p);
return p; }
extern "C" BOOL WINAPI HeapFree( IN HANDLE hHeap, IN DWORD dwFlags, IN LPVOID lpMem ) { if (g_bMemTracking) UntrackBlock(lpMem);
return pfnHeapFree(hHeap, dwFlags, lpMem); }
//***************************************************************************
//
//***************************************************************************
struct TrackingLink { TrackingLink *pNext; DWORD dwThreadId; size_t nSize; DWORD dwSysTime; StackTrace *pTrace; void *pBlock; };
TrackingLink *s_pHead; HANDLE s_hTrackingHeap;
//******************************************************************************
//
//******************************************************************************
void TrackingInit() { InitializeCriticalSection(&s_cs); EnterCriticalSection(&s_cs); s_hTrackingHeap = HeapCreate(0, 0x8000, 0); s_pHead = 0; LeaveCriticalSection(&s_cs); }
//******************************************************************************
//
//******************************************************************************
void TrackingReset() { EnterCriticalSection(&s_cs);
TrackingLink *pTracer, *pTemp;
for (pTracer = s_pHead; pTracer; pTracer = pTemp) { pTemp = pTracer->pNext; //if (pTracer->pTrace)
// pTracer->pTrace->Delete();
pfnHeapFree(s_hTrackingHeap, 0, pTracer); }
s_pHead = 0;
LeaveCriticalSection(&s_cs); }
//******************************************************************************
//
//******************************************************************************
void TrackBlock( size_t nSize, LPVOID pAddr ) { EnterCriticalSection(&s_cs);
// Allocate new memory blocks.
TrackingLink *pNew = (TrackingLink *) pfnHeapAlloc(s_hTrackingHeap, HEAP_ZERO_MEMORY, sizeof(TrackingLink));
if (!pNew) { LeaveCriticalSection(&s_cs); return; }
StackTrace *pTrace = StackTrace__NewTrace();
// Attach to list.
// ===============
pNew->nSize = nSize; pNew->pTrace = pTrace; pNew->pNext = s_pHead; pNew->pBlock = pAddr; pNew->dwSysTime = GetCurrentTime(); pNew->dwThreadId = GetCurrentThreadId(); s_pHead = pNew;
LeaveCriticalSection(&s_cs); }
BOOL UntrackBlock(LPVOID pBlock) { if (!pBlock) return FALSE;
// Special case the head.
// ======================
EnterCriticalSection(&s_cs);
if (s_pHead == 0) { LeaveCriticalSection(&s_cs); return FALSE; };
if (s_pHead->pBlock == pBlock) { TrackingLink *pTemp = s_pHead; s_pHead = s_pHead->pNext; if (pTemp->pTrace) StackTrace_Delete(pTemp->pTrace); pfnHeapFree(s_hTrackingHeap, 0, pTemp); LeaveCriticalSection(&s_cs); return TRUE; }
TrackingLink *pTracer , *pPrevious = 0;
for (pTracer = s_pHead; pTracer; pTracer = pTracer->pNext) { if (pTracer->pBlock == pBlock) { pPrevious->pNext = pTracer->pNext; if (pTracer->pTrace) StackTrace_Delete(pTracer->pTrace); pfnHeapFree(s_hTrackingHeap, 0, pTracer); LeaveCriticalSection(&s_cs); return TRUE; }
pPrevious = pTracer; }
LeaveCriticalSection(&s_cs); return FALSE; }
extern "C" VOID WINAPI StartHeapTracking() { StackTrace_Init(); }
extern "C" DWORD WINAPI GetTotalHeap() { EnterCriticalSection(&s_cs); TrackingLink *pTracer; DWORD dwTotal = 0; for (pTracer = s_pHead; pTracer; pTracer = pTracer->pNext) dwTotal += pTracer->nSize; LeaveCriticalSection(&s_cs); return dwTotal; }
extern "C" DWORD WINAPI DumpHeapStacks() { HANDLE hFile = CreateFile("c:\\temp\\heap.log", GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { return 0; } SetFilePointer(hFile, 0, 0, FILE_END);
DWORD dwWritten; char *pStr = "*************** Dump *******************\r\n"; WriteFile(hFile, pStr, lstrlen(pStr), &dwWritten, 0);
EnterCriticalSection(&s_cs);
TrackingLink *pTracer; DWORD dwTotal = 0; for (pTracer = s_pHead; pTracer; pTracer = pTracer->pNext) { char *pStr = " --Block "; WriteFile(hFile, pStr, lstrlen(pStr), &dwWritten, 0);
char Buf[256]; wsprintf(Buf, " Size=%d Address=0x%X Thread=%d Time=%d\r\n", pTracer->nSize, pTracer->pBlock, pTracer->dwThreadId, pTracer->dwSysTime ); WriteFile(hFile, Buf, lstrlen(Buf), &dwWritten, 0);
StackTrace *pTrace = pTracer->pTrace; char *pDump = 0; if (pTrace) pDump = StackTrace_Dump(pTrace); if (pDump) { WriteFile(hFile, pDump, lstrlen(pDump), &dwWritten, 0); } }
CloseHandle(hFile); LeaveCriticalSection(&s_cs); return 0; }
typedef enum { H_ENABLE_LEAK_TRACKING = 0, H_DISABLE_LEAK_TRACKING = 1, H_RESET_LEAK_TRACKING = 2, H_DUMP_LEAK_TRACKING = 3, H_FAIL_ALLOCATOR = 4, H_RESTORE_ALLOCATOR = 5, H_FAIL_NEXT_ALLOC = 6, H_ENABLE_EXCEPTION_TRACKING = 7, H_DISABLE_EXCEPTION_TRACKING = 8, H_ENABLE_OBJECT_VALIDATION = 9, H_DISABLE_OBJECT_VALIDATION = 10, H_DEBUG_BREAK = 11, H_LAST } eTypes;
static HANDLE m_hArray[H_LAST];
static DWORD WINAPI ThreadProc(LPVOID pArg);
void Setup() { PSECURITY_DESCRIPTOR pSD;
// Initialize a security descriptor.
pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); // defined in WINNT.H
if (pSD == NULL) return;
SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE;
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) return;
// Add a NULL disc. ACL to the security descriptor.
if (!SetSecurityDescriptorDacl(pSD, TRUE, // specifying a disc. ACL
(PACL) NULL, FALSE)) return;
// Set up the IPC signals.
// =======================
m_hArray[H_ENABLE_LEAK_TRACKING] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_ENABLE_LEAK_TRACKING"); m_hArray[H_DISABLE_LEAK_TRACKING] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DISABLE_LEAK_TRACKING"); m_hArray[H_RESET_LEAK_TRACKING] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_RESET_LEAK_TRACKING"); m_hArray[H_DUMP_LEAK_TRACKING] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DUMP_LEAK_TRACKING");
m_hArray[H_FAIL_ALLOCATOR] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_FAIL_ALLOCATOR"); m_hArray[H_RESTORE_ALLOCATOR] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_RESTORE_ALLOCATOR"); m_hArray[H_FAIL_NEXT_ALLOC] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_FAIL_NEXT_ALLOCATION");
m_hArray[H_ENABLE_EXCEPTION_TRACKING] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_ENABLE_EXCEPTION_TRACKING"); m_hArray[H_DISABLE_EXCEPTION_TRACKING] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DISABLE_EXCEPTION_TRACKING");
m_hArray[H_ENABLE_OBJECT_VALIDATION] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_ENABLE_OBJECT_VALIDATION"); m_hArray[H_DISABLE_OBJECT_VALIDATION] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DISABLE_OBJECT_VALIDATION");
m_hArray[H_DEBUG_BREAK] = CreateEventW(&sa, FALSE, 0, L"EVENT_WINMGMT_DEBUG_BREAK");
// Create the waiting thread.
// ==========================
DWORD dwId; HANDLE hThread = CreateThread(0, 0, ThreadProc, 0, 0, &dwId); CloseHandle(hThread);
LocalFree(pSD); }
//***************************************************************************
//
//***************************************************************************
static DWORD WINAPI ThreadProc(LPVOID pArg) { static bool bInitialized = false; if (g_bWinMgmt == FALSE) { return 0; } for (;;) { DWORD dwRes = WaitForMultipleObjects(H_LAST, m_hArray, FALSE, INFINITE);
dwRes -= WAIT_OBJECT_0;
switch(dwRes) { case H_ENABLE_LEAK_TRACKING: if (!bInitialized) { StartHeapTracking(); bInitialized = true; } g_bMemTracking = true; break;
case H_DUMP_LEAK_TRACKING: if (g_bMemTracking) DumpHeapStacks(); break; } }
return 0; }
BOOL TestForWinMgmt() { char mod[128];
GetModuleFileName(0, mod, 128);
// Upcase.
char *p = mod; while (*p) { if (*p >= 'a' && *p <= 'z') { *p -= 32; } p++; }
// Ensure WINMGMT.EXE
p = mod; while (*p) { if ( p[0] != 0 && p[0] == 'W' && p[1] != 0 && p[1] == 'I' && p[2] != 0 && p[2] == 'N' && p[3] != 0 && p[3] == 'M' && p[4] != 0 && p[4] == 'G' && p[5] != 0 && p[5] == 'M' && p[6] != 0 && p[6] == 'T' ) { g_bWinMgmt = TRUE; return TRUE; } p++; }
return FALSE; }
|