1 // Copyright 2011 The Chromium Authors
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 "base/win/wrapped_window_proc.h"
6 #include "testing/gtest/include/gtest/gtest.h"
7
8 namespace {
9
10 DWORD kExceptionCode = 12345;
11 WPARAM kCrashMsg = 98765;
12
13 // A trivial WindowProc that generates an exception.
TestWindowProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)14 LRESULT CALLBACK TestWindowProc(HWND hwnd,
15 UINT message,
16 WPARAM wparam,
17 LPARAM lparam) {
18 if (message == kCrashMsg)
19 RaiseException(kExceptionCode, 0, 0, nullptr);
20 return DefWindowProc(hwnd, message, wparam, lparam);
21 }
22
23 // This class implements an exception filter that can be queried about a past
24 // exception.
25 class TestWrappedExceptionFiter {
26 public:
TestWrappedExceptionFiter()27 TestWrappedExceptionFiter() {
28 EXPECT_FALSE(s_filter_);
29 s_filter_ = this;
30 }
31
~TestWrappedExceptionFiter()32 ~TestWrappedExceptionFiter() {
33 EXPECT_EQ(s_filter_, this);
34 s_filter_ = nullptr;
35 }
36
called()37 bool called() { return called_; }
38
39 // The actual exception filter just records the exception.
Filter(EXCEPTION_POINTERS * info)40 static int Filter(EXCEPTION_POINTERS* info) {
41 EXPECT_FALSE(s_filter_->called_);
42 if (info->ExceptionRecord->ExceptionCode == kExceptionCode)
43 s_filter_->called_ = true;
44 return EXCEPTION_EXECUTE_HANDLER;
45 }
46
47 private:
48 bool called_ = false;
49 static TestWrappedExceptionFiter* s_filter_;
50 };
51 TestWrappedExceptionFiter* TestWrappedExceptionFiter::s_filter_ = nullptr;
52
53 } // namespace.
54
TEST(WrappedWindowProc,CatchesExceptions)55 TEST(WrappedWindowProc, CatchesExceptions) {
56 HINSTANCE hinst = GetModuleHandle(nullptr);
57 std::wstring class_name(L"TestClass");
58
59 WNDCLASS wc = {0};
60 wc.lpfnWndProc = base::win::WrappedWindowProc<TestWindowProc>;
61 wc.hInstance = hinst;
62 wc.lpszClassName = class_name.c_str();
63 RegisterClass(&wc);
64
65 HWND window = CreateWindow(class_name.c_str(), nullptr, 0, 0, 0, 0, 0,
66 HWND_MESSAGE, nullptr, hinst, nullptr);
67 ASSERT_TRUE(window);
68
69 // Before generating the exception we make sure that the filter will see it.
70 TestWrappedExceptionFiter wrapper;
71 base::win::WinProcExceptionFilter old_filter =
72 base::win::SetWinProcExceptionFilter(TestWrappedExceptionFiter::Filter);
73
74 SendMessage(window, kCrashMsg, 0, 0);
75 EXPECT_TRUE(wrapper.called());
76
77 base::win::SetWinProcExceptionFilter(old_filter);
78 }
79