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/breakpad/app/hard_error_handler_win.h"
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
15 #include "base/basictypes.h"
16 #include "base/strings/string_util.h"
17 #include "components/breakpad/app/breakpad_client.h"
22 const DWORD kExceptionModuleNotFound
= VcppException(ERROR_SEVERITY_ERROR
,
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;
31 // We assume that exception codes are NT_STATUS codes.
32 DWORD
FacilityFromException(DWORD exception_code
) {
33 return (exception_code
>> 16) & 0x0FFF;
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())
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
,
52 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
53 reinterpret_cast<wchar_t*>(&msg_template
),
59 count
+= p1
.size() + p2
.size() + 1;
60 base::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
65 ::MessageBox(NULL
, message
.c_str(),
67 MB_OK
| MB_SERVICE_NOTIFICATION
);
68 ::LocalFree(msg_template
);
71 void ModuleNotFoundHardError(const EXCEPTION_RECORD
* ex_record
) {
72 DelayLoadInfo
* dli
= reinterpret_cast<DelayLoadInfo
*>(
73 ex_record
->ExceptionInformation
[0]);
76 RaiseHardErrorMsg(NT_STATUS_DLL_NOT_FOUND
, dli
->szDll
, std::string());
79 void EntryPointNotFoundHardError(const EXCEPTION_RECORD
* ex_record
) {
80 DelayLoadInfo
* dli
= reinterpret_cast<DelayLoadInfo
*>(
81 ex_record
->ExceptionInformation
[0]);
82 if (!dli
->dlp
.fImportByName
)
84 if (!dli
->dlp
.szProcName
)
88 RaiseHardErrorMsg(NT_STATUS_ENTRYPOINT_NOT_FOUND
,
89 dli
->dlp
.szProcName
, dli
->szDll
);
94 bool HardErrorHandler(EXCEPTION_POINTERS
* ex_info
) {
97 if (!ex_info
->ExceptionRecord
)
100 long exception
= ex_info
->ExceptionRecord
->ExceptionCode
;
101 if (exception
== kExceptionModuleNotFound
) {
102 ModuleNotFoundHardError(ex_info
->ExceptionRecord
);
104 } else if (exception
== kExceptionEntryPtNotFound
) {
105 EntryPointNotFoundHardError(ex_info
->ExceptionRecord
);
107 } else if (FacilityFromException(exception
) == FACILITY_GRAPHICS_KERNEL
) {
108 #if defined(USE_AURA)
109 RaiseHardErrorMsg(exception
, std::string(), std::string());
118 } // namespace breakpad