// ExceptionAttacher.cpp // // This module contains the code that you need to add to any // MFC app in order to wrap the main thread in an exception handler. // The original version of this by Hans Dietrich replaced AfxWinMain, // but that fails to link properly, for unknown reasons, when UNICODE is // defined. // The code in this source file consists of two parts. // // The first part replaces code found in appmodul.cpp in the MFC // library. This is a verbatim copy with the exception of commenting // out the #pragma init_seg. The only reason for this code being here // is to fix the link problem; the MFC provided version of _tWinMain // won't call the replacement AfxWinMain because for mysterious reasons // it has a different decorated name when UNICODE is defined. // // The second part is a replacement for AfxWinMain. This is a direct copy // from winmain.cpp, modified by inserting the __try/__except. There is a // small difference here from the way it was done by Hans Deitrich: the call // to AfxWinTerm is moved outside the __try/__except. The reason for this // is that AfxWinTerm calls CToolTipCtrl::DestroyToolTipCtrl. If it's not // done now, it will be done later by ExitProcess, but it's too late then // and will result in a secondary exception. // // Warning: Any time MFC is updated, this file may need to be updated as well. // /////////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "ExceptionHandler.h" #ifdef UNICODE // When UNICODE is defined, the compiler thinks the AfxWinMain is not a // replacement for the one in winmain.cpp. Fortunately, it accepts our // replacement for wWinMain, which ends up correctly calling our version // of AfxWinMain. // the following section is a copy from appmodul.cpp ///////////////////////////////////////////////////////////////////////////// // export WinMain to force linkage to this module extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow); extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); } ///////////////////////////////////////////////////////////////////////////// // initialize app state such that it points to this module's core state BOOL AFXAPI AfxInitialize(BOOL bDLL, DWORD dwVersion) { AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); pModuleState->m_bDLL = (BYTE)bDLL; ASSERT(dwVersion <= _MFC_VER); UNUSED(dwVersion); // not used in release build #ifdef _AFXDLL pModuleState->m_dwVersion = dwVersion; #endif #ifdef _MBCS // set correct multi-byte code-page for Win32 apps if (!bDLL) _setmbcp(_MB_CP_ANSI); #endif //_MBCS return TRUE; } // force initialization early #pragma warning(disable: 4074) //#pragma init_seg(lib) #ifndef _AFXDLL void AFX_CDECL _AfxTermAppState() { // terminate local data and critical sections AfxTermLocalData(NULL, TRUE); AfxCriticalTerm(); // release the reference to thread local storage data AfxTlsRelease(); } #endif #ifndef _AFXDLL char _afxInitAppState = (char)(AfxInitialize(FALSE, _MFC_VER), atexit(&_AfxTermAppState)); #else char _afxInitAppState = (char)(AfxInitialize(FALSE, _MFC_VER)); #endif ///////////////////////////////////////////////////////////////////////////// #endif //UNICODE // the following section is a modified version of AfxWinMain from winmain.cpp: ///////////////////////////////////////////////////////////////////////////// // Standard WinMain implementation // Can be replaced as long as 'AfxWinInit' is called first int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { ASSERT(hPrevInstance == NULL); int nReturnCode = -1; __try { CWinThread* pThread = AfxGetThread(); CWinApp* pApp = AfxGetApp(); // AFX internal initialization if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)) goto InitFailure; // App global initializations (rare) if (pApp != NULL && !pApp->InitApplication()) goto InitFailure; // Perform specific initializations if (!pThread->InitInstance()) { if (pThread->m_pMainWnd != NULL) { TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n"); pThread->m_pMainWnd->DestroyWindow(); } nReturnCode = pThread->ExitInstance(); goto InitFailure; } nReturnCode = pThread->Run(); InitFailure: #ifdef _DEBUG // Check for missing AfxLockTempMap calls if (AfxGetModuleThreadState()->m_nTempMapLock != 0) { TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n", AfxGetModuleThreadState()->m_nTempMapLock); } AfxLockTempMaps(); AfxUnlockTempMaps(-1); #else ; #endif } __except(RecordExceptionInfo(GetExceptionInformation())) { } // must call AfxWinTerm after handling exception or we'll crash // again trying to destroy the tooltip window AfxWinTerm(); return nReturnCode; }