+#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;
+}
+