home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / EXCEPT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  8.8 KB  |  335 lines

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