except.cpp 8.9 KB

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