except.cpp 9.3 KB

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