home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
mfc
/
src
/
except.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-16
|
9KB
|
338 lines
// 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
/////////////////////////////////////////////////////////////////////////////