|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 2002
//
// File: debug.cpp
//
//--------------------------------------------------------------------------
/*----------------------------------------------------------------------------
/ Title; / debug.cpp / / Authors; / David De Vorchik (daviddv) / / Notes; / Provides printf style debug output /----------------------------------------------------------------------------*/ #include "precomp.hxx"
#include "stdio.h"
#include "simstr.h"
#pragma hdrstop
#ifdef DEBUG
/*-----------------------------------------------------------------------------
/ Locals & helper functions /----------------------------------------------------------------------------*/
#define GETDEPTH(x) (x)=reinterpret_cast<UINT_PTR>(TlsGetValue (g_dwMargin));
#define SETDEPTH(x) TlsSetValue (g_dwMargin, reinterpret_cast<LPVOID>((x)));
DWORD g_dwMargin=0; DWORD g_dwTraceMask = 0;
#define MAX_CALL_DEPTH 64
#define BUFFER_SIZE 4096
/*-----------------------------------------------------------------------------
/ _indent / ------- / Output to the debug stream indented by n columns. / / In: / i = column to indent to. / pString -> string to be indented / / Out: / - /----------------------------------------------------------------------------*/
void _indent(UINT_PTR i, const CSimpleString& String) { CSimpleString strIndentBuffer; strIndentBuffer.Format(TEXT("%08x "), GetCurrentThreadId());
for ( ; i > 0 ; i-- ) { strIndentBuffer.Concat(TEXT(" ")); }
strIndentBuffer.Concat(String); strIndentBuffer.Concat(TEXT("\n"));
OutputDebugString(strIndentBuffer.String()); }
/*-----------------------------------------------------------------------------
/ 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; }
/*-----------------------------------------------------------------------------
/ DoTraceEnter / ------------ / Display the name of the function we are in. / / In: / pName -> function name to be displayed in subsequent trace output. / / Out: / - /----------------------------------------------------------------------------*/ void DoTraceEnter(DWORD dwMask, LPCTSTR pName) { UINT_PTR uDepth=0; CSimpleString str; GETDEPTH(uDepth); uDepth++; SETDEPTH(uDepth);
if ( !pName ) pName = TEXT("<no name>"); // no function name given
str.Format(TEXT("ENTER: %s"), pName); _indent (uDepth, str); }
/*-----------------------------------------------------------------------------
/ DoTraceLeave / ------------ / On exit from a function, decrement the margin / / In: / - / Out: / - /----------------------------------------------------------------------------*/ void DoTraceLeave(void) { UINT_PTR uDepth; GETDEPTH (uDepth); uDepth--; SETDEPTH(uDepth); }
/*-----------------------------------------------------------------------------
/ 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: / pFormat -> printf style formatting string / ... = arguments as required for the formatting / / Out: / - /----------------------------------------------------------------------------*/ void DoTrace(LPCTSTR pFormat, ...) { va_list va; TCHAR szTraceBuffer[BUFFER_SIZE] = {0}; UINT_PTR uDepth; GETDEPTH(uDepth); if ( uDepth < MAX_CALL_DEPTH ) { va_start(va, pFormat); wvnsprintf(szTraceBuffer, ARRAYSIZE(szTraceBuffer)-1, pFormat, va); va_end(va);
_indent(uDepth+1, CSimpleString(szTraceBuffer)); } }
/*-----------------------------------------------------------------------------
/ 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: / - /----------------------------------------------------------------------------*/ #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_IPersistStream), MAP_GUID(IID_IPersistFolder), MAP_GUID(IID_IPersistFolder2), MAP_GUID(IID_IPersistFile), 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_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), MAP_GUID(IID_IShellDetails), MAP_GUID(IID_IShellExtInit), MAP_GUID(IID_IShellPropSheetExt), MAP_GUID(IID_IShellIconOverlay), MAP_GUID(IID_IExtractImage), MAP_GUID(IID_IExtractImage2), MAP_GUID(IID_IQueryInfo), MAP_GUID(IID_IShellDetails3), MAP_GUID(IID_IShellView2), MAP_GUID(IID_IShellFolder2), MAP_GUID(IID_IShellIconOverlay), MAP_GUID(IID_IMoniker), MAP_GUID(IID_IStream), MAP_GUID(IID_ISequentialStream), MAP_GUID(IID_IPersistFreeThreadedObject), };
void DoTraceGUID(LPCTSTR pPrefix, REFGUID rGUID) { TCHAR szGUID[GUIDSTR_MAX]; CSimpleString strBuffer; LPCTSTR pName = NULL; size_t i; UINT_PTR uDepth; GETDEPTH(uDepth); if ( uDepth < MAX_CALL_DEPTH ) { 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 ) { SHStringFromGUID(rGUID, szGUID, ARRAYSIZE(szGUID)); pName = szGUID; }
strBuffer.Format(TEXT("%s %s"), pPrefix, pName); _indent(uDepth+1, strBuffer); } }
/*-----------------------------------------------------------------------------
/ DoTraceViewMsg / -------------- / Given a view msg (SFVM_ && DVM_), print out the corresponding text... / / In: / uMsg -> msg to be streamed / wParam -> wParam value for message / lParam -> lParam value for message / / Out: / - /----------------------------------------------------------------------------*/ #ifdef UNICODE
#define MAP_MSG(x) x, TEXT(""L#x)
#else
#define MAP_MSG(x) x, TEXT(""#x)
#endif
const struct { UINT m_uMsg; LPCTSTR m_pName; } _view_msg_map[] = { MAP_MSG(SFVM_MERGEMENU), MAP_MSG(SFVM_INVOKECOMMAND), MAP_MSG(SFVM_GETHELPTEXT), MAP_MSG(SFVM_GETTOOLTIPTEXT), MAP_MSG(SFVM_GETBUTTONINFO), MAP_MSG(SFVM_GETBUTTONS), MAP_MSG(SFVM_INITMENUPOPUP), MAP_MSG(SFVM_SELCHANGE), MAP_MSG(SFVM_DRAWITEM), MAP_MSG(SFVM_MEASUREITEM), MAP_MSG(SFVM_EXITMENULOOP), MAP_MSG(SFVM_PRERELEASE), MAP_MSG(SFVM_GETCCHMAX), MAP_MSG(SFVM_FSNOTIFY), MAP_MSG(SFVM_WINDOWCREATED), MAP_MSG(SFVM_WINDOWDESTROY), MAP_MSG(SFVM_REFRESH), MAP_MSG(SFVM_SETFOCUS), MAP_MSG(SFVM_QUERYCOPYHOOK), MAP_MSG(SFVM_NOTIFYCOPYHOOK), MAP_MSG(SFVM_GETDETAILSOF), MAP_MSG(SFVM_COLUMNCLICK), MAP_MSG(SFVM_QUERYFSNOTIFY), MAP_MSG(SFVM_DEFITEMCOUNT), MAP_MSG(SFVM_DEFVIEWMODE), MAP_MSG(SFVM_UNMERGEMENU), MAP_MSG(SFVM_INSERTITEM), MAP_MSG(SFVM_DELETEITEM), MAP_MSG(SFVM_UPDATESTATUSBAR), MAP_MSG(SFVM_BACKGROUNDENUM), MAP_MSG(SFVM_GETWORKINGDIR), MAP_MSG(SFVM_GETCOLSAVESTREAM), MAP_MSG(SFVM_SELECTALL), MAP_MSG(SFVM_DIDDRAGDROP), MAP_MSG(SFVM_SUPPORTSIDENTITY), MAP_MSG(SFVM_FOLDERISPARENT), MAP_MSG(SFVM_SETISFV), MAP_MSG(SFVM_GETVIEWS), MAP_MSG(SFVM_THISIDLIST), MAP_MSG(SFVM_GETITEMIDLIST), MAP_MSG(SFVM_SETITEMIDLIST), MAP_MSG(SFVM_INDEXOFITEMIDLIST), MAP_MSG(SFVM_ODFINDITEM), MAP_MSG(SFVM_HWNDMAIN), MAP_MSG(SFVM_ADDPROPERTYPAGES), MAP_MSG(SFVM_BACKGROUNDENUMDONE), MAP_MSG(SFVM_GETNOTIFY), MAP_MSG(SFVM_ARRANGE), MAP_MSG(SFVM_QUERYSTANDARDVIEWS), MAP_MSG(SFVM_QUERYREUSEEXTVIEW), MAP_MSG(SFVM_GETSORTDEFAULTS), MAP_MSG(SFVM_GETEMPTYTEXT), MAP_MSG(SFVM_GETITEMICONINDEX), MAP_MSG(SFVM_DONTCUSTOMIZE), MAP_MSG(SFVM_SIZE), MAP_MSG(SFVM_GETZONE), MAP_MSG(SFVM_GETPANE), MAP_MSG(SFVM_ISOWNERDATA), MAP_MSG(SFVM_GETODRANGEOBJECT), MAP_MSG(SFVM_ODCACHEHINT), MAP_MSG(SFVM_GETHELPTOPIC), MAP_MSG(SFVM_OVERRIDEITEMCOUNT), MAP_MSG(SFVM_GETHELPTEXTW), MAP_MSG(SFVM_GETTOOLTIPTEXTW), MAP_MSG(SFVM_GETIPERSISTHISTORY), MAP_MSG(SFVM_GETANIMATION),
};
const struct { UINT m_uMsg; LPCTSTR m_pName; } _shcn_msg_map[] = { MAP_MSG(SHCNE_RENAMEITEM), MAP_MSG(SHCNE_CREATE), MAP_MSG(SHCNE_DELETE), MAP_MSG(SHCNE_MKDIR), MAP_MSG(SHCNE_RMDIR), MAP_MSG(SHCNE_MEDIAINSERTED), MAP_MSG(SHCNE_MEDIAREMOVED), MAP_MSG(SHCNE_DRIVEREMOVED), MAP_MSG(SHCNE_DRIVEADD), MAP_MSG(SHCNE_NETSHARE), MAP_MSG(SHCNE_NETUNSHARE), MAP_MSG(SHCNE_ATTRIBUTES), MAP_MSG(SHCNE_UPDATEDIR), MAP_MSG(SHCNE_UPDATEITEM), MAP_MSG(SHCNE_SERVERDISCONNECT), MAP_MSG(SHCNE_UPDATEIMAGE), MAP_MSG(SHCNE_DRIVEADDGUI), MAP_MSG(SHCNE_RENAMEFOLDER), MAP_MSG(SHCNE_FREESPACE), };
void DoTraceViewMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) { LPCTSTR pName = NULL; CSimpleString strBuffer; CSimpleString strTmp; size_t i; UINT_PTR uDepth; GETDEPTH(uDepth); if ( uDepth < MAX_CALL_DEPTH ) { for ( i = 0 ; i < ARRAYSIZE(_view_msg_map); i++ ) { if ( _view_msg_map[i].m_uMsg == uMsg ) { pName = _view_msg_map[i].m_pName; break; } }
if (!pName) { strTmp.Format(TEXT("SFVM_(%d)"), uMsg ); pName = strTmp.String(); }
if (uMsg == SFVM_FSNOTIFY) { LPCTSTR pEvent = NULL;
for (i= 0; i < ARRAYSIZE(_shcn_msg_map); i++) { if ( _shcn_msg_map[i].m_uMsg == uMsg ) { pEvent = _shcn_msg_map[i].m_pName; break; } }
if (!pEvent) { pEvent = TEXT("Unknown"); }
strBuffer.Format(TEXT("%s w(%08X) l(%08X == %s)"), pName, wParam, lParam, pEvent); _indent(uDepth+1, strBuffer);
} else { strBuffer.Format(TEXT("%s w(%08X) l(%08X)"), pName, wParam, lParam); _indent(uDepth+1, strBuffer); } } }
const struct { UINT m_uMsg; LPCTSTR m_pName; } _menu_msg_map[] = { MAP_MSG(DFM_MERGECONTEXTMENU), MAP_MSG(DFM_INVOKECOMMAND), MAP_MSG(DFM_ADDREF), MAP_MSG(DFM_RELEASE), MAP_MSG(DFM_GETHELPTEXT), MAP_MSG(DFM_WM_MEASUREITEM), MAP_MSG(DFM_WM_DRAWITEM), MAP_MSG(DFM_WM_INITMENUPOPUP), MAP_MSG(DFM_VALIDATECMD), MAP_MSG(DFM_MERGECONTEXTMENU_TOP), MAP_MSG(DFM_GETHELPTEXTW), MAP_MSG(DFM_INVOKECOMMANDEX), MAP_MSG(DFM_MAPCOMMANDNAME), MAP_MSG(DFM_GETDEFSTATICID), MAP_MSG(DFM_GETVERBW),
};
const struct { WPARAM m_uMsg; LPCTSTR m_pName; } _menu_invk_cmd_msg_map[] = { MAP_MSG(DFM_CMD_RENAME), MAP_MSG(DFM_CMD_MODALPROP), MAP_MSG(DFM_CMD_PASTESPECIAL), MAP_MSG(DFM_CMD_PASTELINK), MAP_MSG(DFM_CMD_VIEWDETAILS), MAP_MSG(DFM_CMD_VIEWLIST), MAP_MSG(DFM_CMD_PASTE), MAP_MSG(DFM_CMD_NEWFOLDER), MAP_MSG(DFM_CMD_PROPERTIES), MAP_MSG(DFM_CMD_LINK), MAP_MSG(DFM_CMD_COPY), MAP_MSG(DFM_CMD_MOVE), MAP_MSG(DFM_CMD_DELETE),
};
void DoTraceMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) { LPCTSTR pName = NULL; CSimpleString strBuffer; CSimpleString strTmp; size_t i; UINT_PTR uDepth; GETDEPTH (uDepth); if ( uDepth < MAX_CALL_DEPTH ) { for ( i = 0 ; i < ARRAYSIZE(_menu_msg_map); i++ ) { if ( _menu_msg_map[i].m_uMsg == uMsg ) { pName = _menu_msg_map[i].m_pName; break; } }
if (!pName) { strTmp.Format(TEXT("DFM_(%d)"), uMsg ); pName = strTmp.String(); }
if ((uMsg == DFM_INVOKECOMMAND) && (wParam >= DFM_CMD_RENAME)) { strBuffer.Format(TEXT("%s w(%s) l(%08X)"), pName, _menu_invk_cmd_msg_map[wParam-DFM_CMD_RENAME].m_pName, lParam); } else { strBuffer.Format(TEXT("%s w(%08X) l(%08X)"), pName, wParam, lParam); } _indent(uDepth+1, strBuffer); } }
/*-----------------------------------------------------------------------------
/ 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, LPCTSTR pFilename) { CSimpleString strBuffer; UINT_PTR uDepth; GETDEPTH(uDepth);
strBuffer.Format(TEXT("Assert failed in %s, line %d"), pFilename, iLine);
_indent(uDepth+1, strBuffer);
if ( g_dwTraceMask & TRACE_COMMON_ASSERT ) DebugBreak(); }
#endif
|