/////////////////////////////////////////////////////////////////////////////
-// Name: msw/crashrpt.cpp
+// Name: src/msw/crashrpt.cpp
// Purpose: code to generate crash dumps (minidumps)
// Author: Vadim Zeitlin
// Modified by:
void Output(const wxChar *format, ...);
// output end of line
- void OutputEndl() { Output(_T("\r\n")); }
+ void OutputEndl() { Output(wxT("\r\n")); }
// the handle of the report file
HANDLE m_hFile;
DWORD cbWritten;
wxString s = wxString::FormatV(format, argptr);
- ::WriteFile(m_hFile, s, s.length() * sizeof(wxChar), &cbWritten, 0);
+
+ wxCharBuffer buf(s.mb_str(wxConvUTF8));
+ ::WriteFile(m_hFile, buf.data(), strlen(buf.data()), &cbWritten, 0);
va_end(argptr);
}
if ( !ep )
{
- Output(_T("Context for crash report generation not available."));
+ Output(wxT("Context for crash report generation not available."));
return false;
}
TCHAR envFlags[64];
DWORD dwLen = ::GetEnvironmentVariable
(
- _T("WX_CRASH_FLAGS"),
+ wxT("WX_CRASH_FLAGS"),
envFlags,
WXSIZEOF(envFlags)
);
int flagsEnv;
if ( dwLen && dwLen < WXSIZEOF(envFlags) &&
- wxSscanf(envFlags, _T("%d"), &flagsEnv) == 1 )
+ wxSscanf(envFlags, wxT("%d"), &flagsEnv) == 1 )
{
flags = flagsEnv;
}
}
else // minimal dump
{
- dumpFlags = MiniDumpNormal;
+ // the file size is not much bigger than when using MiniDumpNormal
+ // if we use the flags below, but the minidump is much more useful
+ // as it contains the values of many (but not all) local variables
+ dumpFlags = (MINIDUMP_TYPE)(MiniDumpScanMemory
+#if _MSC_VER > 1300
+ |MiniDumpWithIndirectlyReferencedMemory
+#endif
+ );
}
if ( !wxDbgHelpDLL::MiniDumpWriteDump
NULL // no callbacks
) )
{
- Output(_T("MiniDumpWriteDump() failed."));
+ Output(wxT("MiniDumpWriteDump() failed."));
return false;
}
}
else // dbghelp.dll couldn't be loaded
{
- Output(wxDbgHelpDLL::GetErrorMessage());
+ Output(wxT("%s"), wxDbgHelpDLL::GetErrorMessage().c_str());
}
#else // !wxUSE_DBGHELP
wxUnusedVar(flags);
+ wxUnusedVar(ep);
- Output(_T("Support for crash report generation was not included ")
- _T("in this wxWidgets version."));
+ Output(wxT("Support for crash report generation was not included ")
+ wxT("in this wxWidgets version."));
#endif // wxUSE_DBGHELP/!wxUSE_DBGHELP
return false;
// ----------------------------------------------------------------------------
/* static */
-void wxCrashReport::SetFileName(const wxChar *filename)
+void wxCrashReport::SetFileName(const wxString& filename)
{
- wxStrncpy(gs_reportFilename, filename, WXSIZEOF(gs_reportFilename) - 1);
- gs_reportFilename[WXSIZEOF(gs_reportFilename) - 1] = _T('\0');
+ wxStrlcpy(gs_reportFilename, filename.t_str(), WXSIZEOF(gs_reportFilename));
}
/* static */
-const wxChar *wxCrashReport::GetFileName()
+wxString wxCrashReport::GetFileName()
{
return gs_reportFilename;
}
return impl.Generate(flags, ep);
}
+/* static */
+bool wxCrashReport::GenerateNow(int flags)
+{
+ bool rc = false;
+
+ __try
+ {
+ RaiseException(0x1976, 0, 0, NULL);
+ }
+ __except( rc = Generate(flags, (EXCEPTION_POINTERS *)GetExceptionInformation()),
+ EXCEPTION_CONTINUE_EXECUTION )
+ {
+ // never executed because of EXCEPTION_CONTINUE_EXECUTION above
+ }
+
+ return rc;
+}
+
// ----------------------------------------------------------------------------
// wxCrashContext
// ----------------------------------------------------------------------------
if ( !ep )
{
- wxCHECK_RET( wxGlobalSEInformation, _T("no exception info available") );
+ wxCHECK_RET( wxGlobalSEInformation, wxT("no exception info available") );
ep = wxGlobalSEInformation;
}
{
wxString s;
- #define CASE_EXCEPTION( x ) case EXCEPTION_##x: s = _T(#x); break
+ #define CASE_EXCEPTION( x ) case EXCEPTION_##x: s = wxT(#x); break
switch ( code )
{
(
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_HMODULE,
- ::GetModuleHandle(_T("NTDLL.DLL")),
+ ::GetModuleHandle(wxT("NTDLL.DLL")),
code,
0,
wxStringBuffer(s, 1024),
0
) )
{
- s.Printf(_T("UNKNOWN_EXCEPTION(%d)"), code);
+ s.Printf(wxT("UNKNOWN_EXCEPTION(%d)"), code);
}
}