Click here to Skip to main content
15,881,455 members
Articles / Desktop Programming / MFC

The Ultimate Toolbox - Updates and User Contributions

Rate me:
Please Sign up or sign in to vote.
4.79/5 (26 votes)
12 Feb 2013CPOL8 min read 254.5K   23.7K   170  
Updates and User Contributions for the Ultimate Toolbox Libraries
// ==========================================================================
// 						Class Implementation : COXAdvancedAssert
// ==========================================================================

// Source file OXAdvancedAssert.cpp

// Version: 9.3

// This software along with its related components, documentation and files ("The Libraries")
// is � 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement").  Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office.  For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.  

#include "stdafx.h"

#ifndef __AdvancedAssert_h__
#error In order to use Advanced Asserts "OXAdvancedAssert.h" must be included in stdafx.h
#endif

#include "OXAdvancedAssertMail.h"  // SendMail()

#include "UTBStrOp.h"
#include "UTB64Bit.h"


#ifdef AFX_DBG1_SEG
#pragma code_seg(AFX_DBG1_SEG)
#endif

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__ ;
#endif

#ifndef szNULL
#define szNULL _T("")
#endif // szNULL

#ifndef szCRLF
#define szCRLF _T("\r\n")
#endif // szCRLF

#ifdef _UNICODE
#define _tcstombsz     wcstombsz
#else
#define _tcstombsz     strncpy
#endif

#include "UTBStrOp.h"

// v9.3 - update 04 fixes for ASSERT in unicode builds- AAW 2009-03-29
// Determine number of elements in an array (not bytes)
#ifndef _countof
#define _countof(array) (sizeof(array)/sizeof(array[0]))
#endif // _countof
// END AAW

/////////////////////////////////////////////////////////////////////////////
// Advanced Assert Send state

static BOOL    g_bEnableAssertSend  = TRUE ;
static char    g_szEmailAddress[128] = BETA_EMAIL_ADDRESS ;  // Must not be a Unicode string. 

static CString g_csAssertNote1= OX_ADVANCEDASSERT_NOTE1;
static CString g_csAssertNote2= OX_ADVANCEDASSERT_NOTE2;



BOOL AppGetAssertSendState()
{
	return g_bEnableAssertSend ;
}

BOOL AppSetAssertSendState(BOOL bEnable/*=TRUE*/)
{
	BOOL bOldState = g_bEnableAssertSend ;
	g_bEnableAssertSend = bEnable ;
	return bOldState ;
}

LPCSTR AppGetAssertEmailAddress()
{
	return g_szEmailAddress ;
}

CString AppSetAssertEmailAddress(CString csEmailAddress)
{
	CString csOldEmailAddress ( g_szEmailAddress ) ;
	// v9.3 - update 04 fixes for ASSERT in unicode builds- AAW 2009-03-29
#ifdef  _UNICODE
		::WideCharToMultiByte(CP_ACP, 0, csEmailAddress,csEmailAddress.GetLength()+1, g_szEmailAddress, 128, NULL, NULL);
#else
	UTBStr::strncpy(g_szEmailAddress, _countof(g_szEmailAddress), csEmailAddress, __min(csEmailAddress.GetLength()+1, _countof(g_szEmailAddress)) ) ;
#endif
	// END AAW
	return csOldEmailAddress ;
}

CString AppGetAssertNote1()
{
	return g_csAssertNote1 ;
}

CString AppSetAssertNote1(CString csNote)
{
	CString csOldNote ( g_csAssertNote1 ) ;
	g_csAssertNote1 = csNote ;
	return csOldNote ;
}

CString AppGetAssertNote2()
{
	return g_csAssertNote2 ;
}

CString AppSetAssertNote2(CString csNote)
{
	CString csOldNote ( g_csAssertNote2 ) ;
	g_csAssertNote2 = csNote ;
	return csOldNote ;
}

// If this is not a debug or a beta version, then don't use any of this code. 
#if defined(_DEBUG) || defined(BETA)   // entire file

/////////////////////////////////////////////////////////////////////////////
// Advanced Assert dialog

#define IDD_ADVANCED_ASSERTS 100
#define IDC_MESSAGE          101
#define IDC_SEND             102
#define IDC_NOTE1            103
#define IDC_NOTE2            104



#ifndef _WIN32
typedef char wchar_t ;
#endif

#pragma pack(2)
typedef struct _tagSDialogFontTemplate
{
	WORD        wFontSize      ;
	wchar_t     szFontName[14] ;
} SDialogFontTemplate;

typedef struct _tagSDialogTemplate
{
	DLGTEMPLATE header  ;
	wchar_t     szMenu  ;  // Align on WORD boundry. 
	wchar_t     szClass ;
	wchar_t     szTitle ;

	SDialogFontTemplate font ;
	WORD                wUnused ; // Help it to align.  Interesting that it does not align automatically. 
} SDialogTemplate;

typedef struct _tagSDialogItemTemplate
{
	DLGITEMTEMPLATE item      ;
	wchar_t         szOrdinal ;  // Align on WORD boundry. 
	wchar_t         szClass   ;
	wchar_t         szTitle   ;
	// Creation data falls on a DWORD boundry. 
} SDialogItemTemplate;
#pragma pack()

// Align on 4-byte boundry. 
#pragma pack(4)
typedef struct _tagSAdvancedAssertDialogTemplate
{
	SDialogTemplate     header                ;
	SDialogItemTemplate itemSend              ;
	DWORD               dwCreationDataSend    ;  // Align on DWORD boundry. 
	SDialogItemTemplate itemNote1             ;
	DWORD               dwCreationDataNote1   ;
	SDialogItemTemplate itemNote2             ;
	DWORD               dwCreationDataNote2   ;
	SDialogItemTemplate itemMessage           ;
	DWORD               dwCreationDataMessage ;
	SDialogItemTemplate itemAbort             ;
	DWORD               dwCreationDataAbort   ;
	SDialogItemTemplate itemRetry             ;
	DWORD               dwCreationDataRetry   ;
	SDialogItemTemplate itemIgnore            ;
	DWORD               dwCreationDataIgnore  ;
} SAdvancedAssertDialogTemplate;
#pragma pack()

const DWORD DS_ADVANCED_DIALOG = WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT ;
const DWORD WS_ADVANCED_BUTTON = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON ;
const DWORD WS_ADVANCED_TEXT   = WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_CENTER | ES_MULTILINE | ES_READONLY | WS_VSCROLL ;
const DWORD WS_ADVANCED_STATIC = WS_CHILD | WS_VISIBLE | WS_GROUP   | SS_LEFT ;

const WORD CL_BUTTON    = 0x0080 ;
const WORD CL_EDIT      = 0x0081 ;
const WORD CL_STATIC    = 0x0082 ;
const WORD CL_LISTBOX   = 0x0083 ;
const WORD CL_SCROLLBAR = 0x0084 ;
const WORD CL_COMBOBOX  = 0x0085 ;

static SAdvancedAssertDialogTemplate dlgAdvancedAssertTemplate =
{
#ifdef _WIN32
	{ { DS_ADVANCED_DIALOG, 0,   7,   0,   0, 292, 126,             },      0,         0, 0, { 8, L"MS Sans Serif" } }, // header
#else
	{ { DS_ADVANCED_DIALOG, 0,   7,   0,   0, 292, 126,             },      0,         0, 0, { 8,  "MS Sans Serif" } }, // header. Not UNICODE because not WIN32
#endif
	{ { WS_ADVANCED_BUTTON, 0,      220, 105,  50,  14, IDC_SEND    }, 0xFFFF, CL_BUTTON, 0 }, 0,  // itemSend  
	{ { WS_ADVANCED_STATIC, 0,       24,   7, 243,  21, IDC_NOTE1   }, 0xFFFF, CL_STATIC, 0 }, 0,  // itemNote1  
	{ { WS_ADVANCED_STATIC, 0,       24,  28, 243,  21, IDC_NOTE2   }, 0xFFFF, CL_STATIC, 0 }, 0,  // itemNote2  
	{ { WS_ADVANCED_TEXT  , 0,       22,  52, 247,  48, IDC_MESSAGE }, 0xFFFF, CL_EDIT  , 0 }, 0,  // itemMessage
	{ { WS_ADVANCED_BUTTON, 0,       22, 105,  50,  14, IDABORT     }, 0xFFFF, CL_BUTTON, 0 }, 0,  // itemAbort 
	{ { WS_ADVANCED_BUTTON, 0,       88, 105,  50,  14, IDRETRY     }, 0xFFFF, CL_BUTTON, 0 }, 0,  // itemRetry 
	{ { WS_ADVANCED_BUTTON, 0,      154, 105,  50,  14, IDIGNORE    }, 0xFFFF, CL_BUTTON, 0 }, 0,  // itemIgnore
} ;



typedef struct _tagSAdvancedAssertData
{
	LPCTSTR pszMessage  ;
	BOOL    bEnableSend ;
} SAdvancedAssertData;


BOOL FAR PASCAL AdvancedAssertDlgProc(HWND hDlg, UINT nMessage, 
									  WPARAM wParam, LPARAM lParam)
{
	switch ( nMessage )
	{
	case WM_INITDIALOG:
		{
			// Set the text here so that the dialog structure can be kept simple. 
			// Obviously, No attempt has been make to internationalize this code. 

			::SetWindowText ( hDlg, _T("Assertion Failed!") ) ;
			::SetDlgItemText( hDlg, IDABORT  , _T("&Abort"    ) ) ;
			::SetDlgItemText( hDlg, IDRETRY  , _T("&Retry"    ) ) ;
			::SetDlgItemText( hDlg, IDIGNORE , _T("&Ignore"   ) ) ;
			::SetDlgItemText( hDlg, IDC_SEND , _T("&Send Mail") ) ;
			::SetDlgItemText( hDlg, IDC_NOTE1, g_csAssertNote1  ) ;
			::SetDlgItemText( hDlg, IDC_NOTE2, g_csAssertNote2  ) ;

			SAdvancedAssertData* pData = (SAdvancedAssertData*) lParam ;
			ASSERT( pData);  // Careful, we are already inside an assert. 

			LPCTSTR pszMessage = pData->pszMessage ;
			::SetDlgItemText ( hDlg, IDC_MESSAGE, pszMessage ) ;
#ifndef _DEBUG
			HWND hwndRetry = ::GetDlgItem ( hDlg, IDRETRY ) ;
			::EnableWindow ( hwndRetry, FALSE ) ;
#endif
			HWND hwndSendEmail = ::GetDlgItem ( hDlg, IDC_SEND ) ;
			::EnableWindow ( hwndSendEmail, pData->bEnableSend ) ;

			// Setting the selection does not work. 
			// Try setting focus to the send email button first. 
			::SendDlgItemMessage ( hDlg, IDC_MESSAGE, EM_SETSEL, 0, 0 ) ;
			return TRUE ;
		}
	case WM_COMMAND:
		{
			switch ( wParam )
			{
			case IDCANCEL:  // Escape
				wParam = IDIGNORE ;
			case IDABORT:
			case IDRETRY:
			case IDIGNORE:
			case IDC_SEND:
				::EndDialog ( hDlg, wParam ) ;
				return TRUE ;
			}
			break ;
		}
	}
	return FALSE ;
}


/////////////////////////////////////////////////////////////////////////////
// Advanced Assert function

#define MAX_MSG 4096
#ifdef _WIN32
LONG lAdvancedAssertBusy       = -1 ;
LONG lAdvancedAssertReallyBusy = -1 ;
BOOL (AFXAPI* afxAssertFailedLine)(LPCSTR, int) ;

#ifndef _DEBUG
AFX_DATA BOOL afxTraceEnabled=FALSE ;
#else
#ifdef _AFXDLL
extern __declspec(dllimport) AFX_DATA BOOL afxTraceEnabled ;
#else
extern AFX_DATA BOOL afxTraceEnabled ;
#endif // _AFXDLL
#endif // _DEBUG

#else
int  NEAR nAdvancedIgnoreAssertCount =  0 ;
LONG NEAR lAdvancedAssertBusy        = -1 ;
HWND PASCAL _AfxGetSafeOwner(CWnd* pParent) ;
void AfxDebugBreak()
{
	_asm { int 3 } ;
}

#endif


// v9.3 - update 04 fixes for ASSERT in unicode builds- AAW 2009-03-29
//		- strings have been changed back or converted back to char instead of TCHAR where appropriate,
//		- some wsprintfs are now %hs as well.
// Note: file names are still ANSI strings (filenames rarely need UNICODE)
BOOL AFXAPI AdvancedAssertFailedLine(LPCSTR lpszCondition, LPCSTR lpszFileName, int nLine)
{
#ifdef _WIN32
#ifdef _DEBUG
	BOOL bUseCrtDebug=FALSE ;
	if ( bUseCrtDebug )
	{
		// This little bit of code was taken directly from the MFC sources. 
		// It is placed here just as a reference. 
		// we remove WM_QUIT because if it is in the queue then the message box won't display
		MSG msg ;
		BOOL bQuit = PeekMessage ( &msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE ) ;
		BOOL bResult = _CrtDbgReport ( _CRT_ASSERT, lpszFileName, nLine, NULL, lpszCondition ) ;
		if ( bQuit )
			PostQuitMessage ( (int)msg.wParam ) ;
		return bResult ;
	}
#endif	
	// handle the (hopefully rare) case of AfxGetAllocState ASSERT
	if ( ::InterlockedIncrement(&lAdvancedAssertReallyBusy) > 0 )
	{
		TCHAR szMessage[MAX_MSG ]=szNULL ;
		TCHAR szExeName[_MAX_PATH]=szNULL ;
		if ( !GetModuleFileName(NULL, szExeName, _MAX_PATH) )
			UTBStr::tcscpy ( szExeName, _MAX_PATH, _T("<program name unknown>") ) ;

		// assume the debugger or auxiliary port
		// Keep the trace down to one line. 
		wsprintf ( szMessage, _T("ASSERT( %hs );  Assertion Failed: %s: File %hs, Line %d\n"), lpszCondition, szExeName, lpszFileName, nLine ) ;
		::OutputDebugString ( szMessage ) ;
		::InterlockedDecrement ( &lAdvancedAssertReallyBusy ) ;

		// assert w/in assert (examine call stack to determine first one)
		AfxDebugBreak() ;
		return FALSE ;
	}

	// check for special hook function (for testing diagnostics)
	::InterlockedDecrement ( &lAdvancedAssertReallyBusy ) ;
	if ( afxAssertFailedLine != NULL )
		return (*afxAssertFailedLine)(lpszFileName, nLine) ;

	TCHAR szMessage[MAX_MSG ]=szNULL ;  // Separate message because of potential interlock problem. 
	TCHAR szExeName[_MAX_PATH]=szNULL ;
	if ( !GetModuleFileName(NULL, szExeName, _MAX_PATH) )
		UTBStr::tcscpy ( szExeName, _MAX_PATH, _T("<program name unknown>") ) ;

	if ( afxTraceEnabled )
	{
		// assume the debugger or auxiliary port
		// output into MacsBug looks better if it's done in one string,
		// since MacsBug always breaks the line after each output
		// Keep the trace down to one line. 
		wsprintf ( szMessage, _T("ASSERT( %hs );  Assertion Failed: %s: File %hs, Line %d\n"), lpszCondition, szExeName, lpszFileName, nLine ) ;
		::OutputDebugString ( szMessage ) ;
	}

	if ( ::InterlockedIncrement ( &lAdvancedAssertBusy) > 0 )
	{
		::InterlockedDecrement ( &lAdvancedAssertBusy ) ;

		// assert within assert (examine call stack to determine first one)
		AfxDebugBreak() ;
		return FALSE ;
	}

	// active popup window for the current thread
	HWND hwndParent = ::GetActiveWindow() ;
	if ( hwndParent != NULL )
		hwndParent = ::GetLastActivePopup ( hwndParent ) ;

	// Separate the assertion from the file and line info when displaying in a message box. 
	wsprintf ( szMessage, _T("Condition: ASSERT( %hs ); ") szCRLF _T("Program:%s ") szCRLF _T("File: %hs ") szCRLF _T("Line: %d"), lpszCondition, szExeName, lpszFileName, nLine ) ;

	// we remove WM_QUIT because if it is in the queue then the message box
	// won't display
	MSG msg ;
	BOOL bQuit = ::PeekMessage ( &msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE ) ;
	// display the assert

	SAdvancedAssertData dataAssert ;
	dataAssert.pszMessage  = szMessage           ;
	dataAssert.bEnableSend = g_bEnableAssertSend ;


	// The dialog template must be aligned on a 4-byte boundry. 
	LPVOID lpvSend    = &dlgAdvancedAssertTemplate.itemSend    ;
	LPVOID lpvNote1   = &dlgAdvancedAssertTemplate.itemNote1   ;
	LPVOID lpvNote2   = &dlgAdvancedAssertTemplate.itemNote2   ;
	LPVOID lpvMessage = &dlgAdvancedAssertTemplate.itemMessage ;
	LPVOID lpvAbort   = &dlgAdvancedAssertTemplate.itemAbort   ;
	LPVOID lpvRetry   = &dlgAdvancedAssertTemplate.itemRetry   ;
	LPVOID lpvIgnore  = &dlgAdvancedAssertTemplate.itemIgnore  ;
	// Can't assert here, so just trace the equivalent. 
	if ( ((DWORD_PTR)lpvSend    & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvSend    & 0x0003) == 0);\n") );
	if ( ((DWORD_PTR)lpvNote1   & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvNote1   & 0x0003) == 0);\n") );
	if ( ((DWORD_PTR)lpvNote2   & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvNote2   & 0x0003) == 0);\n") );
	if ( ((DWORD_PTR)lpvMessage & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvMessage & 0x0003) == 0);\n") );
	if ( ((DWORD_PTR)lpvAbort   & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvAbort   & 0x0003) == 0);\n") );
	if ( ((DWORD_PTR)lpvRetry   & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvRetry   & 0x0003) == 0);\n") );
	if ( ((DWORD_PTR)lpvIgnore  & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvIgnore  & 0x0003) == 0);\n") );

	HINSTANCE hInstance = AfxGetResourceHandle() ;

	// v9.3 - update 03 - 64-bit - added cast (DLGPROC) to 4th parameter - test! - TD
	int nCode = (int)::DialogBoxIndirectParam ( hInstance, (LPCDLGTEMPLATE)&dlgAdvancedAssertTemplate, hwndParent, (DLGPROC)AdvancedAssertDlgProc, (LPARAM)&dataAssert ) ;
	// If the custom version fails, then use the original version. 
	if ( nCode == -1 )
		nCode = ::MessageBox ( hwndParent, szMessage, _T("Assertion Failed!"), MB_TASKMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE | MB_SETFOREGROUND ) ;
	if ( bQuit )
		::PostQuitMessage ((int) msg.wParam ) ;

	// cleanup
	::InterlockedDecrement ( &lAdvancedAssertBusy ) ;

#else
	if ( nAdvancedIgnoreAssertCount > 0 )
	{
		nAdvancedIgnoreAssertCount-- ;
		return FALSE ;
	}

	// In case _AfxGetAppDataFails.
	if ( ++lAdvancedAssertBusy > 0 )
	{
		TCHAR szMessage[MAX_MSG ]=szNULL ;
		TCHAR szExeName[_MAX_PATH]=szNULL ;
		if ( !GetModuleFileName(NULL, szExeName, _MAX_PATH) )
			_tcscpy( szExeName, _T("<program name unknown>") ) ;

		// assume the debugger or auxiliary port
		wsprintf ( szMessage, _T("ASSERT( %hs );  Assertion Failed: %s: File %hs, Line %d\n"), lpszCondition, szExeName, lpszFileName, nLine ) ;
		::OutputDebugString ( szMessage ) ;
		lAdvancedAssertBusy-- ;

		// break into the debugger (or Dr Watson log)
		AfxDebugBreak() ;
		return FALSE ;
	}

	TCHAR szMessage[MAX_MSG ]=szNULL ;  // Separate message because of potential interlock problem. 
	TCHAR szExeName[_MAX_PATH]=szNULL ;
	if ( !GetModuleFileName(NULL, szExeName, _MAX_PATH) )
		_tcscpy ( szExeName, _T("<program name unknown>") ) ;

	if ( afxTraceEnabled )
	{
		// assume the debugger or auxiliary port
		wsprintf ( szMessage, _T("ASSERT( %hs );  Assertion Failed: %s: File %hs, Line %d\n"), lpszCondition, szExeName, lpszFileName, nLine ) ;
		::OutputDebugString ( szMessage ) ;
	}

	wsprintf ( szMessage, _T("Condition: ASSERT( %hs ); ") szCRLF _T("Program:%s ") szCRLF _T("File: %hs ") szCRLF _T("Line: %d"), lpszCondition, szExeName, lpszFileName, nLine ) ;

	// we remove WM_QUIT because if it is in the queue then the message box
	// won't display
	MSG msg ;
	BOOL bQuit = ::PeekMessage ( &msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE ) ;
	// display the assert

	SAdvancedAssertData dataAssert ;
	dataAssert.pszMessage  = szMessage           ;
	dataAssert.bEnableSend = g_bEnableAssertSend ;


	// The dialog template must be aligned on a 4-byte boundry. 
	LPVOID lpvSend    = &dlgAdvancedAssertTemplate.itemSend    ;
	LPVOID lpvNote1   = &dlgAdvancedAssertTemplate.itemNote1   ;
	LPVOID lpvNote2   = &dlgAdvancedAssertTemplate.itemNote2   ;
	LPVOID lpvMessage = &dlgAdvancedAssertTemplate.itemMessage ;
	LPVOID lpvAbort   = &dlgAdvancedAssertTemplate.itemAbort   ;
	LPVOID lpvRetry   = &dlgAdvancedAssertTemplate.itemRetry   ;
	LPVOID lpvIgnore  = &dlgAdvancedAssertTemplate.itemIgnore  ;
	// Can't assert here, so just trace the equivalent. 
	if ( ((DWORD)lpvSend    & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvSend    & 0x0003) == 0);\n") );
	if ( ((DWORD)lpvNote1   & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvNote1   & 0x0003) == 0);\n") );
	if ( ((DWORD)lpvNote2   & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvNote2   & 0x0003) == 0);\n") );
	if ( ((DWORD)lpvMessage & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvMessage & 0x0003) == 0);\n") );
	if ( ((DWORD)lpvAbort   & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvAbort   & 0x0003) == 0);\n") );
	if ( ((DWORD)lpvRetry   & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvRetry   & 0x0003) == 0);\n") );
	if ( ((DWORD)lpvIgnore  & 0x0003) != 0 ) TRACE( _T("ASSERT( lpvIgnore  & 0x0003) == 0);\n") );

	HINSTANCE hInstance  =  AfxGetResourceHandle() ;
	HWND      hwndParent = _AfxGetSafeOwner ( NULL ) ;
	int nCode = ::DialogBoxIndirectParam ( hInstance, (LPCDLGTEMPLATE)&dlgAdvancedAssertTemplate, hwndParent, AdvancedAssertDlgProc, (LPARAM)&dataAssert ) ;
	// If the custom version fails, then use the original version. 
	if ( nCode == -1 )
		nCode = ::MessageBox ( hwndParent, szMessage, _T("Assertion Failed!"), MB_SYSTEMMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE ) ;
	if ( bQuit )
		::PostQuitMessage ( msg.wParam ) ;

	lAdvancedAssertBusy-- ;

#endif
	if ( nCode == IDIGNORE )
		return FALSE ;   // ignore
	else if ( nCode == IDRETRY )
		return TRUE ;    // will cause AfxDebugBreak
	else if ( nCode == IDC_SEND )
	{
		// Simple MAPI does not like unicode strings, so convert to regular strings. 
		char szNote   [MAX_MSG]="" ;
		char szSubject[MAX_MSG]="" ;

		CString csSubject ;
		csSubject  = AfxGetApp()->m_pszAppName ;
		csSubject += " Assertion Failed!" ;

		int nMessageLength = (int)_tcslen ( szMessage ) ;
#ifdef  _UNICODE
		::WideCharToMultiByte(CP_ACP, 0, csSubject,csSubject.GetLength(), szSubject, _countof(szSubject), NULL, NULL);
		::WideCharToMultiByte(CP_ACP, 0, szMessage, nMessageLength, szNote, _countof(szNote), NULL, NULL);
#else
		UTBStr::strncpy(szSubject, _countof(szSubject), csSubject, __min(csSubject.GetLength()+1, _countof(szSubject)) ) ;
		UTBStr::strncpy(szNote, _countof(szNote), szMessage, __min(nMessageLength+1, _countof(szNote)) ) ;
#endif


		LPCSTR pszAttachment = NULL ;
		SendMailToBeta ( szSubject, szNote, pszAttachment ) ;
		return FALSE ;
	}
	AfxAbort() ;     // should not return (but otherwise AfxDebugBreak)
	return TRUE ;
}
// AAW: END

#endif // _DEBUG || BETA

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions