Audacity 3.2.0
win32/CrashReportContext.cpp
Go to the documentation of this file.
1/*!********************************************************************
2*
3 Audacity: A Digital Audio Editor
4
5 CrashReportContext.cpp
6
7 Vitaly Sverchinsky
8
9 Some parts of the code are designed to operate while app is crashing,
10 so there may be some restrictions on heap usage. For more information
11 please read Breakpad documentation.
12
13 **********************************************************************/
14
15#include "CrashReportContext.h"
16
17#include <locale>
18#include <codecvt>
19#include <sstream>
20#include "client/windows/handler/exception_handler.h"
21
22namespace
23{
24 //copy src(null-terminated) to dst,
25 //returns false if dest is not large enough
26 bool StrcpyChecked(wchar_t* dest, size_t destsz, const wchar_t* src)
27 {
28 auto len = wcslen(src);
29 if (len < destsz)
30 {
31 memcpy(dest, src, sizeof(wchar_t) * len);
32 dest[len] = 0;
33 return true;
34 }
35 return false;
36 }
37
38 //appends src(null-terminated) to dest, destsz is the total dest buffer size, not remaining
39 //returns false if dest is not large enough
40 bool StrcatChecked(wchar_t* dest, size_t destsz, const wchar_t* src)
41 {
42 auto srclen = wcslen(src);
43 auto dstlen = wcslen(dest);
44 if (srclen + dstlen < destsz)
45 {
46 memcpy(dest + dstlen, src, sizeof(wchar_t) * srclen);
47 dest[srclen + dstlen] = 0;
48 return true;
49 }
50 return false;
51 }
52
53 //converts parameters map to a string, so that the Crash Reporting program
54 //would understand them
55 std::string StringifyParameters(const std::map<std::string, std::string>& parameters)
56 {
57 std::stringstream stream;
58
59 std::size_t parameterIndex = 0;
60 std::size_t parametersCount = parameters.size();
61 for (auto& pair : parameters)
62 {
63 stream << pair.first.c_str() << "=\\\"" << pair.second.c_str() << "\\\"";
64 ++parameterIndex;
65 if (parameterIndex < parametersCount)
66 stream << ",";
67 }
68 return stream.str();
69 }
70}
71
72bool MakeCommand(CrashReportContext* c, const wchar_t* path, const wchar_t* id)
73{
74 //utility path
78
79 //parameters: /p "..."
80 if (ok && c->mParameters[0] != 0)
81 {
85 }
86 //crash report URL: /u https://...
90 //minidump path: path/to/minidump.dmp
96 return ok;
97}
98
99bool SendReport(CrashReportContext* c, const wchar_t* path, const wchar_t* id)
100{
101 if (!MakeCommand(c, path, id))
102 return false;
103
104 STARTUPINFOW si;
105 ZeroMemory(&si, sizeof(si));
106 si.cb = sizeof(si);
107 si.dwFlags = STARTF_USESHOWWINDOW;
108 si.wShowWindow = SW_SHOW;
109
110 PROCESS_INFORMATION pi;
111 ZeroMemory(&pi, sizeof(pi));
112
113 if (CreateProcessW(NULL, c->mCommand, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
114 {
115 CloseHandle(pi.hProcess);
116 CloseHandle(pi.hThread);
117 return true;
118 }
119 else
120 return false;
121}
122
124 const wchar_t* dump_path,
125 const wchar_t* minidump_id,
126 void* context,
127 EXCEPTION_POINTERS* /*exinfo*/,
128 MDRawAssertionInfo* /*assertion*/,
129 bool succeeded)
130{
131 CrashReportContext* crashReportContext = static_cast<CrashReportContext*>(context);
132 if (!SendReport(crashReportContext, dump_path, minidump_id))
133 return false;
134 return succeeded;
135}
136
137bool CrashReportContext::SetSenderPathUTF8(const std::string& path)
138{
139 auto fullpath = path + "\\" + CRASHREPORTER_PROGRAM_NAME;
140 return StrcpyChecked(mSenderPath, MaxBufferLength, std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(fullpath).c_str());
141}
142
143bool CrashReportContext::SetReportURL(const std::string& url)
144{
145 return StrcpyChecked(mReportURL, MaxBufferLength, std::wstring(url.begin(), url.end()).c_str());
146}
147
148bool CrashReportContext::SetParameters(const std::map<std::string, std::string>& p)
149{
150 auto str = StringifyParameters(p);
151 return StrcpyChecked(mParameters, MaxBufferLength, std::wstring(str.begin(), str.end()).c_str());
152}
153
154void CrashReportContext::StartHandler(const std::string& databasePath)
155{
156 //intentinal leak: error hooks may be useful while application is terminating
157 //CrashReportContext data should be alive too...
158 static auto handler = new google_breakpad::ExceptionHandler(
159 std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(databasePath),
160 NULL,
162 this,
163 google_breakpad::ExceptionHandler::HANDLER_ALL);
164}
165
#define str(a)
This object is for internal usage.
char mParameters[MaxBufferLength]
bool SetParameters(const std::map< std::string, std::string > &p)
bool SetReportURL(const std::string &url)
char mSenderPath[MaxBufferLength]
bool SetSenderPathUTF8(const std::string &path)
char mReportURL[MaxBufferLength]
static constexpr size_t MaxCommandLength
static constexpr size_t MaxBufferLength
void StartHandler(const std::string &databasePath)
wchar_t mCommand[MaxCommandLength]
bool StrcpyChecked(wchar_t *dest, size_t destsz, const wchar_t *src)
std::string StringifyParameters(const std::map< std::string, std::string > &parameters)
bool StrcatChecked(wchar_t *dest, size_t destsz, const wchar_t *src)
bool SendReport(CrashReportContext *c, const wchar_t *path, const wchar_t *id)
bool MakeCommand(CrashReportContext *c, const wchar_t *path, const wchar_t *id)
bool UploadReport(const wchar_t *dump_path, const wchar_t *minidump_id, void *context, EXCEPTION_POINTERS *, MDRawAssertionInfo *, bool succeeded)