| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/breakpad/hard_error_handler_win.h" | |
| 6 | |
| 7 #if defined(_WIN32_WINNT_WIN8) && _MSC_VER < 1700 | |
| 8 // The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h, and in | |
| 9 // delayimp.h previous to VS2012. | |
| 10 #undef FACILITY_VISUALCPP | |
| 11 #endif | |
| 12 #include <DelayIMP.h> | |
| 13 #include <winternl.h> | |
| 14 | |
| 15 #include "base/basictypes.h" | |
| 16 #include "base/strings/string_util.h" | |
| 17 #include "components/breakpad/breakpad_client.h" | |
| 18 | |
| 19 namespace breakpad { | |
| 20 | |
| 21 namespace { | |
| 22 const DWORD kExceptionModuleNotFound = VcppException(ERROR_SEVERITY_ERROR, | |
| 23 ERROR_MOD_NOT_FOUND); | |
| 24 const DWORD kExceptionEntryPtNotFound = VcppException(ERROR_SEVERITY_ERROR, | |
| 25 ERROR_PROC_NOT_FOUND); | |
| 26 // This is defined in <ntstatus.h> but we can't include this file here. | |
| 27 const DWORD FACILITY_GRAPHICS_KERNEL = 0x1E; | |
| 28 const DWORD NT_STATUS_ENTRYPOINT_NOT_FOUND = 0xC0000139; | |
| 29 const DWORD NT_STATUS_DLL_NOT_FOUND = 0xC0000135; | |
| 30 | |
| 31 // We assume that exception codes are NT_STATUS codes. | |
| 32 DWORD FacilityFromException(DWORD exception_code) { | |
| 33 return (exception_code >> 16) & 0x0FFF; | |
| 34 } | |
| 35 | |
| 36 // This is not a generic function. It only works with some |nt_status| values. | |
| 37 // Check the strings here http://msdn.microsoft.com/en-us/library/cc704588.aspx | |
| 38 // before attempting to use this function. | |
| 39 void RaiseHardErrorMsg(long nt_status, const std::string& p1, | |
| 40 const std::string& p2) { | |
| 41 // If headless just exit silently. | |
| 42 if (GetBreakpadClient()->IsRunningUnattended()) | |
| 43 return; | |
| 44 | |
| 45 HMODULE ntdll = ::GetModuleHandleA("NTDLL.DLL"); | |
| 46 wchar_t* msg_template = NULL; | |
| 47 size_t count = ::FormatMessage( | |
| 48 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | | |
| 49 FORMAT_MESSAGE_FROM_HMODULE, | |
| 50 ntdll, | |
| 51 nt_status, | |
| 52 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
| 53 reinterpret_cast<wchar_t*>(&msg_template), | |
| 54 0, | |
| 55 NULL); | |
| 56 | |
| 57 if (!count) | |
| 58 return; | |
| 59 count += p1.size() + p2.size() + 1; | |
| 60 string16 message; | |
| 61 ::wsprintf(WriteInto(&message, count), msg_template, p1.c_str(), p2.c_str()); | |
| 62 // The MB_SERVICE_NOTIFICATION causes this message to be displayed by | |
| 63 // csrss. This means that we are not creating windows or pumping WM messages | |
| 64 // in this process. | |
| 65 ::MessageBox(NULL, message.c_str(), | |
| 66 L"chrome.exe", | |
| 67 MB_OK | MB_SERVICE_NOTIFICATION); | |
| 68 ::LocalFree(msg_template); | |
| 69 } | |
| 70 | |
| 71 void ModuleNotFoundHardError(const EXCEPTION_RECORD* ex_record) { | |
| 72 DelayLoadInfo* dli = reinterpret_cast<DelayLoadInfo*>( | |
| 73 ex_record->ExceptionInformation[0]); | |
| 74 if (!dli->szDll) | |
| 75 return; | |
| 76 RaiseHardErrorMsg(NT_STATUS_DLL_NOT_FOUND, dli->szDll, std::string()); | |
| 77 } | |
| 78 | |
| 79 void EntryPointNotFoundHardError(const EXCEPTION_RECORD* ex_record) { | |
| 80 DelayLoadInfo* dli = reinterpret_cast<DelayLoadInfo*>( | |
| 81 ex_record->ExceptionInformation[0]); | |
| 82 if (!dli->dlp.fImportByName) | |
| 83 return; | |
| 84 if (!dli->dlp.szProcName) | |
| 85 return; | |
| 86 if (!dli->szDll) | |
| 87 return; | |
| 88 RaiseHardErrorMsg(NT_STATUS_ENTRYPOINT_NOT_FOUND, | |
| 89 dli->dlp.szProcName, dli->szDll); | |
| 90 } | |
| 91 | |
| 92 } // namespace | |
| 93 | |
| 94 bool HardErrorHandler(EXCEPTION_POINTERS* ex_info) { | |
| 95 if (!ex_info) | |
| 96 return false; | |
| 97 if (!ex_info->ExceptionRecord) | |
| 98 return false; | |
| 99 | |
| 100 long exception = ex_info->ExceptionRecord->ExceptionCode; | |
| 101 if (exception == kExceptionModuleNotFound) { | |
| 102 ModuleNotFoundHardError(ex_info->ExceptionRecord); | |
| 103 return true; | |
| 104 } else if (exception == kExceptionEntryPtNotFound) { | |
| 105 EntryPointNotFoundHardError(ex_info->ExceptionRecord); | |
| 106 return true; | |
| 107 } else if (FacilityFromException(exception) == FACILITY_GRAPHICS_KERNEL) { | |
| 108 #if defined(USE_AURA) | |
| 109 RaiseHardErrorMsg(exception, std::string(), std::string()); | |
| 110 return true; | |
| 111 #else | |
| 112 return false; | |
| 113 #endif | |
| 114 } | |
| 115 return false; | |
| 116 } | |
| 117 | |
| 118 } // namespace breakpad | |
| OLD | NEW |