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