-#endif // !wxUSE_MINIDUMP
-
-#endif // wxUSE_DBGHELP
-
-bool wxCrashReportImpl::Generate(
-#if wxUSE_DBGHELP
- int flags
-#else
- int WXUNUSED(flags)
-#endif
-)
-{
- if ( m_hFile == INVALID_HANDLE_VALUE )
- return false;
-
-#if wxUSE_DBGHELP
- if ( !wxGlobalSEInformation )
- return false;
-
-#if !wxUSE_MINIDUMP
- PEXCEPTION_RECORD pExceptionRecord = wxGlobalSEInformation->ExceptionRecord;
- PCONTEXT pCtx = wxGlobalSEInformation->ContextRecord;
-
- if ( !pExceptionRecord || !pCtx )
- return false;
-
- HANDLE hModuleCrash = OutputBasicContext(pExceptionRecord, pCtx);
-#endif // !wxUSE_MINIDUMP
-
- // show to the user that we're doing something...
- BusyCursor busyCursor;
-
- // user-specified crash report flags override those specified by the
- // programmer
- TCHAR envFlags[64];
- DWORD dwLen = ::GetEnvironmentVariable
- (
- _T("WX_CRASH_FLAGS"),
- envFlags,
- WXSIZEOF(envFlags)
- );
-
- int flagsEnv;
- if ( dwLen && dwLen < WXSIZEOF(envFlags) &&
- wxSscanf(envFlags, _T("%d"), &flagsEnv) == 1 )
- {
- flags = flagsEnv;
- }
-
- // for everything else we need dbghelp.dll
- wxDynamicLibrary dllDbgHelp(_T("dbghelp.dll"), wxDL_VERBATIM);
- if ( dllDbgHelp.IsLoaded() )
- {
- if ( BindDbgHelpFunctions(dllDbgHelp) )
- {
-#if wxUSE_MINIDUMP
- MINIDUMP_EXCEPTION_INFORMATION minidumpExcInfo;
-
- minidumpExcInfo.ThreadId = ::GetCurrentThreadId();
- minidumpExcInfo.ExceptionPointers = wxGlobalSEInformation;
- minidumpExcInfo.ClientPointers = FALSE; // in our own address space
-
- // do generate the dump
- MINIDUMP_TYPE dumpFlags;
- if ( flags & wxCRASH_REPORT_LOCALS )
- {
- // the only way to get local variables is to dump the entire
- // process memory space -- but this makes for huge (dozens or
- // even hundreds of Mb) files
- dumpFlags = MiniDumpWithFullMemory;
- }
- else if ( flags & wxCRASH_REPORT_GLOBALS )
- {
- // MiniDumpWriteDump() has the option for dumping just the data
- // segment which contains all globals -- exactly what we need
- dumpFlags = MiniDumpWithDataSegs;
- }
- else // minimal dump
- {
- dumpFlags = MiniDumpNormal;
- }
-
- if ( !MiniDumpWriteDump
- (
- ::GetCurrentProcess(),
- ::GetCurrentProcessId(),
- m_hFile, // file to write to
- dumpFlags, // kind of dump to craete
- &minidumpExcInfo,
- NULL, // no extra user-defined data
- NULL // no callbacks
- ) )
- {
- Output(_T("MiniDumpWriteDump() failed."));
-
- return false;
- }
-
- return true;
-#else // !wxUSE_MINIDUMP
- SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME);
-
- // Initialize DbgHelp
- if ( SymInitialize(GetCurrentProcess(), NULL, TRUE /* invade */) )
- {
- OutputStack(pCtx, flags);
-
- if ( hModuleCrash && (flags & wxCRASH_REPORT_GLOBALS) )
- {
- OutputGlobals(hModuleCrash);
- }
-
- return true;
- }
-#endif // !wxUSE_MINIDUMP
- }
- else
- {
- Output(_T("\r\nPlease update your dbghelp.dll version, ")
- _T("at least version 5.1 is needed!\r\n")
- _T("(if you already have a new version, please ")
- _T("put it in the same directory where the program is.)\r\n"));
- }
- }
- else // failed to load dbghelp.dll
- {
- Output(_T("Please install dbghelp.dll available free of charge ")
- _T("from Microsoft to get more detailed crash information!"));
- }
-
- Output(_T("\r\nLatest dbghelp.dll is available at ")
- _T("http://www.microsoft.com/whdc/ddk/debugging/\r\n"));
-
-#else // !wxUSE_DBGHELP
- Output(_T("Support for crash report generation was not included ")
- _T("in this wxWidgets version."));
-#endif // wxUSE_DBGHELP/!wxUSE_DBGHELP
-
- return false;
-}
-
-// ----------------------------------------------------------------------------
-// wxCrashReport
-// ----------------------------------------------------------------------------
-
-/* static */
-void wxCrashReport::SetFileName(const wxChar *filename)
-{
- wxStrncpy(gs_reportFilename, filename, WXSIZEOF(gs_reportFilename) - 1);
- gs_reportFilename[WXSIZEOF(gs_reportFilename) - 1] = _T('\0');
-}
-
-/* static */
-const wxChar *wxCrashReport::GetFileName()
-{
- return gs_reportFilename;
-}
-
-/* static */
-bool wxCrashReport::Generate(int flags)
-{
- wxCrashReportImpl impl(gs_reportFilename);
-
- return impl.Generate(flags);
-}
-
-// ----------------------------------------------------------------------------
-// wxApp::OnFatalException() support
-// ----------------------------------------------------------------------------
-
-bool wxHandleFatalExceptions(bool doit)
-{
- // assume this can only be called from the main thread
- gs_handleExceptions = doit;
-
- if ( doit )
- {
- // try to find a place where we can put out report file later
- if ( !::GetTempPath
- (
- WXSIZEOF(gs_reportFilename),
- gs_reportFilename
- ) )
- {
- wxLogLastError(_T("GetTempPath"));
-
- // when all else fails...
- wxStrcpy(gs_reportFilename, _T("c:\\"));
- }
-
- // use PID and date to make the report file name more unique
- wxString fname = wxString::Format
- (
-#if wxUSE_MINIDUMP
- _T("%s_%s_%lu.dmp"),
-#else // !wxUSE_MINIDUMP
- _T("%s_%s_%lu.rpt"),
-#endif // wxUSE_MINIDUMP/!wxUSE_MINIDUMP
- wxTheApp ? wxTheApp->GetAppName().c_str()
- : _T("wxwindows"),
- wxDateTime::Now().Format(_T("%Y%m%d")).c_str(),
- ::GetCurrentProcessId()
- );
-
- wxStrncat(gs_reportFilename, fname,
- WXSIZEOF(gs_reportFilename) - wxStrlen(gs_reportFilename) - 1);
- }
-
- return true;
-}
-
-extern 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;
-}
-
-#else // !wxUSE_ON_FATAL_EXCEPTION
-
-bool wxHandleFatalExceptions(bool WXUNUSED(doit))
-{
- wxFAIL_MSG(_T("set wxUSE_ON_FATAL_EXCEPTION to 1 to use this function"));
-
- return false;
-}
-
-#endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION