debug.cpp
资源名称:shell.rar [点击查看]
上传用户:xhy777
上传日期:2007-02-14
资源大小:24088k
文件大小:19k
源码类别:
系统编程
开发平台:
Visual C++
- /*----------------------------------------------------------------------------
- / Title;
- / debug.cpp
- /
- / Authors;
- / Jeffrey Saathoff (jeffreys)
- /
- / Notes;
- / Provides printf style debug output
- /----------------------------------------------------------------------------*/
- #include "stdafx.h"
- #include <stdio.h>
- #include <comctrlp.h>
- #pragma hdrstop
- // Define some things for debug.h
- //
- #define SZ_DEBUGINI "ccshell.ini"
- #define SZ_DEBUGSECTION "netplwiz"
- #define SZ_MODULE "NETPLWIZ"
- #define DECLARE_DEBUG
- #include "debug.h"
- #ifdef DEBUG
- DWORD g_dwTraceMask = 0;
- DWORD g_tlsDebug = 0xffffffffL;
- #define MAX_CALL_DEPTH 64
- #define BUFFER_SIZE 2048
- class CDebugStack
- {
- private:
- DWORD m_dwThreadID;
- LONG m_cDepth;
- struct
- {
- BOOL fTracedYet;
- LPCTSTR pszFunctionName;
- DWORD dwMask;
- }
- m_CallStack[MAX_CALL_DEPTH];
- TCHAR m_szStringBuffer[BUFFER_SIZE];
- public:
- CDebugStack() : m_dwThreadID(GetCurrentThreadId()), m_cDepth(-1)
- { ZeroMemory(&m_CallStack, SIZEOF(m_CallStack)); }
- public:
- void _Indent(LONG iDepth, LPCTSTR pszFormat, ...);
- void _vIndent(LONG iDepth, LPCTSTR pszFormat, va_list va);
- BOOL _TraceProlog(LONG iDepth, BOOL fForce);
- void _TraceEnter(DWORD dwMask, LPCTSTR pName);
- void _TraceLeave(void);
- void _Trace(BOOL bForce, LPCTSTR pszFormat, ...);
- void _vTrace(BOOL bForce, LPCTSTR pszFormat, va_list va);
- void _TraceGUID(LPCTSTR pPrefix, REFGUID rGUID);
- void _TraceAssert(int iLine, LPTSTR pFilename);
- };
- typedef CDebugStack *PDEBUGSTACK;
- class CDebugStackHolder
- {
- private:
- HDPA m_hDebugStackList;
- CRITICAL_SECTION m_csStackList;
- public:
- CDebugStackHolder() : m_hDebugStackList(NULL) { InitializeCriticalSection(&m_csStackList); }
- ~CDebugStackHolder();
- public:
- void Add(PDEBUGSTACK pDebugStack);
- void Remove(PDEBUGSTACK pDebugStack);
- };
- typedef CDebugStackHolder *PDEBUGSTACKHOLDER;
- PDEBUGSTACKHOLDER g_pStackHolder = NULL;
- /*-----------------------------------------------------------------------------
- / _Indent
- / -------
- / Output to the debug stream indented by n columns.
- /
- / In:
- / i = column to indent to.
- / pszFormat -> string to be indented
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void CDebugStack::_Indent(LONG iDepth, LPCTSTR pszFormat, ...)
- {
- va_list va;
- va_start(va, pszFormat);
- _vIndent(iDepth, pszFormat, va);
- va_end(va);
- }
- void CDebugStack::_vIndent(LONG iDepth, LPCTSTR pszFormat, va_list va)
- {
- m_szStringBuffer[0] = TEXT(' ');
- wsprintf(m_szStringBuffer, TEXT("%08x "), m_dwThreadID);
- iDepth = min(iDepth, MAX_CALL_DEPTH - 1);
- for ( ; iDepth > 0 ; iDepth-- )
- lstrcat(m_szStringBuffer, TEXT(" "));
- wvsprintf(m_szStringBuffer + lstrlen(m_szStringBuffer), pszFormat, va);
- lstrcat(m_szStringBuffer, TEXT("n"));
- OutputDebugString(m_szStringBuffer);
- }
- /*-----------------------------------------------------------------------------
- / _TraceProlog
- / -------------
- / Handle the prolog to a prefix string, including outputting the
- / function name if we haven't already.
- /
- / In:
- / iDepth = depth in the call stack
- / fForce = ignore flags
- /
- / Out:
- / BOOL if trace output should be made
- /----------------------------------------------------------------------------*/
- BOOL CDebugStack::_TraceProlog(LONG iDepth, BOOL fForce)
- {
- if ( iDepth < 0 || iDepth >= MAX_CALL_DEPTH )
- return FALSE;
- if ( (g_dwTraceMask & m_CallStack[iDepth].dwMask) || fForce )
- {
- if ( !m_CallStack[iDepth].fTracedYet )
- {
- if ( iDepth > 0 )
- _TraceProlog(iDepth-1, TRUE);
- _Indent(iDepth, m_CallStack[iDepth].pszFunctionName);
- m_CallStack[iDepth].fTracedYet = TRUE;
- }
- return TRUE;
- }
- return FALSE;
- }
- /*-----------------------------------------------------------------------------
- / _TraceEnter
- / ------------
- / Set the debugging call stack up to indicate which function we are in.
- /
- / In:
- / pName -> function name to be displayed in subsequent trace output.
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void CDebugStack::_TraceEnter(DWORD dwMask, LPCTSTR pName)
- {
- m_cDepth++;
- if ( m_cDepth < MAX_CALL_DEPTH )
- {
- if ( !pName )
- pName = TEXT("<no name>"); // no function name given
- m_CallStack[m_cDepth].fTracedYet = FALSE;
- m_CallStack[m_cDepth].pszFunctionName = pName;
- m_CallStack[m_cDepth].dwMask = dwMask;
- //if ( m_cDepth > 0 )
- // _TraceProlog(m_cDepth-1, FALSE);
- }
- }
- /*-----------------------------------------------------------------------------
- / _TraceLeave
- / ------------
- / On exit from a function this will adjust the function stack pointer to
- / point to our previous function. If no trace output has been made then
- / we will output the function name on a single line (to indicate we went somewhere).
- /
- / In:
- / -
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void CDebugStack::_TraceLeave(void)
- {
- //_TraceProlog(m_cDepth, FALSE);
- //if ( !m_cDepth && m_CallStack[0].fTracedYet )
- // OutputDebugString(TEXT("n"));
- m_cDepth = max(m_cDepth-1, -1); // account for underflow
- }
- /*-----------------------------------------------------------------------------
- / _Trace
- / -------
- / Perform printf formatting to the debugging stream. We indent the output
- / and stream the function name as required to give some indication of
- / call stack depth.
- /
- / In:
- / pszFormat -> printf style formatting string
- / ... = arguments as required for the formatting
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void CDebugStack::_Trace(BOOL bForce, LPCTSTR pszFormat, ...)
- {
- va_list va;
- va_start(va, pszFormat);
- _vTrace(bForce, pszFormat, va);
- va_end(va);
- }
- void CDebugStack::_vTrace(BOOL bForce, LPCTSTR pszFormat, va_list va)
- {
- if ( _TraceProlog(m_cDepth, bForce) || bForce )
- _vIndent(m_cDepth+1, pszFormat, va);
- }
- /*-----------------------------------------------------------------------------
- / _TraceGUID
- / -----------
- / Given a GUID output it into the debug string, first we try and map it
- / to a name (ie. IShellFolder), if that didn't work then we convert it
- / to its human readable form.
- /
- / In:
- / pszPrefix -> prefix string
- / lpGuid -> guid to be streamed
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- #ifdef UNICODE
- #define MAP_GUID(x) &x, TEXT(""L#x)
- #else
- #define MAP_GUID(x) &x, TEXT(""#x)
- #endif
- #define MAP_GUID2(x,y) MAP_GUID(x), MAP_GUID(y)
- const struct
- {
- const GUID* m_pGUID;
- LPCTSTR m_pName;
- }
- _guid_map[] =
- {
- MAP_GUID(IID_IUnknown),
- MAP_GUID(IID_IClassFactory),
- MAP_GUID(IID_IDropTarget),
- MAP_GUID(IID_IDataObject),
- MAP_GUID(IID_IPersist),
- MAP_GUID(IID_IOleWindow),
- MAP_GUID2(IID_INewShortcutHookA, IID_INewShortcutHookW),
- MAP_GUID(IID_IShellBrowser),
- MAP_GUID(IID_IShellView),
- MAP_GUID(IID_IContextMenu),
- MAP_GUID(IID_IShellIcon),
- MAP_GUID(IID_IShellFolder),
- MAP_GUID(IID_IShellExtInit),
- MAP_GUID(IID_IShellPropSheetExt),
- MAP_GUID(IID_IPersistFolder),
- MAP_GUID2(IID_IExtractIconA, IID_IExtractIconW),
- MAP_GUID2(IID_IShellLinkA, IID_IShellLinkW),
- MAP_GUID2(IID_IShellCopyHookA, IID_IShellCopyHookW),
- MAP_GUID2(IID_IFileViewerA, IID_IFileViewerW),
- MAP_GUID(IID_ICommDlgBrowser),
- MAP_GUID(IID_IEnumIDList),
- MAP_GUID(IID_IFileViewerSite),
- MAP_GUID(IID_IContextMenu2),
- MAP_GUID2(IID_IShellExecuteHookA, IID_IShellExecuteHookW),
- MAP_GUID(IID_IPropSheetPage),
- MAP_GUID(IID_IShellView2),
- MAP_GUID(IID_IUniformResourceLocator),
- };
- void CDebugStack::_TraceGUID(LPCTSTR pPrefix, REFGUID rGUID)
- {
- TCHAR szGUID[40];
- LPCTSTR pName = NULL;
- int i;
- for ( i = 0 ; i < ARRAYSIZE(_guid_map); i++ )
- {
- if ( IsEqualGUID(rGUID, *_guid_map[i].m_pGUID) )
- {
- pName = _guid_map[i].m_pName;
- break;
- }
- }
- if ( !pName )
- {
- // StringFromGUID2 only does UNICODE. SHStringFromGUID goes both ways,
- // but requires shlwapip.h and shlwapi.lib.
- #ifndef UNICODE
- #error "_TraceGUID needs fixing"
- #endif
- StringFromGUID2(rGUID, szGUID, ARRAYSIZE(szGUID));
- //SHStringFromGUID(rGUID, szGUID, ARRAYSIZE(szGUID));
- pName = szGUID;
- }
- _Trace(FALSE, TEXT("%s %s"), pPrefix, pName);
- }
- /*-----------------------------------------------------------------------------
- / _TraceAssert
- / -------------
- / Our assert handler, out faults it the trace mask as enabled assert
- / faulting.
- /
- / In:
- / iLine = line
- / pFilename -> filename of the file we asserted in
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void CDebugStack::_TraceAssert(int iLine, LPTSTR pFilename)
- {
- // nb: TRUE --> asserts always displayed
- _Trace(TRUE, TEXT("Assert failed in %s, line %d"), pFilename, iLine);
- if ( g_dwTraceMask & TRACE_COMMON_ASSERT )
- DebugBreak();
- }
- /*-----------------------------------------------------------------------------
- / ~CDebugStackHolder
- / ------------------
- / Free any DebugStack objects that exist
- /
- / In:
- / -
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- int CALLBACK
- _DeleteCB(LPVOID pVoid, LPVOID /*pData*/)
- {
- PDEBUGSTACK pDebugStack = (PDEBUGSTACK)pVoid;
- if (pDebugStack)
- {
- //pDebugStack->_Trace(TRUE, TEXT("~CDebugStackHolder destroying DebugStack"));
- delete pDebugStack;
- }
- return 1;
- }
- CDebugStackHolder::~CDebugStackHolder()
- {
- EnterCriticalSection(&m_csStackList);
- if (NULL != m_hDebugStackList)
- {
- DPA_DestroyCallback(m_hDebugStackList, _DeleteCB, NULL);
- m_hDebugStackList = NULL;
- }
- LeaveCriticalSection(&m_csStackList);
- DeleteCriticalSection(&m_csStackList);
- }
- /*-----------------------------------------------------------------------------
- / CDebugStackHolder::Add
- / ----------------------
- / Saves the DebugStack object in a list
- /
- / In:
- / PDEBUGSTACK pointer to the thread's debug stack object
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void
- CDebugStackHolder::Add(PDEBUGSTACK pDebugStack)
- {
- EnterCriticalSection(&m_csStackList);
- if (NULL == m_hDebugStackList)
- m_hDebugStackList = DPA_Create(4);
- if (NULL != m_hDebugStackList)
- DPA_AppendPtr(m_hDebugStackList, pDebugStack);
- LeaveCriticalSection(&m_csStackList);
- }
- /*-----------------------------------------------------------------------------
- / CDebugStackHolder::Remove
- / -------------------------
- / Removes the DebugStack object from the list
- /
- / In:
- / PDEBUGSTACK pointer to the thread's debug stack object
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void
- CDebugStackHolder::Remove(PDEBUGSTACK pDebugStack)
- {
- EnterCriticalSection(&m_csStackList);
- if (NULL != m_hDebugStackList)
- {
- int iStack = DPA_GetPtrIndex(m_hDebugStackList, pDebugStack);
- if (-1 != iStack)
- DPA_DeletePtr(m_hDebugStackList, iStack);
- }
- LeaveCriticalSection(&m_csStackList);
- }
- /*-----------------------------------------------------------------------------
- / GetThreadStack
- / --------------
- / Create (if necessary) and return the per-thread debug stack object.
- /
- / In:
- / -
- /
- / Out:
- / PDEBUGSTACK pointer to the thread's debug stack object
- /----------------------------------------------------------------------------*/
- PDEBUGSTACK GetThreadStack()
- {
- PDEBUGSTACK pDebugStack;
- if (0xffffffffL == g_tlsDebug)
- return NULL;
- pDebugStack = (PDEBUGSTACK)TlsGetValue(g_tlsDebug);
- if (!pDebugStack)
- {
- pDebugStack = new CDebugStack;
- TlsSetValue(g_tlsDebug, pDebugStack);
- if (!g_pStackHolder)
- g_pStackHolder = new CDebugStackHolder;
- if (g_pStackHolder)
- g_pStackHolder->Add(pDebugStack);
- }
- return pDebugStack;
- }
- /*-----------------------------------------------------------------------------
- / DoTraceSetMask
- / --------------
- / Adjust the trace mask to reflect the state given.
- /
- / In:
- / dwMask = mask for enabling / disable trace output
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void DoTraceSetMask(DWORD dwMask)
- {
- g_dwTraceMask = dwMask;
- }
- /*-----------------------------------------------------------------------------
- / DoTraceSetMaskFromRegKey
- / ------------------------
- / Pick up the TraceMask value from the given registry key and
- / set the trace mask using that.
- /
- / In:
- / hkRoot = handle of open key
- / pszSubKey = name of subkey to open
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void DoTraceSetMaskFromRegKey(HKEY hkRoot, LPCTSTR pszSubKey)
- {
- HKEY hKey;
- if (ERROR_SUCCESS == RegOpenKey(hkRoot, pszSubKey, &hKey))
- {
- DWORD dwTraceMask = 0;
- DWORD cbTraceMask = SIZEOF(dwTraceMask);
- RegQueryValueEx(hKey,
- TEXT("TraceMask"),
- NULL,
- NULL,
- (LPBYTE)&dwTraceMask,
- &cbTraceMask);
- DoTraceSetMask(dwTraceMask);
- RegCloseKey(hKey);
- }
- }
- /*-----------------------------------------------------------------------------
- / DoTraceSetMaskFromCLSID
- / -----------------------
- / Pick up the TraceMask value from the given CLSID value and
- / set the trace mask using that.
- /
- / In:
- / rCLSID = CLSID to query the value from
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void DoTraceSetMaskFromCLSID(REFCLSID rCLSID)
- {
- TCHAR szClsidKey[48] = TEXT("CLSID\");
- int nLength = lstrlen(szClsidKey);
- // StringFromGUID2 only does UNICODE. SHStringFromGUID goes both ways,
- // but requires shlwapip.h and shlwapi.lib.
- #ifdef UNICODE
- if (0 == StringFromGUID2(rCLSID, szClsidKey + nLength, ARRAYSIZE(szClsidKey) - nLength))
- #else
- #error "DoTraceSetMaskFromCLSID needs fixing"
- if (0 == SHStringFromGUID(rCLSID, szClsidKey + nLength, ARRAYSIZE(szClsidKey) - nLength))
- #endif
- return;
- DoTraceSetMaskFromRegKey(HKEY_CLASSES_ROOT, szClsidKey);
- }
- /*-----------------------------------------------------------------------------
- / DoTraceEnter
- / ------------
- / Set the debugging call stack up to indicate which function we are in.
- /
- / In:
- / pName -> function name to be displayed in subsequent trace output.
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void DoTraceEnter(DWORD dwMask, LPCTSTR pName)
- {
- PDEBUGSTACK pDebugStack = GetThreadStack();
- if (pDebugStack)
- pDebugStack->_TraceEnter(dwMask, pName);
- }
- /*-----------------------------------------------------------------------------
- / DoTraceLeave
- / ------------
- / On exit from a function this will adjust the function stack pointer to
- / point to our previous function. If no trace output has been made then
- / we will output the function name on a single line (to indicate we went somewhere).
- /
- / In:
- / -
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void DoTraceLeave(void)
- {
- PDEBUGSTACK pDebugStack = GetThreadStack();
- if (pDebugStack)
- pDebugStack->_TraceLeave();
- }
- /*-----------------------------------------------------------------------------
- / DoTrace
- / -------
- / Perform printf formatting to the debugging stream. We indent the output
- / and stream the function name as required to give some indication of
- / call stack depth.
- /
- / In:
- / pszFormat -> printf style formatting string
- / ... = arguments as required for the formatting
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void DoTrace(LPCTSTR pszFormat, ...)
- {
- PDEBUGSTACK pDebugStack = GetThreadStack();
- va_list va;
- if (pDebugStack)
- {
- va_start(va, pszFormat);
- pDebugStack->_vTrace(FALSE, pszFormat, va);
- va_end(va);
- }
- }
- /*-----------------------------------------------------------------------------
- / DoTraceGuid
- / -----------
- / Given a GUID output it into the debug string, first we try and map it
- / to a name (ie. IShellFolder), if that didn't work then we convert it
- / to its human readable form.
- /
- / In:
- / pszPrefix -> prefix string
- / lpGuid -> guid to be streamed
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void DoTraceGUID(LPCTSTR pPrefix, REFGUID rGUID)
- {
- PDEBUGSTACK pDebugStack = GetThreadStack();
- if (pDebugStack)
- pDebugStack->_TraceGUID(pPrefix, rGUID);
- }
- /*-----------------------------------------------------------------------------
- / DoTraceAssert
- / -------------
- / Our assert handler, out faults it the trace mask as enabled assert
- / faulting.
- /
- / In:
- / iLine = line
- / pFilename -> filename of the file we asserted in
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void DoTraceAssert(int iLine, LPTSTR pFilename)
- {
- PDEBUGSTACK pDebugStack = GetThreadStack();
- if (pDebugStack)
- pDebugStack->_TraceAssert(iLine, pFilename);
- }
- /*-----------------------------------------------------------------------------
- / DebugThreadDetach
- / DebugProcessAttach
- / DebugProcessDetach
- / -------------
- / These must be called from DllMain
- /
- / In:
- / -
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- void DebugThreadDetach(void)
- {
- PDEBUGSTACK pDebugStack;
- if (0xffffffffL == g_tlsDebug)
- return;
- pDebugStack = (PDEBUGSTACK)TlsGetValue(g_tlsDebug);
- if (pDebugStack)
- {
- if (g_pStackHolder)
- g_pStackHolder->Remove(pDebugStack);
- delete pDebugStack;
- TlsSetValue(g_tlsDebug, NULL);
- }
- }
- void DebugProcessAttach(void)
- {
- g_tlsDebug = TlsAlloc();
- }
- void DebugProcessDetach(void)
- {
- DebugThreadDetach();
- if (NULL != g_pStackHolder)
- {
- delete g_pStackHolder;
- g_pStackHolder = NULL;
- }
- if (0xffffffffL != g_tlsDebug)
- {
- TlsFree(g_tlsDebug);
- g_tlsDebug = 0xffffffffL;
- }
- }
- #endif // DEBUG
English
