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.
542 lines
9.8 KiB
542 lines
9.8 KiB
/*++
|
|
|
|
Copyright (c) 1994-1999 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
debugafx.cpp
|
|
|
|
Abstract:
|
|
|
|
Debugging routines using AFX/MFC extensions
|
|
|
|
Author:
|
|
|
|
Ronald Meijer (ronaldm)
|
|
|
|
Project:
|
|
|
|
Internet Services Manager
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
|
|
//
|
|
// Include Files
|
|
//
|
|
#include "stdafx.h"
|
|
#include "common.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
|
|
|
|
#if defined(_DEBUG) || DBG
|
|
|
|
|
|
|
|
int
|
|
IISUIFireAssert(
|
|
const char * filename,
|
|
const char * timestamp,
|
|
int linenum,
|
|
const char * expr
|
|
)
|
|
{
|
|
char sz[4096];
|
|
char * pch = sz;
|
|
|
|
pch += wsprintfA(pch,
|
|
"-------------------------------------------------------------------------------\n"
|
|
"ASSERT FAILURE!\n"
|
|
"-------------------------------------------------------------------------------\n"
|
|
"File:\t\t%s\n"
|
|
"Line:\t\t%u\n"
|
|
"Time Stamp:\t%s\n"
|
|
"-------------------------------------------------------------------------------\n",
|
|
filename, linenum, timestamp
|
|
);
|
|
|
|
if (expr)
|
|
{
|
|
wsprintfA(pch, "Expression:\t%s\n"
|
|
"-------------------------------------------------------------------------------\n",
|
|
expr
|
|
);
|
|
}
|
|
|
|
TRACEEOL(sz);
|
|
|
|
int nReturn = MessageBoxA(
|
|
NULL,
|
|
sz,
|
|
"ASSERT FAILURE!",
|
|
MB_ABORTRETRYIGNORE | MB_DEFBUTTON1 | MB_ICONHAND
|
|
);
|
|
|
|
if (nReturn == IDABORT)
|
|
{
|
|
exit(-1);
|
|
}
|
|
|
|
//
|
|
// Return 1 to break, 0 to ignore
|
|
//
|
|
return (nReturn == IDRETRY);
|
|
}
|
|
|
|
|
|
|
|
#endif // _DEBUG || DBG
|
|
|
|
|
|
|
|
#if defined(_DEBUG) || DBG
|
|
|
|
|
|
|
|
#ifndef _DEBUG
|
|
//
|
|
// SDK build links with retail MFC. Swiped code from MFC sources. Some
|
|
// modifications.
|
|
//
|
|
COMDLL CDumpContext afxDump;
|
|
COMDLL BOOL afxTraceEnabled = TRUE;
|
|
|
|
void
|
|
CDumpContext::OutputString(LPCTSTR lpsz)
|
|
{
|
|
if (m_pFile == NULL)
|
|
{
|
|
OutputDebugString(lpsz);
|
|
return;
|
|
}
|
|
|
|
m_pFile->Write(lpsz, lstrlen(lpsz)*sizeof(TCHAR));
|
|
}
|
|
|
|
CDumpContext::CDumpContext(CFile * pFile)
|
|
{
|
|
if (pFile)
|
|
{
|
|
ASSERT_PTR(pFile);
|
|
}
|
|
|
|
m_pFile = pFile;
|
|
m_nDepth = 0;
|
|
}
|
|
|
|
void
|
|
CDumpContext::Flush()
|
|
{
|
|
if (m_pFile)
|
|
{
|
|
m_pFile->Flush();
|
|
}
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(LPCTSTR lpsz)
|
|
{
|
|
if (lpsz == NULL)
|
|
{
|
|
OutputString(_T("(NULL)"));
|
|
return *this;
|
|
}
|
|
|
|
if (m_pFile == NULL)
|
|
{
|
|
TCHAR szBuffer[512];
|
|
LPTSTR lpBuf = szBuffer;
|
|
|
|
while (*lpsz != '\0')
|
|
{
|
|
if (lpBuf > szBuffer + ARRAY_SIZE(szBuffer) - 3)
|
|
{
|
|
*lpBuf = '\0';
|
|
OutputString(szBuffer);
|
|
lpBuf = szBuffer;
|
|
}
|
|
|
|
if (*lpsz == '\n')
|
|
{
|
|
*lpBuf++ = '\r';
|
|
}
|
|
|
|
*lpBuf++ = *lpsz++;
|
|
}
|
|
|
|
*lpBuf = '\0';
|
|
OutputString(szBuffer);
|
|
return *this;
|
|
}
|
|
|
|
m_pFile->Write(lpsz, lstrlen(lpsz) * sizeof(TCHAR));
|
|
return *this;
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(BYTE by)
|
|
{
|
|
TCHAR szBuffer[32];
|
|
|
|
wsprintf(szBuffer, _T("%d"), (int)by);
|
|
OutputString(szBuffer);
|
|
|
|
return *this;
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(WORD w)
|
|
{
|
|
TCHAR szBuffer[32];
|
|
|
|
wsprintf(szBuffer, _T("%u"), (UINT) w);
|
|
OutputString(szBuffer);
|
|
|
|
return *this;
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(UINT u)
|
|
{
|
|
TCHAR szBuffer[32];
|
|
|
|
wsprintf(szBuffer, _T("0x%X"), u);
|
|
OutputString(szBuffer);
|
|
|
|
return *this;
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(LONG l)
|
|
{
|
|
TCHAR szBuffer[32];
|
|
|
|
wsprintf(szBuffer, _T("%ld"), l);
|
|
OutputString(szBuffer);
|
|
|
|
return *this;
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(DWORD dw)
|
|
{
|
|
TCHAR szBuffer[32];
|
|
|
|
wsprintf(szBuffer, _T("%lu"), dw);
|
|
OutputString(szBuffer);
|
|
|
|
return *this;
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(int n)
|
|
{
|
|
TCHAR szBuffer[32];
|
|
|
|
wsprintf(szBuffer, _T("%d"), n);
|
|
OutputString(szBuffer);
|
|
|
|
return *this;
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(const CObject * pOb)
|
|
{
|
|
if (pOb == NULL)
|
|
{
|
|
*this << _T("NULL");
|
|
}
|
|
else
|
|
{
|
|
pOb->Dump(*this);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(const CObject & ob)
|
|
{
|
|
return *this << &ob;
|
|
}
|
|
|
|
CDumpContext& CDumpContext::operator<<(const void * lp)
|
|
{
|
|
TCHAR szBuffer[32];
|
|
|
|
wsprintf(szBuffer, _T("$%p"), lp);
|
|
OutputString(szBuffer);
|
|
|
|
return *this;
|
|
}
|
|
|
|
void
|
|
CDumpContext::HexDump(
|
|
LPCTSTR lpszLine,
|
|
BYTE * pby,
|
|
int nBytes,
|
|
int nWidth
|
|
)
|
|
{
|
|
ASSERT(nBytes > 0);
|
|
ASSERT(nWidth > 0);
|
|
ASSERT(AfxIsValidString(lpszLine));
|
|
ASSERT(AfxIsValidAddress(pby, nBytes, FALSE));
|
|
|
|
int nRow = 0;
|
|
TCHAR szBuffer[32];
|
|
|
|
while (nBytes--)
|
|
{
|
|
if (nRow == 0)
|
|
{
|
|
wsprintf(szBuffer, lpszLine, pby);
|
|
*this << szBuffer;
|
|
}
|
|
|
|
wsprintf(szBuffer, _T(" %02X"), *pby++);
|
|
*this << szBuffer;
|
|
|
|
if (++nRow >= nWidth)
|
|
{
|
|
*this << _T("\n");
|
|
nRow = 0;
|
|
}
|
|
}
|
|
|
|
if (nRow != 0)
|
|
{
|
|
*this << _T("\n");
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef _UNICODE
|
|
|
|
CDumpContext & CDumpContext::operator<<(LPCSTR lpsz)
|
|
{
|
|
if (lpsz == NULL)
|
|
{
|
|
OutputString(L"(NULL)");
|
|
return *this;
|
|
}
|
|
|
|
TCHAR szBuffer[512];
|
|
_mbstowcsz(szBuffer, lpsz, ARRAY_SIZE(szBuffer));
|
|
return *this << szBuffer;
|
|
}
|
|
|
|
#else //_UNICODE
|
|
|
|
CDumpContext& CDumpContext::operator<<(LPCWSTR lpsz)
|
|
{
|
|
if (lpsz == NULL)
|
|
{
|
|
OutputString("(NULL)");
|
|
return *this;
|
|
}
|
|
|
|
char szBuffer[512];
|
|
_wcstombsz(szBuffer, lpsz, ARRAY_SIZE(szBuffer));
|
|
return *this << szBuffer;
|
|
}
|
|
|
|
#endif //!_UNICODE
|
|
|
|
//
|
|
// End of block of code copied from MFC
|
|
//
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
LPCSTR
|
|
DbgFmtPgm(
|
|
IN LPCSTR szFn,
|
|
IN int line
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Format debugging string containing file name and line number. Remove
|
|
the path portion of the file name if present.
|
|
|
|
Arguments:
|
|
|
|
LPCSTR szFn : File name (ANSI)
|
|
int line : Line number
|
|
|
|
Return Value:
|
|
|
|
Pointer to the internal buffer
|
|
|
|
--*/
|
|
{
|
|
LPCSTR pszTail = szFn + lstrlenA(szFn);
|
|
static CHAR szBuff[MAX_PATH + 1];
|
|
|
|
for ( /**/; pszTail > szFn; --pszTail)
|
|
{
|
|
if (*pszTail == '\\' || *pszTail == ':')
|
|
{
|
|
++pszTail;
|
|
break;
|
|
}
|
|
}
|
|
|
|
wsprintfA(szBuff, "[%s:%d] ", pszTail, line);
|
|
|
|
return szBuff;
|
|
}
|
|
|
|
|
|
|
|
CDumpContext &
|
|
operator <<(
|
|
IN OUT CDumpContext & out,
|
|
IN ENUM_DEBUG_AFX edAfx
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Output debugging control character to the debug context
|
|
|
|
Arguments:
|
|
|
|
CDumpContext & out : Output debugging context
|
|
edAfx : Control character
|
|
|
|
Return Value:
|
|
|
|
Output debugging context reference
|
|
|
|
--*/
|
|
{
|
|
static CHAR * szEol = "\r\n";
|
|
|
|
switch (edAfx)
|
|
{
|
|
case EDBUG_AFX_EOL:
|
|
out << szEol;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
|
|
|
|
#ifndef UNICODE
|
|
|
|
|
|
|
|
CDumpContext &
|
|
operator <<(
|
|
IN OUT CDumpContext & out,
|
|
IN LPCWSTR pwchStr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Insert a wide-character string into the output stream. For non-UNICODE only,
|
|
as this functions would be handled by the generic 'T' function otherwise.
|
|
|
|
Arguments:
|
|
|
|
CDumpContext & out : Output debugging context
|
|
pwchStr : Wide character string
|
|
|
|
Return Value:
|
|
|
|
Output debugging context reference
|
|
|
|
--*/
|
|
{
|
|
size_t cwch ;
|
|
|
|
if (pwchStr == NULL)
|
|
{
|
|
out << "<null>";
|
|
}
|
|
else if ((cwch = ::wcslen(pwchStr )) > 0)
|
|
{
|
|
CHAR * pszTemp = (LPSTR)AllocMem(cwch + 2);
|
|
|
|
if (pszTemp != NULL)
|
|
{
|
|
for (int i = 0; pwchStr[i]; ++i)
|
|
{
|
|
pszTemp[i] = (CHAR)pwchStr[i];
|
|
}
|
|
|
|
pszTemp[i] = 0;
|
|
out << pszTemp;
|
|
FreeMem(pszTemp);
|
|
}
|
|
else
|
|
{
|
|
out << "<memerr>";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
out << "\"\"";
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
|
|
|
|
#endif // UNICODE
|
|
|
|
|
|
|
|
CDumpContext &
|
|
operator <<(
|
|
IN CDumpContext & out,
|
|
IN const GUID & guid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a GUID to the debugger
|
|
|
|
Arguments:
|
|
|
|
CDumpContext & out : Output debugging context
|
|
GUID & guid : GUID
|
|
|
|
Return Value:
|
|
|
|
Output debugging context reference
|
|
|
|
--*/
|
|
{
|
|
out << "{ "
|
|
<< guid.Data1
|
|
<< ","
|
|
<< guid.Data2
|
|
<< ","
|
|
<< guid.Data3
|
|
<< ","
|
|
<< guid.Data4
|
|
<< "}";
|
|
|
|
return out;
|
|
}
|
|
|
|
|
|
#endif // _DEBUG
|