// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #ifdef AFX_CORE1_SEG #pragma code_seg(AFX_CORE1_SEG) #endif #ifdef _DEBUG void PASCAL CException::operator delete(void* pbData) { // check for proper exception object deletion CException* pException = (CException*)pbData; // use: pException->Delete(), do not use: delete pException ASSERT(pException->m_bReadyForDelete); ASSERT(pException->m_bAutoDelete > 0); // avoid crash when assert above is ignored if (pException->m_bReadyForDelete && pException->m_bAutoDelete > 0) CObject::operator delete(pbData); } #if _MSC_VER >= 1200 void PASCAL CException::operator delete(void* pbData, LPCSTR /* lpszFileName */, int /* nLine */) { operator delete(pbData); } #endif #undef THIS_FILE static char THIS_FILE[] = __FILE__; #define new DEBUG_NEW #endif ///////////////////////////////////////////////////////////////////////////// // AFX_EXCEPTION_CONTEXT (thread global state) inline AFX_EXCEPTION_CONTEXT* AfxGetExceptionContext() { DWORD lError = GetLastError(); AFX_EXCEPTION_CONTEXT* pContext = &_afxThreadState->m_exceptionContext; SetLastError(lError); return pContext; } ///////////////////////////////////////////////////////////////////////////// // CException CException::CException() { // most exceptions are deleted when not needed m_bAutoDelete = TRUE; #ifdef _DEBUG m_bReadyForDelete = FALSE; #endif } CException::CException(BOOL bAutoDelete) { // for exceptions which are not auto-delete (usually) m_bAutoDelete = bAutoDelete; #ifdef _DEBUG m_bReadyForDelete = FALSE; #endif } void CException::Delete() { // delete exception if it is auto-deleting if (m_bAutoDelete > 0) { #ifdef _DEBUG m_bReadyForDelete = TRUE; #endif delete this; } } BOOL CException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError, PUINT pnHelpContext /* = NULL */ ) { if (pnHelpContext != NULL) *pnHelpContext = 0; if (nMaxError != 0 && lpszError != NULL) *lpszError = '\0'; return FALSE; } int CException::ReportError(UINT nType /* = MB_OK */, UINT nError /* = 0 */) { TCHAR szErrorMessage[512]; int nDisposition; UINT nHelpContext; if (GetErrorMessage(szErrorMessage, _countof(szErrorMessage), &nHelpContext)) nDisposition = AfxMessageBox(szErrorMessage, nType, nHelpContext); else { if (nError == 0) nError = AFX_IDP_NO_ERROR_AVAILABLE; nDisposition = AfxMessageBox(nError, nType, nHelpContext); } return nDisposition; } ///////////////////////////////////////////////////////////////////////////// // AFX_EXCEPTION_LINK linked 'jmpbuf' and out-of-line helpers AFX_EXCEPTION_LINK::AFX_EXCEPTION_LINK() { // setup initial link state #ifdef _AFX_OLD_EXCEPTIONS m_nType = 0; #endif m_pException = NULL; // no current exception yet // wire into top of exception link stack AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); m_pLinkPrev = pContext->m_pLinkTop; pContext->m_pLinkTop = this; } // out-of-line cleanup called from inline AFX_EXCEPTION_LINK destructor void AFXAPI AfxTryCleanup() { AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); AFX_EXCEPTION_LINK* pLinkTop = pContext->m_pLinkTop; // delete current exception ASSERT(pLinkTop != NULL); if (pLinkTop->m_pException != NULL) pLinkTop->m_pException->Delete(); // remove ourself from the top of the chain pContext->m_pLinkTop = pLinkTop->m_pLinkPrev; } #ifndef _AFX_OLD_EXCEPTIONS // special out-of-line implementation of THROW_LAST (for auto-delete behavior) void AFXAPI AfxThrowLastCleanup() { AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); AFX_EXCEPTION_LINK* pLinkTop = pContext->m_pLinkTop; // check for THROW_LAST inside of auto-delete block if (pLinkTop != NULL) { // make sure current exception does not get auto-deleted pLinkTop->m_pException = NULL; } // THROW_LAST macro will do actual 'throw' } #endif //!_AFX_OLD_EXCEPTIONS ///////////////////////////////////////////////////////////////////////////// // Global exception terminate handling - Obsolete API // (apps written to C++ exceptions should use set_terminate) #ifdef _AFX_OLD_EXCEPTIONS void AFXAPI AfxTerminate() { TRACE0("AfxTerminate called.\n"); (*AfxGetModuleState()->m_pfnTerminate)(); } AFX_TERM_PROC AFXAPI AfxSetTerminate(AFX_TERM_PROC pfnNew) { AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); AFX_TERM_PROC pfnOld = pModuleState->m_pfnTerminate; pModuleState->m_pfnTerminate = pfnNew; return pfnOld; } #endif //_AFX_OLD_EXCEPTIONS ///////////////////////////////////////////////////////////////////////////// // Special non-C++ exception implementation #ifdef _AFX_OLD_EXCEPTIONS // out-of-line implementation of THROW (for non-C++ exceptions) void AFXAPI AfxThrow(CException* pNewException) { // get current exception context for running task AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); // check for THROW_LAST() first if (pNewException == NULL) { ASSERT(pContext->m_pLinkTop != NULL); pNewException = pContext->m_pLinkTop->m_pException; } ASSERT_VALID(pNewException); TRACE1("Warning: Throwing an Exception of type %hs.\n", pNewException->GetRuntimeClass()->m_lpszClassName); while (pContext->m_pLinkTop != NULL) { AFX_EXCEPTION_LINK* pReceiver = pContext->m_pLinkTop; if (pReceiver->m_pException != NULL) { // a THROW during a CATCH block -- this link may not be // destructed, so it is necessary to do all the cleanup that // the destructor would do. if (pReceiver->m_pException != pNewException) pReceiver->m_pException->Delete(); pReceiver->m_pException = NULL; pContext->m_pLinkTop = pReceiver->m_pLinkPrev; } else { // throw the exception to the top handler (if appropriate type) if (pReceiver->m_nType == 0) { // setup the receiver's context for the new exception pReceiver->m_pException = pNewException; // and jump into the handler... longjmp(pReceiver->m_jumpBuf, 1); ASSERT(FALSE); // not reached } // otherwise just call cleanup proc (*pReceiver->m_callback.pfnCleanup)(pReceiver); } } ASSERT(pContext->m_pLinkTop == NULL); // uncaught exception, terminate TRACE1("Error: Uncaught Exception (%hs).\n", pNewException->GetRuntimeClass()->m_lpszClassName); AfxTerminate(); ASSERT(FALSE); // not reached } // out-of-line implementation of CATCH and AND_CATCH BOOL AFXAPI AfxCatchProc(CRuntimeClass* pClass) { ASSERT(pClass != NULL); AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext(); ASSERT(pContext->m_pLinkTop != NULL); CException* pException = pContext->m_pLinkTop->m_pException; ASSERT(pException != NULL); return pException->IsKindOf(pClass); } #endif //_AFX_OLD_EXCEPTIONS #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif IMPLEMENT_DYNAMIC(CException, CObject) IMPLEMENT_DYNAMIC(CMemoryException, CException) CMemoryException _simpleMemoryException(FALSE, AFX_IDS_MEMORY_EXCEPTION); IMPLEMENT_DYNAMIC(CNotSupportedException, CException) CNotSupportedException _simpleNotSupportedException(FALSE, AFX_IDS_NOT_SUPPORTED_EXCEPTION); ///////////////////////////////////////////////////////////////////////////// // Standard exceptions #ifdef AFX_AUX_SEG #pragma code_seg(AFX_AUX_SEG) #endif void CSimpleException::InitString() { m_bInitialized = TRUE; m_bLoaded = (AfxLoadString(m_nResourceID, m_szMessage, _countof(m_szMessage)) != 0); } BOOL CSimpleException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError, PUINT pnHelpContext) { ASSERT(lpszError != NULL && AfxIsValidString(lpszError, nMaxError)); if (pnHelpContext != NULL) *pnHelpContext = 0; // if we didn't load our string (eg, we're a console app) // return a null string and FALSE if (!m_bInitialized) InitString(); if (m_bLoaded) lstrcpyn(lpszError, m_szMessage, nMaxError); else lpszError[0] = '\0'; return m_bLoaded; } void AFXAPI AfxThrowMemoryException() { THROW(&_simpleMemoryException); } void AFXAPI AfxThrowNotSupportedException() { THROW(&_simpleNotSupportedException); } #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif //////////////////////////////////////////////////////////////////////////// // out-of-line inlines for binary compatibility #ifdef _AFXDLL #ifndef _DEBUG CSimpleException::~CSimpleException() { } #endif #endif /////////////////////////////////////////////////////////////////////////////