Ensure low-memory renderers retry failed loads correctly.
[chromium-blink-merge.git] / components / crash / app / hard_error_handler_win.cc
blobee8852297d7e83e05d05c24d8277f53d804d5331
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.
5 #include "components/crash/app/hard_error_handler_win.h"
7 #include <DelayIMP.h>
8 #include <winternl.h>
10 #include "base/basictypes.h"
11 #include "base/strings/string_util.h"
12 #include "components/crash/app/crash_reporter_client.h"
14 namespace breakpad {
16 using crash_reporter::GetCrashReporterClient;
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;
28 // We assume that exception codes are NT_STATUS codes.
29 DWORD FacilityFromException(DWORD exception_code) {
30 return (exception_code >> 16) & 0x0FFF;
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;
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),
52 NULL);
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);
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());
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);
90 } // namespace
92 bool HardErrorHandler(EXCEPTION_POINTERS* ex_info) {
93 if (!ex_info)
94 return false;
95 if (!ex_info->ExceptionRecord)
96 return false;
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;
109 return false;
112 } // namespace breakpad