+// flag telling us whether the application wants to handle exceptions at all
+static bool gs_handleExceptions = false;
+
+unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs)
+{
+ if ( gs_handleExceptions && wxTheApp )
+ {
+ // store the pointer to exception info
+ wxGlobalSEInformation = pExcPtrs;
+
+ // give the user a chance to do something special about this
+ __try
+ {
+ wxTheApp->OnFatalException();
+ }
+ __except ( EXCEPTION_EXECUTE_HANDLER )
+ {
+ // nothing to do here, just ignore the exception inside the
+ // exception handler
+ ;
+ }
+
+ wxGlobalSEInformation = NULL;
+
+ // this will execute our handler and terminate the process
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+#ifdef __VISUALC__
+
+static void wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS *ep)
+{
+ wxGlobalSEHandler(ep);
+}
+
+#endif // __VISUALC__
+
+bool wxHandleFatalExceptions(bool doit)
+{
+ // assume this can only be called from the main thread
+ gs_handleExceptions = doit;
+
+#ifdef __VISUALC__
+ // VC++ (at least from 4.0 up to version 7.1) is incredibly broken in that
+ // a "catch ( ... )" will *always* catch SEH exceptions in it even though
+ // it should have never been the case... to prevent such catches from
+ // stealing the exceptions from our wxGlobalSEHandler which is only called
+ // if the exception is not handled elsewhere, we have to also call it from
+ // a special SEH translator function which is called by VC CRT when a Win32
+ // exception occurs
+
+ // this warns that /EHa (async exceptions) should be used when using
+ // _set_se_translator but, in fact, this doesn't seem to change anything
+ // with VC++ up to 7.1 -- to be confirmed with VC++ 8
+ #if _MSC_VER <= 1310
+ #pragma warning(disable:4535)
+ #endif
+
+ _set_se_translator(doit ? wxSETranslator : NULL);
+#endif
+
+#if wxUSE_CRASHREPORT
+ if ( doit )
+ {
+ // try to find a place where we can put out report file later
+ wxChar fullname[MAX_PATH];
+ if ( !::GetTempPath(WXSIZEOF(fullname), fullname) )
+ {
+ wxLogLastError(_T("GetTempPath"));
+
+ // when all else fails...
+ wxStrcpy(fullname, _T("c:\\"));
+ }
+
+ // use PID and date to make the report file name more unique
+ wxString name = wxString::Format
+ (
+ _T("%s_%s_%lu.dmp"),
+ wxTheApp ? wxTheApp->GetAppName().c_str()
+ : _T("wxwindows"),
+ wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(),
+ ::GetCurrentProcessId()
+ );
+
+ wxStrncat(fullname, name, WXSIZEOF(fullname) - wxStrlen(fullname) - 1);
+
+ wxCrashReport::SetFileName(fullname);
+ }
+#endif // wxUSE_CRASHREPORT
+
+ return true;
+}
+
+int wxEntry(int& argc, wxChar **argv)
+{
+ __try
+ {
+ extern int wxEntryReal(int& argc, wxChar **argv);
+
+ return wxEntryReal(argc, argv);
+ }
+ __except ( wxGlobalSEHandler(GetExceptionInformation()) )
+ {
+ ::ExitProcess(3); // the same exit code as abort()
+
+#if !defined(_MSC_VER) || _MSC_VER < 1300
+ // this code is unreachable but put it here to suppress warnings
+ // from some compilers
+ return -1;
+#endif
+ }
+}
+
+#endif // wxUSE_ON_FATAL_EXCEPTION && wxUSE_BASE
+
+#if wxUSE_GUI