|
|
/*----------------------------------------------------------------------------
dbgtrace.c Debug trace functions.
Copyright (C) Microsoft Corporation, 1993 - 1999 All rights reserved.
Authors: suryanr Suryanarayanan Raman GaryBu Gary S. Burd
History: 05/11/93 suryanr Created 06/18/93 GaryBu Convert to C. 07/21/93 KennT Code Reorg 07/26/94 SilvanaR Trace Buffer 27 oct 95 garykac DBCS_FILE_CHECK debug file: BEGIN_STRING_OK ----------------------------------------------------------------------------*/ #include "stdafx.h"
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <stdarg.h>
#include <tchar.h>
#include "dbgutil.h"
#include "tfschar.h"
#include "atlconv.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
#if 0
DBG_API(BOOL) FDbgFalse(void) { return FALSE; } #endif
#ifdef DEBUG
/*!--------------------------------------------------------------------------
DbgFmtPgm builds a string with the filename and line number Author: EricDav ---------------------------------------------------------------------------*/ DBG_APIV(LPCTSTR) DbgFmtFileLine ( const char * szFn, int line ) { USES_CONVERSION; const TCHAR * ptszFn = A2CT(szFn); const TCHAR * pszTail = ptszFn + ::_tcslen( ptszFn ); static TCHAR szBuff [100];
for ( ; pszTail > ptszFn ; pszTail-- ) { if ( *pszTail == '\\' || *pszTail == ':' ) { pszTail++; break; } }
::wsprintf( szBuff, _T("[%s:%d] "), pszTail, line );
return szBuff; }
/*!--------------------------------------------------------------------------
DbgTrace Trace string with args. Author: suryanr ---------------------------------------------------------------------------*/ DBG_APIV(void) DbgTrace(LPCTSTR szFileLine, LPTSTR szFormat, ...) { TCHAR szBuffer[1024]; va_list args; va_start(args, szFormat); wvsprintf(szBuffer, szFormat, args);
OutputDebugString(szFileLine); OutputDebugString(szBuffer); va_end(args); }
#define MAX_ASSERT_INFO 32
#define MAX_ASSERT_FILE_LEN 64
struct ASSERT_INFO { char szFile[MAX_ASSERT_FILE_LEN]; int iLine; }; static ASSERT_INFO s_rgAssertInfo[MAX_ASSERT_INFO] = {0}; static int s_iAssertInfo = 0;
/*!--------------------------------------------------------------------------
DbgAssert Display assert dialog. Author: GaryBu, kennt ---------------------------------------------------------------------------*/ DBG_APIV(void) DbgAssert(LPCSTR szFile, int iLine, LPCTSTR szFmt, ...) { va_list arg; TCHAR sz[1024]; int iloc; int ival; TCHAR *pch = sz; TCHAR *pchHead; static BOOL s_fInDbgAssert = FALSE; BOOL fQuit; MSG msgT;
// -- begin Ctrl-Ignore support ---------------------------------------
// check if this assert is disabled (user has hit Ctrl-Ignore on this
// assert this session).
for (int i = s_iAssertInfo; i--;) if (lstrcmpA(szFile, s_rgAssertInfo[i].szFile) == 0 && iLine == s_rgAssertInfo[i].iLine) // this assert is disabled
return; // -- end Ctrl-Ignore support -----------------------------------------
DBG_STRING(szTitle, "NT Networking Snapin Assert") DBG_STRING(szFileLineFmt, "%S @ line %d\n\n")
pch += wsprintf(pch, (LPCTSTR)szFileLineFmt, szFile, iLine); pchHead = pch;
// Add location to the output.
if (szFmt) { *pch++ = '"';
va_start(arg, szFmt); pch += wvsprintf(pch, szFmt, arg); va_end(arg); // Remove trailing newlines...
while (*(pch-1) == '\n') --pch;
*pch++ = '"'; *pch++ = '\n'; } else *pch++ = ' ';
if (s_fInDbgAssert) { *pch = 0; Trace1("Arrgg! Recursive assert: %s", (LPTSTR) sz);
MessageBeep(0);MessageBeep(0); return; }
s_fInDbgAssert = TRUE;
*pch++ = '\n'; *pch = 0;
Trace2("%s: %s", (LPTSTR) szTitle, (LPTSTR) sz);
repost_assert: // Is there a WM_QUIT message in the queue, if so remove it.
#define WM_QUIT 0x0012
fQuit = ::PeekMessage(&msgT, NULL, WM_QUIT, WM_QUIT, PM_REMOVE); ival = MessageBox(NULL, sz, szTitle, MB_TASKMODAL|MB_ICONHAND|MB_ABORTRETRYIGNORE|MB_DEFBUTTON3); // If there was a quit message, add it back into the queue
if (fQuit) ::PostQuitMessage((int)msgT.wParam); switch (ival) { case 0: Trace0("Failed to create message box on assert.\n"); // Fallthrough
case IDRETRY: // Hard break to cause just-in-time to fire (DbgStop doesn't)
s_fInDbgAssert = FALSE; DebugBreak(); return; case IDIGNORE: // -- begin Shift-Ignore support ------------------------------
// use Shift-Ignore to copy assert text to clipboard.
if ((GetKeyState(VK_SHIFT) & 0x8000) != 0) { if (OpenClipboard(0)) { HGLOBAL hData; LPTSTR lpstr;
hData = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, (lstrlen(sz)+1)*sizeof(TCHAR)); if (hData) { lpstr = (LPTSTR)GlobalLock(hData); if (lpstr) { lstrcpy(lpstr, sz); GlobalUnlock(hData); EmptyClipboard(); // Windows takes ownership of hData
SetClipboardData(CF_TEXT, hData); } else { GlobalFree(hData); MessageBox(NULL, _T("Error locking memory handle."), szTitle, MB_OK); } } else MessageBox(NULL, _T("Not enough memory."), szTitle, MB_OK); CloseClipboard(); } else MessageBox(NULL, _T("Cannot access clipboard."), szTitle, MB_OK); goto repost_assert; } // -- end Shift-Ignore support --------------------------------
// -- begin Ctrl-Ignore support -------------------------------
// check if user hit Ctrl-Ignore to disable this assert for the
// rest of this session.
if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) if (s_iAssertInfo < MAX_ASSERT_INFO) { // add this assert to list of asserts to disable
s_rgAssertInfo[s_iAssertInfo].iLine = iLine; lstrcpynA(s_rgAssertInfo[s_iAssertInfo].szFile, szFile, MAX_ASSERT_FILE_LEN); s_rgAssertInfo[s_iAssertInfo].szFile[MAX_ASSERT_FILE_LEN-1] = 0; s_iAssertInfo++; } else { // max asserts disabled already, warn user
MessageBox(NULL, _T("Cannot disable that assert; ") _T("already disabled max number of asserts (32)."), szTitle, MB_OK); } // -- end Ctrl-Ignore support ---------------------------------
s_fInDbgAssert = FALSE; return; case IDABORT: ExitProcess(1); break; }
Trace1("Panic! Dropping out of DbgAssert: %s", (LPSTR) sz); s_fInDbgAssert = FALSE; // A generic way of bringing up the debugger
DebugBreak(); }
DBG_API(HRESULT) HrReportExit(HRESULT hr, LPCTSTR szName) { if (!FHrOK(hr)) { Trace2("%s returned 0x%08lx\n", szName, hr); } return hr; }
#endif
|