| 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 |