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