// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/win/wrapped_window_proc.h" #include "base/message_loop.h" #include "testing/gtest/include/gtest/gtest.h" namespace { DWORD kExceptionCode = 12345; WPARAM kCrashMsg = 98765; // A trivial WindowProc that generates an exception. LRESULT CALLBACK TestWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { if (message == kCrashMsg) RaiseException(kExceptionCode, 0, 0, NULL); return DefWindowProc(hwnd, message, wparam, lparam); } // This class implements an exception filter that can be queried about a past // exception. class TestWrappedExceptionFiter { public: TestWrappedExceptionFiter() : called_(false) { EXPECT_FALSE(s_filter_); s_filter_ = this; } ~TestWrappedExceptionFiter() { EXPECT_EQ(s_filter_, this); s_filter_ = NULL; } bool called() { return called_; } // The actual exception filter just records the exception. static int Filter(EXCEPTION_POINTERS* info) { EXPECT_FALSE(s_filter_->called_); if (info->ExceptionRecord->ExceptionCode == kExceptionCode) s_filter_->called_ = true; return EXCEPTION_EXECUTE_HANDLER; } private: bool called_; static TestWrappedExceptionFiter* s_filter_; }; TestWrappedExceptionFiter* TestWrappedExceptionFiter::s_filter_ = NULL; } // namespace. TEST(WrappedWindowProc, CatchesExceptions) { HINSTANCE hinst = GetModuleHandle(NULL); std::wstring class_name(L"TestClass"); WNDCLASS wc = {0}; wc.lpfnWndProc = base::win::WrappedWindowProc; wc.hInstance = hinst; wc.lpszClassName = class_name.c_str(); RegisterClass(&wc); HWND window = CreateWindow(class_name.c_str(), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, 0); ASSERT_TRUE(window); // Before generating the exception we make sure that the filter will see it. TestWrappedExceptionFiter wrapper; base::win::WinProcExceptionFilter old_filter = base::win::SetWinProcExceptionFilter(TestWrappedExceptionFiter::Filter); SendMessage(window, kCrashMsg, 0, 0); EXPECT_TRUE(wrapper.called()); base::win::SetWinProcExceptionFilter(old_filter); }