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.
274 lines
6.9 KiB
274 lines
6.9 KiB
/*----------------------------------------------------------------------------
|
|
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
|