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 9namespace { 10 11DWORD kExceptionCode = 12345; 12WPARAM kCrashMsg = 98765; 13 14// A trivial WindowProc that generates an exception. 15LRESULT 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. 24class 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}; 52TestWrappedExceptionFiter* TestWrappedExceptionFiter::s_filter_ = NULL; 53 54} // namespace. 55 56TEST(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