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.
910 lines
30 KiB
910 lines
30 KiB
// --------------------------------------------------------------------------------
|
|
// Msoedbg.cpp
|
|
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
|
|
// --------------------------------------------------------------------------------
|
|
#include "pch.hxx"
|
|
#include <BadStrFunctions.h>
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Debug Only Code
|
|
// --------------------------------------------------------------------------------
|
|
#ifdef DEBUG
|
|
|
|
#include <shlwapi.h>
|
|
#include "dllmain.h"
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// REGISTRYNAMES
|
|
// --------------------------------------------------------------------------------
|
|
typedef struct tagREGISTRYNAMES {
|
|
LPCSTR pszEnableTracing;
|
|
LPCSTR pszTraceLogType;
|
|
LPCSTR pszLogfilePath;
|
|
LPCSTR pszResetLogfile;
|
|
LPCSTR pszLogTraceCall;
|
|
LPCSTR pszLogTraceInfo;
|
|
LPCSTR pszLogWatchFilePath;
|
|
LPCSTR pszLaunchLogWatcher;
|
|
LPCSTR pszDisplaySourceFilePaths;
|
|
LPCSTR pszTraceCallIndent;
|
|
} REGISTRYNAMES, *LPREGISTRYNAMES;
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// RegKeyNames
|
|
// --------------------------------------------------------------------------------
|
|
static REGISTRYNAMES g_rRegKeyNames = {
|
|
"EnableTracing",
|
|
"TraceLogType",
|
|
"LogfilePath",
|
|
"LogfileResetType",
|
|
"LogTraceCall",
|
|
"LogTraceInfo",
|
|
"LogWatchFilePath",
|
|
"LaunchLogWatcher",
|
|
"DisplaySourceFilePaths",
|
|
"TraceCallIndent"
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Prototypes
|
|
// --------------------------------------------------------------------------------
|
|
void ReadTraceComponentInfo(
|
|
IN HKEY hRegKey,
|
|
IN LPREGISTRYNAMES pNames,
|
|
OUT LPTRACECOMPONENTINFO pInfo);
|
|
|
|
void ReadTraceItemTable(
|
|
IN HKEY hKeyRoot,
|
|
IN LPCSTR pszSubKey,
|
|
OUT LPTRACEITEMTABLE pTable);
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Global Configuration
|
|
// --------------------------------------------------------------------------------
|
|
static CRITICAL_SECTION g_csTracing={0};
|
|
static LPTRACECOMPONENTINFO g_pHeadComponent=NULL;
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// InitializeTracingSystem
|
|
// --------------------------------------------------------------------------------
|
|
void InitializeTracingSystem(void)
|
|
{
|
|
g_dwTlsTraceThread = TlsAlloc();
|
|
Assert(g_dwTlsTraceThread != 0xffffffff);
|
|
InitializeCriticalSection(&g_csTracing);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// FreeTraceItemTable
|
|
// --------------------------------------------------------------------------------
|
|
void FreeTraceItemTable(LPTRACEITEMTABLE pTable)
|
|
{
|
|
for (ULONG i=0; i<pTable->cItems; i++)
|
|
SafeMemFree(pTable->prgItem[i].pszName);
|
|
SafeMemFree(pTable->prgItem);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// FreeTraceComponentInfo
|
|
// --------------------------------------------------------------------------------
|
|
void FreeTraceComponentInfo(LPTRACECOMPONENTINFO pInfo)
|
|
{
|
|
SafeRelease(pInfo->pStmFile);
|
|
SafeMemFree(pInfo->pszComponent);
|
|
FreeTraceItemTable(&pInfo->rFunctions);
|
|
FreeTraceItemTable(&pInfo->rClasses);
|
|
FreeTraceItemTable(&pInfo->rThreads);
|
|
FreeTraceItemTable(&pInfo->rFiles);
|
|
FreeTraceItemTable(&pInfo->rTagged);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// FreeTraceThreadInfo
|
|
// --------------------------------------------------------------------------------
|
|
void FreeTraceThreadInfo(LPTRACETHREADINFO pThread)
|
|
{
|
|
//Assert(pThread->cStackDepth == 0);
|
|
SafeMemFree(pThread->pszName);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// UninitializeTracingSystem
|
|
// --------------------------------------------------------------------------------
|
|
void UninitializeTracingSystem(void)
|
|
{
|
|
// Locals
|
|
LPTRACECOMPONENTINFO pCurrComponent=g_pHeadComponent;
|
|
LPTRACECOMPONENTINFO pNextComponent;
|
|
|
|
// Loop
|
|
while(pCurrComponent)
|
|
{
|
|
// Save Next
|
|
pNextComponent = pCurrComponent->pNext;
|
|
|
|
// Free the Current
|
|
FreeTraceComponentInfo(pCurrComponent);
|
|
g_pMalloc->Free(pCurrComponent);
|
|
|
|
// Goto Next
|
|
pCurrComponent = pNextComponent;
|
|
}
|
|
|
|
// Reset Headers
|
|
g_pHeadComponent = NULL;
|
|
|
|
// Free Critical Section
|
|
DeleteCriticalSection(&g_csTracing);
|
|
|
|
// Free thread tls index
|
|
TlsFree(g_dwTlsTraceThread);
|
|
g_dwTlsTraceThread = 0xffffffff;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CoStartTracingComponent
|
|
// --------------------------------------------------------------------------------
|
|
OESTDAPI_(HRESULT) CoStartTracingComponent(
|
|
IN HKEY hKeyRoot,
|
|
IN LPCSTR pszRegRoot,
|
|
OUT LPDWORD pdwTraceId)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
HKEY hRoot=NULL;
|
|
DWORD dw;
|
|
LPTRACECOMPONENTINFO pComponent=NULL;
|
|
ULONG i;
|
|
LONG j;
|
|
|
|
// Invalid Arg
|
|
if (NULL == hKeyRoot || NULL == pszRegRoot || NULL == pdwTraceId)
|
|
return TrapError(E_INVALIDARG);
|
|
|
|
// Initialize
|
|
*pdwTraceId = 0;
|
|
|
|
// Thread Safe
|
|
EnterCriticalSection(&g_csTracing);
|
|
|
|
// Open pszRegRoot
|
|
if (RegOpenKeyEx(hKeyRoot, pszRegRoot, 0, KEY_ALL_ACCESS, &hRoot) != ERROR_SUCCESS)
|
|
{
|
|
// Lets create the subkey
|
|
if (RegCreateKeyEx(hKeyRoot, pszRegRoot, 0, NULL, NULL, KEY_ALL_ACCESS, NULL, &hRoot, &dw) != ERROR_SUCCESS)
|
|
{
|
|
Assert(FALSE);
|
|
hRoot = NULL;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Allocate a new LPTRACECOMPONENTINFO
|
|
CHECKALLOC(pComponent = (LPTRACECOMPONENTINFO)g_pMalloc->Alloc(sizeof(TRACECOMPONENTINFO)));
|
|
|
|
// Loads Configuration...
|
|
ReadTraceComponentInfo(hRoot, &g_rRegKeyNames, pComponent);
|
|
|
|
// Read trace item tables
|
|
ReadTraceItemTable(hRoot, "Functions", &pComponent->rFunctions);
|
|
ReadTraceItemTable(hRoot, "Classes", &pComponent->rClasses);
|
|
ReadTraceItemTable(hRoot, "Threads", &pComponent->rThreads);
|
|
ReadTraceItemTable(hRoot, "Files", &pComponent->rFiles);
|
|
ReadTraceItemTable(hRoot, "Tagged", &pComponent->rTagged);
|
|
|
|
// Fixup Class Names to have a :: on the end
|
|
for (i=0; i<pComponent->rClasses.cItems; i++)
|
|
{
|
|
// I'm guaranteed to have extra room, loot at ReadTraceItemTable
|
|
StrCatBuff(pComponent->rClasses.prgItem[i].pszName, "::", pComponent->rClasses.prgItem[i].cchName);
|
|
}
|
|
|
|
// Parse off the component name
|
|
for (j=lstrlen(pszRegRoot); j>=0; j--)
|
|
{
|
|
// Software\\Microsoft\\Outlook Express\\Debug\\MSIMNUI
|
|
if ('\\' == pszRegRoot[j])
|
|
{
|
|
// Dup the string
|
|
CHECKALLOC(pComponent->pszComponent = PszDupA(pszRegRoot + j + 1));
|
|
|
|
// Done
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Did we find a component name
|
|
Assert(pComponent->pszComponent);
|
|
if (NULL == pComponent->pszComponent)
|
|
{
|
|
// Unknown Module
|
|
CHECKALLOC(pComponent->pszComponent = PszDupA("ModUnknown"));
|
|
}
|
|
|
|
// Link pComponent into linked list
|
|
pComponent->pNext = g_pHeadComponent;
|
|
if (g_pHeadComponent)
|
|
g_pHeadComponent->pPrev = pComponent;
|
|
g_pHeadComponent = pComponent;
|
|
|
|
// Set Return Value
|
|
*pdwTraceId = (DWORD)pComponent;
|
|
pComponent = NULL;
|
|
|
|
exit:
|
|
// Thread Safe
|
|
LeaveCriticalSection(&g_csTracing);
|
|
|
|
// Cleanup
|
|
if (hRoot)
|
|
RegCloseKey(hRoot);
|
|
if (pComponent)
|
|
{
|
|
FreeTraceComponentInfo(pComponent);
|
|
g_pMalloc->Free(pComponent);
|
|
}
|
|
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CoStopTracingComponent
|
|
// --------------------------------------------------------------------------------
|
|
OESTDAPI_(HRESULT) CoStopTracingComponent(
|
|
IN DWORD dwTraceId /* g_dbg_dwTraceId */)
|
|
{
|
|
// Locals
|
|
LPTRACECOMPONENTINFO pInfo;
|
|
|
|
// Invalid Arg
|
|
if (0 == dwTraceId)
|
|
return E_INVALIDARG;
|
|
|
|
// Thread Safe
|
|
EnterCriticalSection(&g_csTracing);
|
|
|
|
// Cast
|
|
pInfo = (LPTRACECOMPONENTINFO)dwTraceId;
|
|
|
|
// Find pInfo in the linked list
|
|
if (pInfo->pNext)
|
|
pInfo->pNext->pPrev = pInfo->pPrev;
|
|
if (pInfo->pPrev)
|
|
pInfo->pPrev->pNext = pInfo->pNext;
|
|
|
|
// Was this the head item ?
|
|
if (pInfo == g_pHeadComponent)
|
|
g_pHeadComponent = pInfo->pNext;
|
|
|
|
// Free pInfo
|
|
FreeTraceComponentInfo(pInfo);
|
|
g_pMalloc->Free(pInfo);
|
|
|
|
// Thread Safe
|
|
LeaveCriticalSection(&g_csTracing);
|
|
|
|
// Done
|
|
return S_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ThreadAllocateTlsTraceInfo
|
|
// --------------------------------------------------------------------------------
|
|
void ThreadAllocateTlsTraceInfo(void)
|
|
{
|
|
// Do we have a tls index
|
|
if (0xffffffff != g_dwTlsTraceThread)
|
|
{
|
|
// Allocate thread info
|
|
LPTRACETHREADINFO pThread = (LPTRACETHREADINFO)g_pMalloc->Alloc(sizeof(TRACETHREADINFO));
|
|
|
|
// Zero It out
|
|
if (pThread)
|
|
{
|
|
// Zero It
|
|
ZeroMemory(pThread, sizeof(TRACETHREADINFO));
|
|
|
|
// Get the thread id
|
|
pThread->dwThreadId = GetCurrentThreadId();
|
|
}
|
|
|
|
// Store It
|
|
TlsSetValue(g_dwTlsTraceThread, pThread);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ThreadFreeTlsTraceInfo
|
|
// --------------------------------------------------------------------------------
|
|
void ThreadFreeTlsTraceInfo(void)
|
|
{
|
|
// Do we have a tls index
|
|
if (0xffffffff != g_dwTlsTraceThread)
|
|
{
|
|
// Allocate thread info
|
|
LPTRACETHREADINFO pThread = (LPTRACETHREADINFO)TlsGetValue(g_dwTlsTraceThread);
|
|
|
|
// Free It
|
|
if (pThread)
|
|
{
|
|
SafeMemFree(pThread->pszName);
|
|
MemFree(pThread);
|
|
}
|
|
|
|
// Store It
|
|
TlsSetValue(g_dwTlsTraceThread, NULL);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CoTraceSetCurrentThreadName
|
|
// --------------------------------------------------------------------------------
|
|
OESTDAPI_(HRESULT) CoTraceSetCurrentThreadName(
|
|
IN LPCSTR pszThreadName)
|
|
{
|
|
// Invalid Arg
|
|
Assert(pszThreadName);
|
|
|
|
// Do we have a tls index
|
|
if (0xffffffff != g_dwTlsTraceThread)
|
|
{
|
|
// Allocate thread info
|
|
LPTRACETHREADINFO pThread = (LPTRACETHREADINFO)TlsGetValue(g_dwTlsTraceThread);
|
|
|
|
// If there is a thread
|
|
if (pThread)
|
|
{
|
|
// If the name has not yet been set...
|
|
SafeMemFree(pThread->pszName);
|
|
|
|
// Duplicate It
|
|
pThread->pszName = PszDupA(pszThreadName);
|
|
Assert(pThread->pszName);
|
|
}
|
|
}
|
|
|
|
// Done
|
|
return S_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// PGetCurrentTraceThread
|
|
// --------------------------------------------------------------------------------
|
|
LPTRACETHREADINFO PGetCurrentTraceThread(void)
|
|
{
|
|
// Locals
|
|
LPTRACETHREADINFO pThread=NULL;
|
|
|
|
// Do we have a tls index
|
|
if (0xffffffff != g_dwTlsTraceThread)
|
|
{
|
|
// Allocate thread info
|
|
pThread = (LPTRACETHREADINFO)TlsGetValue(g_dwTlsTraceThread);
|
|
}
|
|
|
|
// Done
|
|
return pThread;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ReadTraceComponentInfo
|
|
// --------------------------------------------------------------------------------
|
|
void ReadTraceComponentInfo(
|
|
IN HKEY hRegKey,
|
|
IN LPREGISTRYNAMES pNames,
|
|
OUT LPTRACECOMPONENTINFO pInfo)
|
|
{
|
|
// Locals
|
|
ULONG cb;
|
|
|
|
// Invalid ARg
|
|
Assert(hRegKey && pNames && pInfo);
|
|
|
|
// ZeroInit
|
|
ZeroMemory(pInfo, sizeof(TRACECOMPONENTINFO));
|
|
|
|
// Read pInfo->fEnableTracing
|
|
cb = sizeof(pInfo->tracetype);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszEnableTracing, 0, NULL, (LPBYTE)&pInfo->tracetype, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
pInfo->tracetype = TRACE_NONE;
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszEnableTracing, 0, REG_DWORD, (LPBYTE)&pInfo->tracetype, sizeof(DWORD)) == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Read pInfo->logtype
|
|
cb = sizeof(DWORD);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszTraceLogType, 0, NULL, (LPBYTE)&pInfo->logtype, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
pInfo->logtype = LOGTYPE_OUTPUT;
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszTraceLogType, 0, REG_DWORD, (LPBYTE)&pInfo->logtype, sizeof(DWORD)) == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Read pInfo->szLogfilePath
|
|
cb = sizeof(pInfo->szLogfilePath);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszLogfilePath, 0, NULL, (LPBYTE)&pInfo->szLogfilePath, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszLogfilePath, 0, REG_SZ, (LPBYTE)"", 1) == ERROR_SUCCESS);
|
|
|
|
// Adjust the logtype
|
|
if (pInfo->logtype >= LOGTYPE_FILE)
|
|
pInfo->logtype = LOGTYPE_OUTPUT;
|
|
}
|
|
|
|
// Read pInfo->fResetLogfile
|
|
cb = sizeof(DWORD);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszResetLogfile, 0, NULL, (LPBYTE)&pInfo->fResetLogfile, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
pInfo->fResetLogfile = TRUE;
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszResetLogfile, 0, REG_DWORD, (LPBYTE)&pInfo->fResetLogfile, sizeof(DWORD)) == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Read pInfo->fTraceCallIndent
|
|
cb = sizeof(DWORD);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszTraceCallIndent, 0, NULL, (LPBYTE)&pInfo->fTraceCallIndent, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
pInfo->fTraceCallIndent = TRUE;
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszTraceCallIndent, 0, REG_DWORD, (LPBYTE)&pInfo->fTraceCallIndent, sizeof(DWORD)) == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Read pInfo->fTraceCalls
|
|
cb = sizeof(DWORD);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszLogTraceCall, 0, NULL, (LPBYTE)&pInfo->fTraceCalls, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
pInfo->fTraceCalls = FALSE;
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszLogTraceCall, 0, REG_DWORD, (LPBYTE)&pInfo->fTraceCalls, sizeof(DWORD)) == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Read pInfo->fTraceInfo
|
|
cb = sizeof(DWORD);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszLogTraceInfo, 0, NULL, (LPBYTE)&pInfo->fTraceInfo, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
pInfo->fTraceInfo = FALSE;
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszLogTraceInfo, 0, REG_DWORD, (LPBYTE)&pInfo->fTraceInfo, sizeof(DWORD)) == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Read pInfo->fLaunchLogWatcher
|
|
cb = sizeof(DWORD);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszLaunchLogWatcher, 0, NULL, (LPBYTE)&pInfo->fLaunchLogWatcher, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
pInfo->fLaunchLogWatcher = FALSE;
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszLaunchLogWatcher, 0, REG_DWORD, (LPBYTE)&pInfo->fLaunchLogWatcher, sizeof(DWORD)) == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Read pInfo->szLogWatchFilePath
|
|
cb = sizeof(pInfo->szLogWatchFilePath);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszLogWatchFilePath, 0, NULL, (LPBYTE)&pInfo->szLogWatchFilePath, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszLogWatchFilePath, 0, REG_SZ, (LPBYTE)"", 1) == ERROR_SUCCESS);
|
|
|
|
// Reset
|
|
pInfo->fLaunchLogWatcher = FALSE;
|
|
}
|
|
|
|
// Read pInfo->fDisplaySourceFilePaths
|
|
cb = sizeof(DWORD);
|
|
if (RegQueryValueEx(hRegKey, pNames->pszDisplaySourceFilePaths, 0, NULL, (LPBYTE)&pInfo->fDisplaySourceFilePaths, &cb) != ERROR_SUCCESS)
|
|
{
|
|
// Set the Default Value
|
|
pInfo->fDisplaySourceFilePaths = FALSE;
|
|
SideAssert(RegSetValueEx(hRegKey, pNames->pszDisplaySourceFilePaths, 0, REG_DWORD, (LPBYTE)&pInfo->fDisplaySourceFilePaths, sizeof(DWORD)) == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Open the file...
|
|
if (LOGTYPE_BOTH == pInfo->logtype || LOGTYPE_FILE == pInfo->logtype)
|
|
{
|
|
// Open the logfile
|
|
if (FAILED(OpenFileStreamShare(pInfo->szLogfilePath, pInfo->fResetLogfile ? CREATE_ALWAYS : OPEN_ALWAYS,
|
|
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &pInfo->pStmFile)))
|
|
{
|
|
// Switch Logtype
|
|
Assert(FALSE);
|
|
pInfo->logtype = LOGTYPE_OUTPUT;
|
|
}
|
|
|
|
// Launch LogWatcher ?
|
|
if (pInfo->pStmFile && pInfo->fLaunchLogWatcher)
|
|
{
|
|
// Locals
|
|
STARTUPINFO rStart;
|
|
PROCESS_INFORMATION rProcess;
|
|
LPSTR pszCmdLine;
|
|
|
|
// Init process info
|
|
ZeroMemory(&rProcess, sizeof(PROCESS_INFORMATION));
|
|
|
|
// Init Startup info
|
|
ZeroMemory(&rStart, sizeof(STARTUPINFO));
|
|
rStart.cb = sizeof(STARTUPINFO);
|
|
rStart.wShowWindow = SW_NORMAL;
|
|
|
|
// Create the command line
|
|
DWORD cchSize = (lstrlen(pInfo->szLogWatchFilePath) + lstrlen(pInfo->szLogfilePath) + 2);
|
|
pszCmdLine = (LPSTR)g_pMalloc->Alloc(cchSize);
|
|
Assert(pszCmdLine);
|
|
wnsprintf(pszCmdLine, cchSize, "%s %s", pInfo->szLogWatchFilePath, pInfo->szLogfilePath);
|
|
|
|
// Create the process...
|
|
CreateProcess(pInfo->szLogWatchFilePath, pszCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &rStart, &rProcess);
|
|
|
|
// Cleanup
|
|
g_pMalloc->Free(pszCmdLine);
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ReadTraceItemTable
|
|
// --------------------------------------------------------------------------------
|
|
void ReadTraceItemTable(
|
|
IN HKEY hKeyRoot,
|
|
IN LPCSTR pszSubKey,
|
|
OUT LPTRACEITEMTABLE pTable)
|
|
{
|
|
// Locals
|
|
HKEY hSubKey=NULL;
|
|
ULONG cbMax;
|
|
ULONG i;
|
|
ULONG cb;
|
|
LONG lResult;
|
|
|
|
// Invalid Arg
|
|
Assert(hKeyRoot && pszSubKey && pTable);
|
|
|
|
// Init
|
|
ZeroMemory(pTable, sizeof(TRACEITEMTABLE));
|
|
|
|
// Open pszRegRoot
|
|
if (RegOpenKeyEx(hKeyRoot, pszSubKey, 0, KEY_ALL_ACCESS, &hSubKey) != ERROR_SUCCESS)
|
|
{
|
|
// Lets create the subkey
|
|
if (RegCreateKeyEx(hKeyRoot, pszSubKey, 0, NULL, NULL, KEY_ALL_ACCESS, NULL, &hSubKey, &cbMax) != ERROR_SUCCESS)
|
|
{
|
|
Assert(FALSE);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Count SubItems
|
|
if (RegQueryInfoKey(hSubKey, NULL, NULL, NULL, &pTable->cItems, &cbMax, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
|
{
|
|
pTable->cItems = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// No Items
|
|
if (0 == pTable->cItems)
|
|
goto exit;
|
|
|
|
// Check
|
|
AssertSz(cbMax < MAX_PATH, "Name is longer than MAX_PATH.");
|
|
|
|
// Allocate an Array
|
|
pTable->prgItem = (LPTRACEITEMINFO)g_pMalloc->Alloc(pTable->cItems * sizeof(TRACEITEMINFO));
|
|
|
|
// Init
|
|
ZeroMemory(pTable->prgItem, pTable->cItems * sizeof(TRACEITEMINFO));
|
|
|
|
// Loop through the subkeys
|
|
for (i=0; i<pTable->cItems; i++)
|
|
{
|
|
// Allocate
|
|
pTable->prgItem[i].pszName = (LPSTR)g_pMalloc->Alloc(cbMax + 10);
|
|
Assert(pTable->prgItem[i].pszName);
|
|
|
|
// Set max size
|
|
lResult = RegEnumKeyEx(hSubKey, i, pTable->prgItem[i].pszName, &cb, NULL, NULL, NULL, NULL);
|
|
|
|
// Done or failure
|
|
if (lResult == ERROR_NO_MORE_ITEMS)
|
|
break;
|
|
else if (lResult != ERROR_SUCCESS)
|
|
{
|
|
Assert(FALSE);
|
|
continue;
|
|
}
|
|
|
|
// Save Length of Name
|
|
pTable->prgItem[i].cchName = lstrlen(pTable->prgItem[i].pszName);
|
|
}
|
|
|
|
exit:
|
|
// Cleanup
|
|
if (hSubKey)
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDebugTrace::CDebugTrace
|
|
// --------------------------------------------------------------------------------
|
|
CDebugTrace::CDebugTrace(DWORD dwTraceId, LPCSTR pszFilePath, ULONG ulLine, LPCSTR pszFunction, LPCSTR pszTag, LPCSTR pszMessage)
|
|
{
|
|
// Get Component Information
|
|
m_pComponent = (LPTRACECOMPONENTINFO)dwTraceId;
|
|
|
|
// Invalid Arg
|
|
Assert(pszFilePath && pszFunction);
|
|
|
|
// Save Function and File Name
|
|
m_pszFunction = pszFunction;
|
|
m_pszFilePath = pszFilePath;
|
|
m_pszFileName = NULL;
|
|
m_ulCallLine = ulLine;
|
|
m_pThreadDefault = NULL;
|
|
m_dwTickEnter = GetTickCount();
|
|
|
|
// Get thread information
|
|
m_pThread = PGetCurrentTraceThread();
|
|
if (NULL == m_pThread)
|
|
{
|
|
// Allocate a default thread info object
|
|
m_pThreadDefault = (LPTRACETHREADINFO)g_pMalloc->Alloc(sizeof(TRACETHREADINFO));
|
|
|
|
// Zero init
|
|
ZeroMemory(m_pThreadDefault, sizeof(TRACETHREADINFO));
|
|
|
|
// Set thread id, name and stack depth
|
|
m_pThreadDefault->dwThreadId = GetCurrentThreadId();
|
|
m_pThreadDefault->pszName = "_Unknown_";
|
|
m_pThreadDefault->cStackDepth = 0;
|
|
|
|
// Save a current thread information
|
|
m_pThread = m_pThreadDefault;
|
|
}
|
|
|
|
// Save Stack Depth
|
|
m_cStackDepth = m_pThread->cStackDepth;
|
|
|
|
// Are we tracing
|
|
m_fTracing = _FIsTraceEnabled(pszTag);
|
|
|
|
// Should we log this ?
|
|
if (m_fTracing && m_pComponent && m_pComponent->fTraceCalls)
|
|
{
|
|
// Output some information
|
|
if (pszMessage)
|
|
_OutputDebugText(NULL, ulLine, "ENTER: %s - %s\r\n", m_pszFunction, pszMessage);
|
|
else
|
|
_OutputDebugText(NULL, ulLine, "ENTER: %s\r\n", m_pszFunction);
|
|
}
|
|
|
|
// Increment Stack Depth
|
|
m_pThread->cStackDepth++;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDebugTrace::~CDebugTrace
|
|
// --------------------------------------------------------------------------------
|
|
CDebugTrace::~CDebugTrace(void)
|
|
{
|
|
// Invalid Arg
|
|
Assert(m_pThread);
|
|
|
|
// Decrement Stack Depth
|
|
m_pThread->cStackDepth--;
|
|
|
|
// Did we trace the call
|
|
if (m_fTracing && m_pComponent && m_pComponent->fTraceCalls)
|
|
{
|
|
// Output some information
|
|
_OutputDebugText(NULL, m_ulCallLine, "LEAVE: %s (Inc.Time: %d ms)\r\n", m_pszFunction, ((GetTickCount() - m_dwTickEnter)));
|
|
}
|
|
|
|
// Cleanup
|
|
SafeMemFree(m_pThreadDefault);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDebugTrace::_FIsTraceEnabled
|
|
// --------------------------------------------------------------------------------
|
|
BOOL CDebugTrace::_FIsTraceEnabled(LPCSTR pszTag)
|
|
{
|
|
// No Component
|
|
if (NULL == m_pComponent)
|
|
return FALSE;
|
|
|
|
// No tracing enabled
|
|
if (TRACE_NONE == m_pComponent->tracetype)
|
|
return FALSE;
|
|
|
|
// Trace Everything
|
|
if (TRACE_EVERYTHING == m_pComponent->tracetype)
|
|
return TRUE;
|
|
|
|
// Is current inforamtion registered
|
|
return _FIsRegistered(pszTag);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDebugTrace::_FIsRegistered
|
|
// --------------------------------------------------------------------------------
|
|
BOOL CDebugTrace::_FIsRegistered(LPCSTR pszTag)
|
|
{
|
|
// Locals
|
|
ULONG i;
|
|
|
|
// No Component
|
|
if (NULL == m_pComponent)
|
|
return FALSE;
|
|
|
|
// Search Registered Classes
|
|
for (i=0; i<m_pComponent->rClasses.cItems; i++)
|
|
{
|
|
// Better have a name
|
|
Assert(m_pComponent->rClasses.prgItem[i].pszName);
|
|
|
|
// Compare CClass:: to m_pszFunction
|
|
if (StrCmpN(m_pszFunction, m_pComponent->rClasses.prgItem[i].pszName, m_pComponent->rClasses.prgItem[i].cchName) == 0)
|
|
return TRUE;
|
|
}
|
|
|
|
// Search Registered Functions
|
|
for (i=0; i<m_pComponent->rFunctions.cItems; i++)
|
|
{
|
|
// Better have a name
|
|
Assert(m_pComponent->rFunctions.prgItem[i].pszName);
|
|
|
|
// Compare CClass:: to m_pszFunction
|
|
if (lstrcmp(m_pszFunction, m_pComponent->rFunctions.prgItem[i].pszName) == 0)
|
|
return TRUE;
|
|
}
|
|
|
|
// Get a filename
|
|
if (NULL == m_pszFileName)
|
|
m_pszFileName = PathFindFileName(m_pszFilePath);
|
|
|
|
// Search Registered Files
|
|
for (i=0; i<m_pComponent->rFiles.cItems; i++)
|
|
{
|
|
// Better have a name
|
|
Assert(m_pComponent->rFiles.prgItem[i].pszName);
|
|
|
|
// Compare CClass:: to m_pszFunction
|
|
if (lstrcmp(m_pszFileName, m_pComponent->rFiles.prgItem[i].pszName) == 0)
|
|
return TRUE;
|
|
}
|
|
|
|
// Does this thread have a name
|
|
if (m_pThread->pszName)
|
|
{
|
|
// Search Registered Threads
|
|
for (i=0; i<m_pComponent->rThreads.cItems; i++)
|
|
{
|
|
// Better have a name
|
|
Assert(m_pComponent->rThreads.prgItem[i].pszName);
|
|
|
|
// Compare CClass:: to m_pszFunction
|
|
if (lstrcmp(m_pThread->pszName, m_pComponent->rThreads.prgItem[i].pszName) == 0)
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// Search Tagged Items
|
|
if (pszTag)
|
|
{
|
|
for (i=0; i<m_pComponent->rTagged.cItems; i++)
|
|
{
|
|
// Better have a name
|
|
Assert(m_pComponent->rTagged.prgItem[i].pszName);
|
|
|
|
// Compare CClass:: to m_pszFunction
|
|
if (lstrcmp(pszTag, m_pComponent->rTagged.prgItem[i].pszName) == 0)
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// Don't log it
|
|
return FALSE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDebugTrace::_OutputDebugText
|
|
// --------------------------------------------------------------------------------
|
|
void CDebugTrace::_OutputDebugText(CLogFile *pLog, ULONG ulLine, LPSTR pszFormat, ...)
|
|
{
|
|
// Locals
|
|
va_list arglist;
|
|
ULONG cchOutput;
|
|
LPCSTR pszFile;
|
|
CHAR szIndent[512];
|
|
|
|
// Should we output anything
|
|
if (NULL == m_pComponent || (m_pComponent->logtype == LOGTYPE_NONE && NULL == pLog))
|
|
return;
|
|
|
|
// Format the string
|
|
va_start(arglist, pszFormat);
|
|
wvnsprintf(m_pThread->szBuffer, ARRAYSIZE(m_pThread->szBuffer), pszFormat, arglist);
|
|
va_end(arglist);
|
|
|
|
// Write Header
|
|
if (m_pComponent->fDisplaySourceFilePaths)
|
|
pszFile = m_pszFilePath;
|
|
else
|
|
{
|
|
// Get a filename
|
|
if (NULL == m_pszFileName)
|
|
{
|
|
// Parse out the filename
|
|
m_pszFileName = PathFindFileName(m_pszFilePath);
|
|
if (NULL == m_pszFileName)
|
|
m_pszFileName = m_pszFilePath;
|
|
}
|
|
|
|
// Use just a filename
|
|
pszFile = m_pszFileName;
|
|
}
|
|
|
|
// Setup Indent
|
|
if (m_pComponent->fTraceCalls && m_pComponent->fTraceCallIndent)
|
|
{
|
|
// Assert that we have enough room
|
|
Assert(m_cStackDepth * 4 <= sizeof(szIndent));
|
|
|
|
// Setup the indent
|
|
FillMemory(szIndent, m_cStackDepth * 4, ' ');
|
|
|
|
// Insert a null
|
|
szIndent[m_cStackDepth * 4] = '\0';
|
|
}
|
|
else
|
|
*szIndent = '\0';
|
|
|
|
// Build the string
|
|
cchOutput = wnsprintf(m_pThread->szOutput, ARRAYSIZE(m_pThread->szOutput), "0x%08X: %s: %s(%05d) %s%s", m_pThread->dwThreadId, m_pComponent->pszComponent, pszFile, ulLine, szIndent, m_pThread->szBuffer);
|
|
Assert(cchOutput < sizeof(m_pThread->szOutput));
|
|
|
|
// Output to vc window
|
|
if (LOGTYPE_OUTPUT == m_pComponent->logtype || LOGTYPE_BOTH == m_pComponent->logtype)
|
|
OutputDebugString(m_pThread->szOutput);
|
|
|
|
// Output to file
|
|
if (LOGTYPE_FILE == m_pComponent->logtype || LOGTYPE_BOTH == m_pComponent->logtype)
|
|
m_pComponent->pStmFile->Write(m_pThread->szOutput, cchOutput, NULL);
|
|
|
|
// LogFile
|
|
if (pLog)
|
|
pLog->DebugLog(m_pThread->szOutput);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDebugTrace::TraceInfo
|
|
// --------------------------------------------------------------------------------
|
|
void CDebugTrace::TraceInfoImpl(ULONG ulLine, LPCSTR pszMessage, CLogFile *pLog)
|
|
{
|
|
// Should we log this ?
|
|
if (m_fTracing && m_pComponent && m_pComponent->fTraceInfo)
|
|
{
|
|
// Output some information
|
|
if (pszMessage)
|
|
_OutputDebugText(pLog, ulLine, "INFO: %s - %s\r\n", m_pszFunction, pszMessage);
|
|
else
|
|
_OutputDebugText(pLog, ulLine, "INFO: %s\r\n", m_pszFunction);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// CDebugTrace::TraceResult
|
|
// ----------------------------------------------------------------------------
|
|
HRESULT CDebugTrace::TraceResultImpl(ULONG ulLine, HRESULT hrResult, LPCSTR pszMessage, CLogFile *pLog)
|
|
{
|
|
// Output some information
|
|
if (pszMessage)
|
|
_OutputDebugText(pLog, ulLine, "RESULT: %s - HRESULT(0x%08X) - GetLastError() = %d - %s\r\n", m_pszFunction, hrResult, GetLastError(), pszMessage);
|
|
else
|
|
_OutputDebugText(pLog, ulLine, "RESULT: %s - HRESULT(0x%08X) - GetLastError() = %d\r\n", m_pszFunction, hrResult, GetLastError());
|
|
|
|
// Done
|
|
return hrResult;
|
|
}
|
|
|
|
#endif // DEBUG
|