/*++ 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 << ""; } 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 << ""; } } 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