Return backed up TemplateURL on default search change
[chromium-blink-merge.git] / chrome / app / hard_error_handler_win.cc
blob26c64ff49d730f232567263605d1d14274d42c1c
1 // Copyright (c) 2009 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 "chrome/app/hard_error_handler_win.h"
7 #include <delayimp.h>
8 #include <ntsecapi.h>
9 #include <string>
11 #include "base/basictypes.h"
12 #include "base/logging.h"
13 #include "base/string_piece.h"
14 #include "base/sys_string_conversions.h"
16 namespace {
18 const int32 kExceptionModuleNotFound = VcppException(ERROR_SEVERITY_ERROR,
19 ERROR_MOD_NOT_FOUND);
20 const int32 kExceptionEntryPtNotFound = VcppException(ERROR_SEVERITY_ERROR,
21 ERROR_PROC_NOT_FOUND);
23 const int32 NT_STATUS_ENTRYPOINT_NOT_FOUND = 0xC0000139;
24 const int32 NT_STATUS_DLL_NOT_FOUND = 0xC0000135;
26 bool MakeNTUnicodeString(const std::wstring& str,
27 UNICODE_STRING* nt_string) {
28 if (str.empty())
29 return false;
30 size_t str_size_bytes = str.size() * sizeof(wchar_t);
31 if (kuint16max < str_size_bytes) {
32 // The string is too long - nt_string->Length is USHORT
33 NOTREACHED() << "The string is too long";
34 return false;
36 nt_string->Length = static_cast<USHORT>(str_size_bytes);
37 nt_string->MaximumLength = static_cast<USHORT>(str_size_bytes);
38 nt_string->Buffer = const_cast<wchar_t*>(str.c_str());
39 return true;
42 // NT-level function (not a win32 api) used to tell CSRSS of a critical error
43 // in the program which results in a message box dialog.
44 // The |exception| parameter is a standard exception code, the |param_count|
45 // indicates the number of items in |payload_params|. |payload_params| is
46 // dependent on the |exception| type but is typically an array to pointers to
47 // strings. |error_mode| indicates the kind of dialog buttons to show.
48 typedef LONG (WINAPI *NtRaiseHardErrorPF)(LONG exception,
49 ULONG param_count,
50 ULONG undocumented,
51 PVOID payload_params,
52 UINT error_mode,
53 PULONG response);
55 // Helper function to call NtRaiseHardError(). It takes the exception code
56 // and one or two strings which are dependent on the exception code. No
57 // effort is done to validate that they match.
58 void RaiseHardErrorMsg(int32 exception, const std::wstring& text1,
59 const std::wstring& text2) {
60 // Bind the entry point. We can do it here since this function is really
61 // called at most once per session. Usually never called.
62 NtRaiseHardErrorPF NtRaiseHardError =
63 reinterpret_cast<NtRaiseHardErrorPF>(
64 ::GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtRaiseHardError"));
65 if (!NtRaiseHardError)
66 return;
68 UNICODE_STRING uni_str1;
69 UNICODE_STRING uni_str2;
70 // A message needs to be displayed or else it would be confusing to the user.
71 if (!MakeNTUnicodeString(text1, &uni_str1))
72 return;
73 int num_params = 1;
74 // The second string is optional.
75 if (MakeNTUnicodeString(text2, &uni_str2))
76 num_params = 2;
78 UNICODE_STRING* args[] = {&uni_str1, &uni_str2};
79 uint32 undoc_value = 3; // Display message to user.
80 uint32 error_mode = 1; // Display OK button only.
81 ULONG response; // What user clicked in the dialog. Discarded.
82 NtRaiseHardError(exception, num_params, 3, args, error_mode, &response);
85 } // namespace.
87 // Using RaiseHardErrorMsg(), it generates the same message box that is seen
88 // when the loader cannot find a DLL that a module depends on. |module| is the
89 // DLL name and it cannot be empty. The Message box only has an 'ok' button.
90 void ModuleNotFoundHardError(const char* module) {
91 if (!module)
92 return;
93 std::wstring mod_name(base::SysMultiByteToWide(module, CP_ACP));
94 RaiseHardErrorMsg(NT_STATUS_DLL_NOT_FOUND, mod_name, std::wstring());
97 // Using RaiseHardErrorMsg(), it generates the same message box that seen
98 // when the loader cannot find an import a module depends on. |module| is the
99 // DLL name and it cannot be empty. |entry| is the name of the method that
100 // could not be found. The Message box only has an 'ok' button.
101 void EntryPointNotFoundHardError(const char* entry, const char* module) {
102 if (!module || !entry)
103 return;
104 std::wstring entry_point(base::SysMultiByteToWide(entry, CP_ACP));
105 std::wstring mod_name(base::SysMultiByteToWide(module, CP_ACP));
106 RaiseHardErrorMsg(NT_STATUS_ENTRYPOINT_NOT_FOUND, entry_point, mod_name);
109 bool DelayLoadFailureExceptionMessageBox(EXCEPTION_POINTERS* ex_info) {
110 if (!ex_info)
111 return false;
112 DelayLoadInfo* dli = reinterpret_cast<DelayLoadInfo*>(
113 ex_info->ExceptionRecord->ExceptionInformation[0]);
114 if (!dli)
115 return false;
116 if (ex_info->ExceptionRecord->ExceptionCode == kExceptionModuleNotFound) {
117 ModuleNotFoundHardError(dli->szDll);
118 return true;
120 if (ex_info->ExceptionRecord->ExceptionCode == kExceptionEntryPtNotFound) {
121 if (dli->dlp.fImportByName) {
122 EntryPointNotFoundHardError(dli->dlp.szProcName, dli->szDll);
123 return true;
126 return false;