Windows2003-3790/inetcore/outlookexpress/msoert/msoedbg.cpp
2020-09-30 16:53:55 +02:00

911 lines
30 KiB
C++

// --------------------------------------------------------------------------------
// 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