Index: components/crash/app/hard_error_handler_win.cc |
diff --git a/components/crash/app/hard_error_handler_win.cc b/components/crash/app/hard_error_handler_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ee8852297d7e83e05d05c24d8277f53d804d5331 |
--- /dev/null |
+++ b/components/crash/app/hard_error_handler_win.cc |
@@ -0,0 +1,112 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "components/crash/app/hard_error_handler_win.h" |
+ |
+#include <DelayIMP.h> |
+#include <winternl.h> |
+ |
+#include "base/basictypes.h" |
+#include "base/strings/string_util.h" |
+#include "components/crash/app/crash_reporter_client.h" |
+ |
+namespace breakpad { |
+ |
+using crash_reporter::GetCrashReporterClient; |
+ |
+namespace { |
+const DWORD kExceptionModuleNotFound = VcppException(ERROR_SEVERITY_ERROR, |
+ ERROR_MOD_NOT_FOUND); |
+const DWORD kExceptionEntryPtNotFound = VcppException(ERROR_SEVERITY_ERROR, |
+ ERROR_PROC_NOT_FOUND); |
+// This is defined in <ntstatus.h> but we can't include this file here. |
+const DWORD FACILITY_GRAPHICS_KERNEL = 0x1E; |
+const DWORD NT_STATUS_ENTRYPOINT_NOT_FOUND = 0xC0000139; |
+const DWORD NT_STATUS_DLL_NOT_FOUND = 0xC0000135; |
+ |
+// We assume that exception codes are NT_STATUS codes. |
+DWORD FacilityFromException(DWORD exception_code) { |
+ return (exception_code >> 16) & 0x0FFF; |
+} |
+ |
+// This is not a generic function. It only works with some |nt_status| values. |
+// Check the strings here http://msdn.microsoft.com/en-us/library/cc704588.aspx |
+// before attempting to use this function. |
+void RaiseHardErrorMsg(long nt_status, const std::string& p1, |
+ const std::string& p2) { |
+ // If headless just exit silently. |
+ if (GetCrashReporterClient()->IsRunningUnattended()) |
+ return; |
+ |
+ HMODULE ntdll = ::GetModuleHandleA("NTDLL.DLL"); |
+ wchar_t* msg_template = NULL; |
+ size_t count = ::FormatMessage( |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | |
+ FORMAT_MESSAGE_FROM_HMODULE, |
+ ntdll, |
+ nt_status, |
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
+ reinterpret_cast<wchar_t*>(&msg_template), |
+ 0, |
+ NULL); |
+ |
+ if (!count) |
+ return; |
+ count += p1.size() + p2.size() + 1; |
+ base::string16 message; |
+ ::wsprintf(base::WriteInto(&message, count), msg_template, |
+ p1.c_str(), p2.c_str()); |
+ // The MB_SERVICE_NOTIFICATION causes this message to be displayed by |
+ // csrss. This means that we are not creating windows or pumping WM messages |
+ // in this process. |
+ ::MessageBox(NULL, message.c_str(), |
+ L"chrome.exe", |
+ MB_OK | MB_SERVICE_NOTIFICATION); |
+ ::LocalFree(msg_template); |
+} |
+ |
+void ModuleNotFoundHardError(const EXCEPTION_RECORD* ex_record) { |
+ DelayLoadInfo* dli = reinterpret_cast<DelayLoadInfo*>( |
+ ex_record->ExceptionInformation[0]); |
+ if (!dli->szDll) |
+ return; |
+ RaiseHardErrorMsg(NT_STATUS_DLL_NOT_FOUND, dli->szDll, std::string()); |
+} |
+ |
+void EntryPointNotFoundHardError(const EXCEPTION_RECORD* ex_record) { |
+ DelayLoadInfo* dli = reinterpret_cast<DelayLoadInfo*>( |
+ ex_record->ExceptionInformation[0]); |
+ if (!dli->dlp.fImportByName) |
+ return; |
+ if (!dli->dlp.szProcName) |
+ return; |
+ if (!dli->szDll) |
+ return; |
+ RaiseHardErrorMsg(NT_STATUS_ENTRYPOINT_NOT_FOUND, |
+ dli->dlp.szProcName, dli->szDll); |
+} |
+ |
+} // namespace |
+ |
+bool HardErrorHandler(EXCEPTION_POINTERS* ex_info) { |
+ if (!ex_info) |
+ return false; |
+ if (!ex_info->ExceptionRecord) |
+ return false; |
+ |
+ long exception = ex_info->ExceptionRecord->ExceptionCode; |
+ if (exception == kExceptionModuleNotFound) { |
+ ModuleNotFoundHardError(ex_info->ExceptionRecord); |
+ return true; |
+ } else if (exception == kExceptionEntryPtNotFound) { |
+ EntryPointNotFoundHardError(ex_info->ExceptionRecord); |
+ return true; |
+ } else if (FacilityFromException(exception) == FACILITY_GRAPHICS_KERNEL) { |
+ RaiseHardErrorMsg(exception, std::string(), std::string()); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+} // namespace breakpad |