OLD | NEW |
| (Empty) |
1 // Copyright 2007-2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #ifndef OMAHA_GOOPDATE_CRASH_H__ | |
17 #define OMAHA_GOOPDATE_CRASH_H__ | |
18 | |
19 #include <windows.h> | |
20 #include <dbghelp.h> | |
21 #include <atlsecurity.h> | |
22 #include <atlstr.h> | |
23 #include <map> | |
24 #include "base/basictypes.h" | |
25 #include "omaha/common/const_goopdate.h" | |
26 #include "third_party/gtest/include/gtest/gtest_prod.h" | |
27 #include "third_party/breakpad/src/client/windows/crash_generation/client_info.h
" | |
28 #include "third_party/breakpad/src/client/windows/crash_generation/crash_generat
ion_server.h" | |
29 #include "third_party/breakpad/src/client/windows/handler/exception_handler.h" | |
30 | |
31 namespace omaha { | |
32 | |
33 // Annotates the version reported along with the crash. | |
34 const TCHAR* const kCrashVersionPostfixString = | |
35 #if !OFFICIAL_BUILD | |
36 _T(".private") | |
37 #endif | |
38 #if DEBUG | |
39 _T(".debug") | |
40 #endif | |
41 _T(""); | |
42 | |
43 // Official builds can only send a few crashes per day. Debug builds including | |
44 // all build modes for unit tests send unlimited number of crashes. | |
45 const int kCrashReportMaxReportsPerDay = | |
46 #if OFFICIAL_BUILD | |
47 5; | |
48 #else | |
49 INT_MAX; | |
50 #endif | |
51 | |
52 const TCHAR* const kNoCrashHandlerEnvVariableName = | |
53 _T("GOOGLE_UPDATE_NO_CRASH_HANDLER"); | |
54 | |
55 // TODO(omaha): refactor so this is not a static class. | |
56 // TODO(omaha): rename class name to better indicate its funtionality. | |
57 class Crash { | |
58 public: | |
59 typedef std::map<std::wstring, std::wstring> ParameterMap; | |
60 | |
61 // Installs and uninstalls Breakpad exception handler. Calling the | |
62 // functions from DllMain results in undefined behavior, including | |
63 // deadlocks. | |
64 static HRESULT InstallCrashHandler(bool is_machine); | |
65 static void UninstallCrashHandler(); | |
66 | |
67 // Starts the server to listen for out-of-process crashes. | |
68 static HRESULT StartServer(); | |
69 | |
70 // Stops the crash server. | |
71 static void StopServer(); | |
72 | |
73 // Generates a divide by zero to trigger Breakpad dump in non-ship builds. | |
74 static int CrashNow(); | |
75 | |
76 // Handles out-of-process crash requests. | |
77 static HRESULT CrashHandler(bool is_machine, | |
78 const google_breakpad::ClientInfo& client_info, | |
79 const CString& crash_filename); | |
80 | |
81 // Reports a crash by logging it to the Windows event log, saving a copy of | |
82 // the crash, and uploading it. After reporting the crash, the function | |
83 // deletes the crash file. Crashes that have a custom info file are | |
84 // considered product crashes and they are always handled out-of-process. | |
85 // These crashes are always uploaded. | |
86 // Crashes that do not specify a custom info file are considered Omaha | |
87 // internal crashes and they are handled in-process. In this case, the | |
88 // upload behavior is controlled by the value of can_upload_in_process | |
89 // parameter. | |
90 static HRESULT Report(bool can_upload_in_process, | |
91 const CString& crash_filename, | |
92 const CString& custom_info_filename, | |
93 const CString& lang); | |
94 | |
95 // Sets a version string which is appended to the 'ver' parameter sent | |
96 // with the crash report. | |
97 static void set_version_postfix(const TCHAR* version_postfix) { | |
98 version_postfix_ = version_postfix; | |
99 } | |
100 | |
101 // Sets how many reports can be sent until the crash report sender starts | |
102 // rejecting and discarding crashes. | |
103 static void set_max_reports_per_day(int max_reports_per_day) { | |
104 max_reports_per_day_ = max_reports_per_day; | |
105 } | |
106 | |
107 static void set_crash_report_url(const TCHAR* crash_report_url) { | |
108 crash_report_url_ = crash_report_url; | |
109 } | |
110 | |
111 static bool is_machine() { return is_machine_; } | |
112 | |
113 private: | |
114 | |
115 static HRESULT Initialize(bool is_machine); | |
116 | |
117 // Reports a crash of Google Update. Does not delete the crash file. | |
118 static HRESULT ReportGoogleUpdateCrash(bool can_upload, | |
119 const CString& crash_filename, | |
120 const CString& custom_info_filename, | |
121 const CString& lang); | |
122 | |
123 // Reports an out-of-process crash on behalf of another product. Does not | |
124 // delete the crash file. | |
125 static HRESULT ReportProductCrash(bool can_upload, | |
126 const CString& crash_filename, | |
127 const CString& custom_info_filename, | |
128 const CString& lang); | |
129 | |
130 // Initializes the crash directory. Creates the directory if it does not | |
131 // exist. | |
132 static HRESULT InitializeCrashDir(); | |
133 | |
134 static HRESULT InitializeDirSecurity(CString* dir); | |
135 | |
136 // Returns true if the current process is reporting an exception. | |
137 static HRESULT IsCrashReportProcess(bool* is_crash_report_process); | |
138 | |
139 // Logs an entry in the Windows Event Log for the specified source. | |
140 static HRESULT Log(uint16 type, | |
141 uint32 id, | |
142 const TCHAR* source, | |
143 const TCHAR* description); | |
144 | |
145 // Starts the sender process with the environment variables setup such that | |
146 // the sender process doesn't register crash filter to avoid potential | |
147 // recursive crashes problem. | |
148 static HRESULT StartSenderWithCommandLine(CString* cmd_line); | |
149 | |
150 // Creates a text file that contains name/value pairs of custom information. | |
151 // The text file is created in the same directory as the given dump file, but | |
152 // with a .txt extension. Stores the path of the text file created in the | |
153 // custom_info_filepath parameter. | |
154 // TODO(omaha): Move this functionality to breakpad. All the information | |
155 // needed to write custom information file is known when the dump is generated | |
156 // and hence breakpad could as easily create the text file. | |
157 static HRESULT CreateCustomInfoFile( | |
158 const CString& dump_file, | |
159 const google_breakpad::CustomClientInfo& client_info, | |
160 CString* custom_info_filepath); | |
161 | |
162 // Sends a crash report. If sent successfully, report_id contains the | |
163 // report id generated by the crash server. | |
164 static HRESULT DoSendCrashReport(bool can_upload, | |
165 bool is_out_of_process, | |
166 const CString& crash_filename, | |
167 const ParameterMap& parameters, | |
168 CString* report_id); | |
169 | |
170 // Callback function to run after the minidump has been written. | |
171 static bool MinidumpCallback(const wchar_t* dump_path, | |
172 const wchar_t* minidump_id, | |
173 void* context, | |
174 EXCEPTION_POINTERS* exinfo, | |
175 MDRawAssertionInfo* assertion, | |
176 bool succeeded); | |
177 | |
178 // Start an instance of /report. | |
179 static void StartReportCrash(bool is_interactive, | |
180 const CString& crash_filename); | |
181 | |
182 // Returns true if the crash has happened in an Omaha process which | |
183 // has a top level window up. | |
184 static bool IsInteractive(); | |
185 | |
186 // Returns the "prod" product name if found in the map or a default, | |
187 // constant string otherwise. | |
188 static CString GetProductName(const ParameterMap& parameters); | |
189 | |
190 // Updates the crash metrics after uploading the crash. | |
191 static void UpdateCrashUploadMetrics(bool is_out_of_process, HRESULT hr); | |
192 | |
193 // Uploads the crash, logs the result of the crash upload, and updates | |
194 // the crash metrics. | |
195 static HRESULT UploadCrash(bool is_out_of_process, | |
196 const CString& crash_filename, | |
197 const ParameterMap& parameters, | |
198 CString* report_id); | |
199 | |
200 // Creates a back up copy of the current crash for future debugging use cases. | |
201 static HRESULT SaveLastCrash(const CString& crash_filename, | |
202 const CString& product_name); | |
203 | |
204 // Cleans up stale crashes from the crash dir. Curently, crashes older than | |
205 // 1 day are deleted. | |
206 static HRESULT CleanStaleCrashes(); | |
207 | |
208 // Retrieves the minidump exception information from the minidump file. | |
209 static HRESULT GetExceptionInfo(const CString& crash_filename, | |
210 MINIDUMP_EXCEPTION* ex_info); | |
211 | |
212 // Receives a top-level window and sets the param to true if the window | |
213 // belongs to this process. | |
214 static BOOL CALLBACK EnumWindowsCallback(HWND hwnd, LPARAM param); | |
215 | |
216 // Callback function to run when an exception is passing through an | |
217 // exception barrier. | |
218 static void __stdcall EBHandler(EXCEPTION_POINTERS* ptrs); | |
219 | |
220 // Callback function to run when a new client connects to the crash server. | |
221 static void _cdecl ClientConnectedCallback( | |
222 void* context, | |
223 const google_breakpad::ClientInfo* client_info); | |
224 | |
225 // Callback function to run when a client signals a crash to the crash server. | |
226 static void _cdecl ClientCrashedCallback( | |
227 void* context, | |
228 const google_breakpad::ClientInfo* client_info, | |
229 const std::wstring* dump_path); | |
230 | |
231 // Callback function to run when a client disconnects from the crash server. | |
232 static void _cdecl ClientExitedCallback( | |
233 void* context, | |
234 const google_breakpad::ClientInfo* client_info); | |
235 | |
236 // Given an empty CSecurityDesc, creates a low integrity sacl within it. | |
237 static HRESULT CreateLowIntegrityDesc(CSecurityDesc* sd); | |
238 | |
239 // Builds a security DACL to allow user processes to connect to the crash | |
240 // server named pipe, and sets the DACL on the CSecurityDesc. | |
241 static bool AddPipeSecurityDaclToDesc(bool is_machine, CSecurityDesc* sd); | |
242 | |
243 // Builds a security attribute to allow user processes including low integrity | |
244 // to connect to the crash server named pipe. | |
245 static bool BuildPipeSecurityAttributes(bool is_machine, | |
246 CSecurityAttributes* sa); | |
247 | |
248 // Builds a security attribute to allow full control for the Local System | |
249 // account and read/execute for the Administrators group, when the crash | |
250 // handler is running as Local System. | |
251 static bool BuildCrashDirSecurityAttributes(CSecurityAttributes* sa); | |
252 | |
253 // TODO(omaha): fix static instances of class type not allowed. | |
254 static CString module_filename_; | |
255 static CString Crash::crash_dir_; | |
256 static CString Crash::checkpoint_file_; | |
257 static CString version_postfix_; | |
258 | |
259 static CString crash_report_url_; | |
260 static int max_reports_per_day_; | |
261 static google_breakpad::ExceptionHandler* exception_handler_; | |
262 static google_breakpad::CrashGenerationServer* crash_server_; | |
263 | |
264 static bool is_machine_; | |
265 | |
266 static const int kCrashReportAttempts = 3; | |
267 static const int kCrashReportResendPeriodMs = 1 * 60 * 60 * 1000; // 1 hour. | |
268 | |
269 // Default string to report out-of-process crashes with in the case | |
270 // 'prod' information is not available. | |
271 static const TCHAR* const kDefaultProductName; | |
272 | |
273 friend class CrashTest; | |
274 | |
275 FRIEND_TEST(CrashTest, CleanStaleCrashes); | |
276 FRIEND_TEST(CrashTest, CreateCustomInfoFile); | |
277 FRIEND_TEST(CrashTest, GetExceptionInfo); | |
278 FRIEND_TEST(CrashTest, GetProductName); | |
279 FRIEND_TEST(CrashTest, InstallCrashHandler); | |
280 FRIEND_TEST(CrashTest, IsCrashReportProcess); | |
281 FRIEND_TEST(CrashTest, Report_OmahaCrash); | |
282 FRIEND_TEST(CrashTest, Report_ProductCrash); | |
283 FRIEND_TEST(CrashTest, SaveLastCrash); | |
284 FRIEND_TEST(CrashTest, StartServer); | |
285 FRIEND_TEST(CrashTest, WriteMinidump); | |
286 | |
287 DISALLOW_IMPLICIT_CONSTRUCTORS(Crash); | |
288 }; | |
289 | |
290 } // namespace omaha | |
291 | |
292 #endif // OMAHA_GOOPDATE_CRASH_H__ | |
293 | |
OLD | NEW |