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"
10 #include "base/basictypes.h"
11 #include "base/strings/string_util.h"
12 #include "components/crash/app/crash_reporter_client.h"
16 using crash_reporter::GetCrashReporterClient
;
19 const DWORD kExceptionModuleNotFound
= VcppException(ERROR_SEVERITY_ERROR
,
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())
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
,
49 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
50 reinterpret_cast<wchar_t*>(&msg_template
),
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
63 ::MessageBox(NULL
, message
.c_str(),
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]);
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
)
82 if (!dli
->dlp
.szProcName
)
86 RaiseHardErrorMsg(NT_STATUS_ENTRYPOINT_NOT_FOUND
,
87 dli
->dlp
.szProcName
, dli
->szDll
);
92 bool HardErrorHandler(EXCEPTION_POINTERS
* ex_info
) {
95 if (!ex_info
->ExceptionRecord
)
98 long exception
= ex_info
->ExceptionRecord
->ExceptionCode
;
99 if (exception
== kExceptionModuleNotFound
) {
100 ModuleNotFoundHardError(ex_info
->ExceptionRecord
);
102 } else if (exception
== kExceptionEntryPtNotFound
) {
103 EntryPointNotFoundHardError(ex_info
->ExceptionRecord
);
105 } else if (FacilityFromException(exception
) == FACILITY_GRAPHICS_KERNEL
) {
106 RaiseHardErrorMsg(exception
, std::string(), std::string());
112 } // namespace breakpad