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 >
C/C++ Source or Header  |  1998-06-16  |  9KB  |  338 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE1_SEG
  14. #pragma code_seg(AFX_CORE1_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. void PASCAL CException::operator delete(void* pbData)
  19. {
  20.     // check for proper exception object deletion
  21.     CException* pException = (CException*)pbData;
  22.     // use: pException->Delete(), do not use: delete pException
  23.     ASSERT(pException->m_bReadyForDelete);
  24.     ASSERT(pException->m_bAutoDelete > 0);
  25.  
  26.     // avoid crash when assert above is ignored
  27.     if (pException->m_bReadyForDelete && pException->m_bAutoDelete > 0)
  28.         CObject::operator delete(pbData);
  29. }
  30.  
  31. #if _MSC_VER >= 1200
  32. void PASCAL CException::operator delete(void* pbData,
  33.     LPCSTR /* lpszFileName */, int /* nLine */)
  34. {
  35.     operator delete(pbData);
  36. }
  37. #endif
  38.  
  39. #undef THIS_FILE
  40. static char THIS_FILE[] = __FILE__;
  41. #define new DEBUG_NEW
  42. #endif
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45. // AFX_EXCEPTION_CONTEXT (thread global state)
  46.  
  47. inline AFX_EXCEPTION_CONTEXT* AfxGetExceptionContext()
  48. {
  49.     DWORD lError = GetLastError();
  50.     AFX_EXCEPTION_CONTEXT* pContext = &_afxThreadState->m_exceptionContext;
  51.     SetLastError(lError);
  52.     return pContext;
  53. }
  54.  
  55. /////////////////////////////////////////////////////////////////////////////
  56. // CException
  57.  
  58. CException::CException()
  59. {
  60.     // most exceptions are deleted when not needed
  61.     m_bAutoDelete = TRUE;
  62. #ifdef _DEBUG
  63.     m_bReadyForDelete = FALSE;
  64. #endif
  65. }
  66.  
  67. CException::CException(BOOL bAutoDelete)
  68. {
  69.     // for exceptions which are not auto-delete (usually)
  70.     m_bAutoDelete = bAutoDelete;
  71. #ifdef _DEBUG
  72.     m_bReadyForDelete = FALSE;
  73. #endif
  74. }
  75.  
  76. void CException::Delete()
  77. {
  78.     // delete exception if it is auto-deleting
  79.     if (m_bAutoDelete > 0)
  80.     {
  81. #ifdef _DEBUG
  82.         m_bReadyForDelete = TRUE;
  83. #endif
  84.         delete this;
  85.     }
  86. }
  87.  
  88. BOOL CException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
  89.     PUINT pnHelpContext /* = NULL */ )
  90. {
  91.     if (pnHelpContext != NULL)
  92.         *pnHelpContext = 0;
  93.  
  94.     if (nMaxError != 0 && lpszError != NULL)
  95.         *lpszError = '\0';
  96.  
  97.     return FALSE;
  98. }
  99.  
  100. int CException::ReportError(UINT nType /* = MB_OK */,
  101.     UINT nError /* = 0 */)
  102. {
  103.     TCHAR   szErrorMessage[512];
  104.     int     nDisposition;
  105.     UINT    nHelpContext;
  106.  
  107.     if (GetErrorMessage(szErrorMessage, _countof(szErrorMessage), &nHelpContext))
  108.         nDisposition = AfxMessageBox(szErrorMessage, nType, nHelpContext);
  109.     else
  110.     {
  111.         if (nError == 0)
  112.             nError = AFX_IDP_NO_ERROR_AVAILABLE;
  113.         nDisposition = AfxMessageBox(nError, nType, nHelpContext);
  114.     }
  115.     return nDisposition;
  116. }
  117.  
  118. /////////////////////////////////////////////////////////////////////////////
  119. // AFX_EXCEPTION_LINK linked 'jmpbuf' and out-of-line helpers
  120.  
  121. AFX_EXCEPTION_LINK::AFX_EXCEPTION_LINK()
  122. {
  123.     // setup initial link state
  124. #ifdef _AFX_OLD_EXCEPTIONS
  125.     m_nType = 0;
  126. #endif
  127.     m_pException = NULL;    // no current exception yet
  128.  
  129.     // wire into top of exception link stack
  130.     AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext();
  131.     m_pLinkPrev = pContext->m_pLinkTop;
  132.     pContext->m_pLinkTop = this;
  133. }
  134.  
  135. // out-of-line cleanup called from inline AFX_EXCEPTION_LINK destructor
  136. void AFXAPI AfxTryCleanup()
  137. {
  138.     AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext();
  139.     AFX_EXCEPTION_LINK* pLinkTop = pContext->m_pLinkTop;
  140.  
  141.     // delete current exception
  142.     ASSERT(pLinkTop != NULL);
  143.     if (pLinkTop->m_pException != NULL)
  144.         pLinkTop->m_pException->Delete();
  145.  
  146.     // remove ourself from the top of the chain
  147.     pContext->m_pLinkTop = pLinkTop->m_pLinkPrev;
  148. }
  149.  
  150. #ifndef _AFX_OLD_EXCEPTIONS
  151. // special out-of-line implementation of THROW_LAST (for auto-delete behavior)
  152. void AFXAPI AfxThrowLastCleanup()
  153. {
  154.     AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext();
  155.     AFX_EXCEPTION_LINK* pLinkTop = pContext->m_pLinkTop;
  156.  
  157.     // check for THROW_LAST inside of auto-delete block
  158.     if (pLinkTop != NULL)
  159.     {
  160.         // make sure current exception does not get auto-deleted
  161.         pLinkTop->m_pException = NULL;
  162.     }
  163.  
  164.     // THROW_LAST macro will do actual 'throw'
  165. }
  166. #endif //!_AFX_OLD_EXCEPTIONS
  167.  
  168. /////////////////////////////////////////////////////////////////////////////
  169. // Global exception terminate handling - Obsolete API
  170. //  (apps written to C++ exceptions should use set_terminate)
  171.  
  172. #ifdef _AFX_OLD_EXCEPTIONS
  173.  
  174. void AFXAPI AfxTerminate()
  175. {
  176.     TRACE0("AfxTerminate called.\n");
  177.     (*AfxGetModuleState()->m_pfnTerminate)();
  178. }
  179.  
  180. AFX_TERM_PROC AFXAPI AfxSetTerminate(AFX_TERM_PROC pfnNew)
  181. {
  182.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  183.     AFX_TERM_PROC pfnOld = pModuleState->m_pfnTerminate;
  184.     pModuleState->m_pfnTerminate = pfnNew;
  185.     return pfnOld;
  186. }
  187.  
  188. #endif //_AFX_OLD_EXCEPTIONS
  189.  
  190. /////////////////////////////////////////////////////////////////////////////
  191. // Special non-C++ exception implementation
  192.  
  193. #ifdef _AFX_OLD_EXCEPTIONS
  194. // out-of-line implementation of THROW (for non-C++ exceptions)
  195. void AFXAPI AfxThrow(CException* pNewException)
  196. {
  197.     // get current exception context for running task
  198.     AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext();
  199.  
  200.     // check for THROW_LAST() first
  201.     if (pNewException == NULL)
  202.     {
  203.         ASSERT(pContext->m_pLinkTop != NULL);
  204.         pNewException = pContext->m_pLinkTop->m_pException;
  205.     }
  206.     ASSERT_VALID(pNewException);
  207.  
  208.     TRACE1("Warning: Throwing an Exception of type %hs.\n",
  209.         pNewException->GetRuntimeClass()->m_lpszClassName);
  210.  
  211.     while (pContext->m_pLinkTop != NULL)
  212.     {
  213.         AFX_EXCEPTION_LINK* pReceiver = pContext->m_pLinkTop;
  214.         if (pReceiver->m_pException != NULL)
  215.         {
  216.             // a THROW during a CATCH block -- this link may not be
  217.             //  destructed, so it is necessary to do all the cleanup that
  218.             //  the destructor would do.
  219.             if (pReceiver->m_pException != pNewException)
  220.                 pReceiver->m_pException->Delete();
  221.             pReceiver->m_pException = NULL;
  222.             pContext->m_pLinkTop = pReceiver->m_pLinkPrev;
  223.         }
  224.         else
  225.         {
  226.             // throw the exception to the top handler (if appropriate type)
  227.             if (pReceiver->m_nType == 0)
  228.             {
  229.                 // setup the receiver's context for the new exception
  230.                 pReceiver->m_pException = pNewException;
  231.  
  232.                 // and jump into the handler...
  233.                 longjmp(pReceiver->m_jumpBuf, 1);
  234.                 ASSERT(FALSE);  // not reached
  235.             }
  236.             // otherwise just call cleanup proc
  237.             (*pReceiver->m_callback.pfnCleanup)(pReceiver);
  238.         }
  239.     }
  240.  
  241.     ASSERT(pContext->m_pLinkTop == NULL);
  242.     // uncaught exception, terminate
  243.     TRACE1("Error: Uncaught Exception (%hs).\n",
  244.         pNewException->GetRuntimeClass()->m_lpszClassName);
  245.     AfxTerminate();
  246.     ASSERT(FALSE);  // not reached
  247. }
  248.  
  249. // out-of-line implementation of CATCH and AND_CATCH
  250. BOOL AFXAPI AfxCatchProc(CRuntimeClass* pClass)
  251. {
  252.     ASSERT(pClass != NULL);
  253.  
  254.     AFX_EXCEPTION_CONTEXT* pContext = AfxGetExceptionContext();
  255.     ASSERT(pContext->m_pLinkTop != NULL);
  256.     CException* pException = pContext->m_pLinkTop->m_pException;
  257.     ASSERT(pException != NULL);
  258.  
  259.     return pException->IsKindOf(pClass);
  260. }
  261. #endif //_AFX_OLD_EXCEPTIONS
  262.  
  263. #ifdef AFX_INIT_SEG
  264. #pragma code_seg(AFX_INIT_SEG)
  265. #endif
  266.  
  267. IMPLEMENT_DYNAMIC(CException, CObject)
  268.  
  269. IMPLEMENT_DYNAMIC(CMemoryException, CException)
  270. CMemoryException _simpleMemoryException(FALSE, AFX_IDS_MEMORY_EXCEPTION);
  271.  
  272. IMPLEMENT_DYNAMIC(CNotSupportedException, CException)
  273. CNotSupportedException _simpleNotSupportedException(FALSE, AFX_IDS_NOT_SUPPORTED_EXCEPTION);
  274.  
  275. /////////////////////////////////////////////////////////////////////////////
  276. // Standard exceptions
  277.  
  278. #ifdef AFX_AUX_SEG
  279. #pragma code_seg(AFX_AUX_SEG)
  280. #endif
  281.  
  282. void CSimpleException::InitString()
  283. {
  284.     m_bInitialized = TRUE;
  285.     m_bLoaded = (AfxLoadString(m_nResourceID,
  286.         m_szMessage, _countof(m_szMessage)) != 0);
  287. }
  288.  
  289. BOOL CSimpleException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
  290.         PUINT pnHelpContext)
  291. {
  292.     ASSERT(lpszError != NULL && AfxIsValidString(lpszError, nMaxError));
  293.  
  294.     if (pnHelpContext != NULL)
  295.         *pnHelpContext = 0;
  296.  
  297.     // if we didn't load our string (eg, we're a console app)
  298.     // return a null string and FALSE
  299.  
  300.     if (!m_bInitialized)
  301.         InitString();
  302.  
  303.     if (m_bLoaded)
  304.         lstrcpyn(lpszError, m_szMessage, nMaxError);
  305.     else
  306.         lpszError[0] = '\0';
  307.  
  308.     return m_bLoaded;
  309. }
  310.  
  311. void AFXAPI AfxThrowMemoryException()
  312. {
  313.     THROW(&_simpleMemoryException);
  314. }
  315.  
  316. void AFXAPI AfxThrowNotSupportedException()
  317. {
  318.     THROW(&_simpleNotSupportedException);
  319. }
  320.  
  321. #ifdef AFX_INIT_SEG
  322. #pragma code_seg(AFX_INIT_SEG)
  323. #endif
  324.  
  325. ////////////////////////////////////////////////////////////////////////////
  326. // out-of-line inlines for binary compatibility
  327.  
  328. #ifdef _AFXDLL
  329. #ifndef _DEBUG
  330.  
  331. CSimpleException::~CSimpleException()
  332.     { }
  333.  
  334. #endif
  335. #endif
  336.  
  337. /////////////////////////////////////////////////////////////////////////////
  338.