Import Cobalt 24.master.0.1033952
diff --git a/ui/gfx/win/DEPS b/ui/gfx/win/DEPS
new file mode 100644
index 0000000..99162b4
--- /dev/null
+++ b/ui/gfx/win/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/crash",
+]
diff --git a/ui/gfx/win/OWNERS b/ui/gfx/win/OWNERS
new file mode 100644
index 0000000..6ef3395
--- /dev/null
+++ b/ui/gfx/win/OWNERS
@@ -0,0 +1,4 @@
+# For any other files, defer to ui/gfx/OWNERS.
+
+# Direct Write, fonts and related classes.
+per-file direct_write*=etienneb@chromium.org
diff --git a/ui/gfx/win/crash_id_helper.cc b/ui/gfx/win/crash_id_helper.cc
new file mode 100644
index 0000000..5cbf920
--- /dev/null
+++ b/ui/gfx/win/crash_id_helper.cc
@@ -0,0 +1,80 @@
+// Copyright 2019 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 "ui/gfx/win/crash_id_helper.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_util.h"
+
+namespace gfx {
+
+// static
+CrashIdHelper* CrashIdHelper::Get() {
+  static base::NoDestructor<CrashIdHelper> helper;
+  return helper.get();
+}
+
+// static
+void CrashIdHelper::RegisterMainThread(base::PlatformThreadId thread_id) {
+  main_thread_id_ = thread_id;
+}
+
+CrashIdHelper::ScopedLogger::~ScopedLogger() {
+  CrashIdHelper::Get()->OnDidProcessMessages();
+}
+
+CrashIdHelper::ScopedLogger::ScopedLogger() = default;
+
+std::unique_ptr<CrashIdHelper::ScopedLogger>
+CrashIdHelper::OnWillProcessMessages(const std::string& id) {
+  if (main_thread_id_ == base::kInvalidThreadId ||
+      base::PlatformThread::CurrentId() != main_thread_id_) {
+    return nullptr;
+  }
+
+  if (!ids_.empty())
+    was_nested_ = true;
+  ids_.push_back(id.empty() ? "unspecified" : id);
+  debugging_crash_key_.Set(CurrentCrashId());
+  // base::WrapUnique() as constructor is private.
+  return base::WrapUnique(new ScopedLogger);
+}
+
+void CrashIdHelper::OnDidProcessMessages() {
+  DCHECK(!ids_.empty());
+  ids_.pop_back();
+  if (ids_.empty()) {
+    debugging_crash_key_.Clear();
+    was_nested_ = false;
+  } else {
+    debugging_crash_key_.Set(CurrentCrashId());
+  }
+}
+
+CrashIdHelper::CrashIdHelper() = default;
+
+CrashIdHelper::~CrashIdHelper() = default;
+
+std::string CrashIdHelper::CurrentCrashId() const {
+  // This should only be called when there is at least one id.
+  DCHECK(!ids_.empty());
+  // Common case is only one id.
+  if (ids_.size() == 1) {
+    // If the size of |ids_| is 1, then the message loop is not nested. If
+    // |was_nested_| is true, it means in processing the message corresponding
+    // to ids_[0] another message was processed, resulting in nested message
+    // loops.  A nested message loop can lead to reentrancy and/or problems when
+    // the stack unravels. For example, it's entirely possible that when a
+    // nested message loop completes, objects further up in the stack have been
+    // deleted. "(N)" is added to signify that a nested message loop was run at
+    // some point during the current message loop.
+    return was_nested_ ? "(N) " + ids_[0] : ids_[0];
+  }
+  return base::JoinString(ids_, ">");
+}
+
+// static
+base::PlatformThreadId CrashIdHelper::main_thread_id_ = base::kInvalidThreadId;
+
+}  // namespace gfx
diff --git a/ui/gfx/win/crash_id_helper.h b/ui/gfx/win/crash_id_helper.h
new file mode 100644
index 0000000..649e203
--- /dev/null
+++ b/ui/gfx/win/crash_id_helper.h
@@ -0,0 +1,90 @@
+// Copyright 2019 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.
+
+#ifndef UI_GFX_WIN_CRASH_ID_HELPER_H_
+#define UI_GFX_WIN_CRASH_ID_HELPER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/no_destructor.h"
+#include "base/threading/platform_thread.h"
+#include "components/crash/core/common/crash_key.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+// CrashIdHelper is used to log (in crash dumps) the id(s) of the window/widget
+// currently dispatching an event. Often times crashes occur purely in ui
+// code, while the bug lies in client code. Logging an id helps better identify
+// the client code that created the window/widget.
+//
+// This class only logs ids on the thread identified by RegisterMainThread().
+//
+// Example usage:
+// {
+//   auto logger = CrashIdHelper::Get()->OnWillProcessMessages(crash_id);
+//   <do message processing>
+// }
+class GFX_EXPORT CrashIdHelper {
+ public:
+  static CrashIdHelper* Get();
+
+  CrashIdHelper(const CrashIdHelper&) = delete;
+  CrashIdHelper& operator=(const CrashIdHelper&) = delete;
+
+  // Registers the thread used for logging.
+  static void RegisterMainThread(base::PlatformThreadId thread_id);
+
+  // RAII style class that unregisters in the destructor.
+  class GFX_EXPORT ScopedLogger {
+   public:
+    ScopedLogger(const ScopedLogger&) = delete;
+    ScopedLogger& operator=(const ScopedLogger&) = delete;
+
+    ~ScopedLogger();
+
+   private:
+    friend class CrashIdHelper;
+    ScopedLogger();
+  };
+
+  // Adds |id| to the list of active debugging ids. When the returned object
+  // is destroyed, |id| is removed from the list of active debugging ids.
+  // Returns null if logging is not enabled on the current thread.
+  std::unique_ptr<ScopedLogger> OnWillProcessMessages(const std::string& id);
+
+ private:
+  friend base::NoDestructor<CrashIdHelper>;
+  friend class CrashIdHelperTest;
+
+  CrashIdHelper();
+  ~CrashIdHelper();
+
+  // Called from ~ScopedLogger. Removes the most recently added id.
+  void OnDidProcessMessages();
+
+  // Returns the identifier to put in the crash key.
+  std::string CurrentCrashId() const;
+
+  // Ordered list of debugging identifiers added.
+  std::vector<std::string> ids_;
+
+  // Set to true once |ids_| has more than one object, and false once |ids_| is
+  // empty. That is, this is true once processing the windows message resulted
+  // in processing another windows message (nested message loops). See comment
+  // in implementation of CurrentCrashId() as to why this is tracked.
+  bool was_nested_ = false;
+
+  // This uses the name 'widget' as this code is most commonly triggered from
+  // views, which uses the term Widget.
+  crash_reporter::CrashKeyString<128> debugging_crash_key_{"widget-id"};
+
+  static base::PlatformThreadId main_thread_id_;
+};
+
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_CRASH_ID_HELPER_H_
diff --git a/ui/gfx/win/crash_id_helper_unittest.cc b/ui/gfx/win/crash_id_helper_unittest.cc
new file mode 100644
index 0000000..5e3e509
--- /dev/null
+++ b/ui/gfx/win/crash_id_helper_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2019 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 "ui/gfx/win/crash_id_helper.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gfx {
+
+class CrashIdHelperTest : public testing::Test {
+ public:
+  CrashIdHelperTest() = default;
+
+  CrashIdHelperTest(const CrashIdHelperTest&) = delete;
+  CrashIdHelperTest& operator=(const CrashIdHelperTest&) = delete;
+
+  ~CrashIdHelperTest() override = default;
+
+  std::string CurrentCrashId() {
+    return CrashIdHelper::Get()->CurrentCrashId();
+  }
+};
+
+// This test verifies CurrentCrashId(). Ideally this would verify at
+// crash_reporter::CrashKeyString, but that class isn't particularly test
+// friendly (and the implementation varies depending upon compile time flags).
+TEST_F(CrashIdHelperTest, Basic) {
+  CrashIdHelper::RegisterMainThread(base::PlatformThread::CurrentId());
+
+  const std::string id1 = "id";
+  {
+    auto scoper = CrashIdHelper::Get()->OnWillProcessMessages(id1);
+    EXPECT_EQ(id1, CurrentCrashId());
+  }
+
+  // No assertions for empty as CurrentCrashId() DCHECKs there is at least
+  // one id.
+
+  const std::string id2 = "id2";
+  {
+    auto scoper = CrashIdHelper::Get()->OnWillProcessMessages(id2);
+    EXPECT_EQ(id2, CurrentCrashId());
+
+    {
+      auto scoper2 = CrashIdHelper::Get()->OnWillProcessMessages(id1);
+      EXPECT_EQ("id2>id", CurrentCrashId());
+    }
+    EXPECT_EQ("(N) id2", CurrentCrashId());
+  }
+  CrashIdHelper::RegisterMainThread(base::kInvalidThreadId);
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/win/direct_write.cc b/ui/gfx/win/direct_write.cc
new file mode 100644
index 0000000..fc7356b
--- /dev/null
+++ b/ui/gfx/win/direct_write.cc
@@ -0,0 +1,176 @@
+// Copyright 2014 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 "ui/gfx/win/direct_write.h"
+
+#include <wrl/client.h>
+
+#include <string>
+
+#include "base/debug/alias.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
+#include "base/win/windows_version.h"
+#include "skia/ext/fontmgr_default.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
+#include "third_party/skia/include/ports/SkTypeface_win.h"
+
+namespace gfx {
+namespace win {
+
+namespace {
+
+// Pointer to the global IDWriteFactory interface.
+IDWriteFactory* g_direct_write_factory = nullptr;
+
+void SetDirectWriteFactory(IDWriteFactory* factory) {
+  DCHECK(!g_direct_write_factory);
+  // We grab a reference on the DirectWrite factory. This reference is
+  // leaked, which is ok because skia leaks it as well.
+  factory->AddRef();
+  g_direct_write_factory = factory;
+}
+
+}  // anonymous namespace
+
+void CreateDWriteFactory(IDWriteFactory** factory) {
+  Microsoft::WRL::ComPtr<IUnknown> factory_unknown;
+  HRESULT hr =
+      DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
+                          &factory_unknown);
+  if (FAILED(hr)) {
+    base::debug::Alias(&hr);
+    CHECK(false);
+    return;
+  }
+  factory_unknown.CopyTo(factory);
+}
+
+void InitializeDirectWrite() {
+  static bool tried_dwrite_initialize = false;
+  DCHECK(!tried_dwrite_initialize);
+  tried_dwrite_initialize = true;
+
+  TRACE_EVENT0("fonts", "gfx::InitializeDirectWrite");
+  SCOPED_UMA_HISTOGRAM_LONG_TIMER("DirectWrite.Fonts.Gfx.InitializeTime");
+
+  Microsoft::WRL::ComPtr<IDWriteFactory> factory;
+  CreateDWriteFactory(&factory);
+  CHECK(!!factory);
+  SetDirectWriteFactory(factory.Get());
+
+  // The skia call to create a new DirectWrite font manager instance can fail
+  // if we are unable to get the system font collection from the DirectWrite
+  // factory. The GetSystemFontCollection method in the IDWriteFactory
+  // interface fails with E_INVALIDARG on certain Windows 7 gold versions
+  // (6.1.7600.*).
+  sk_sp<SkFontMgr> direct_write_font_mgr =
+      SkFontMgr_New_DirectWrite(factory.Get());
+  int iteration = 0;
+  if (!direct_write_font_mgr &&
+      base::win::GetVersion() == base::win::Version::WIN7) {
+    // Windows (win7_rtm) may fail to map the service sections
+    // (crbug.com/956064).
+    constexpr int kMaxRetries = 5;
+    constexpr base::TimeDelta kRetrySleepTime = base::Microseconds(500);
+    while (iteration < kMaxRetries) {
+      base::PlatformThread::Sleep(kRetrySleepTime);
+      direct_write_font_mgr = SkFontMgr_New_DirectWrite(factory.Get());
+      if (direct_write_font_mgr)
+        break;
+      ++iteration;
+    }
+  }
+  if (!direct_write_font_mgr)
+    iteration = -1;
+  base::UmaHistogramSparse("DirectWrite.Fonts.Gfx.InitializeLoopCount",
+                           iteration);
+  // TODO(crbug.com/956064): Move to a CHECK when the cause of the crash is
+  // fixed and remove the if statement that fallback to GDI font manager.
+  DCHECK(!!direct_write_font_mgr);
+  if (!direct_write_font_mgr)
+    direct_write_font_mgr = SkFontMgr_New_GDI();
+
+  // Override the default skia font manager. This must be called before any
+  // use of the skia font manager is done (e.g. before any call to
+  // SkFontMgr::RefDefault()).
+  skia::OverrideDefaultSkFontMgr(std::move(direct_write_font_mgr));
+}
+
+IDWriteFactory* GetDirectWriteFactory() {
+  // Some unittests may access this accessor without any previous call to
+  // |InitializeDirectWrite|. A call to |InitializeDirectWrite| after this
+  // function being called is still invalid.
+  if (!g_direct_write_factory)
+    InitializeDirectWrite();
+  return g_direct_write_factory;
+}
+
+absl::optional<std::string> RetrieveLocalizedString(
+    IDWriteLocalizedStrings* names,
+    const std::string& locale) {
+  std::wstring locale_wide = base::UTF8ToWide(locale);
+
+  // If locale is empty, index 0 will be used. Otherwise, the locale name must
+  // be found and must exist.
+  UINT32 index = 0;
+  BOOL exists = false;
+  if (!locale.empty() &&
+      (FAILED(names->FindLocaleName(locale_wide.c_str(), &index, &exists)) ||
+       !exists)) {
+    return absl::nullopt;
+  }
+
+  // Get the string length.
+  UINT32 length = 0;
+  if (FAILED(names->GetStringLength(index, &length)))
+    return absl::nullopt;
+
+  // The output buffer length needs to be one larger to receive the NUL
+  // character.
+  std::wstring buffer;
+  buffer.resize(length + 1);
+  if (FAILED(names->GetString(index, &buffer[0], buffer.size())))
+    return absl::nullopt;
+
+  // Shrink the string to fit the actual length.
+  buffer.resize(length);
+
+  return base::WideToUTF8(buffer);
+}
+
+absl::optional<std::string> RetrieveLocalizedFontName(
+    base::StringPiece font_name,
+    const std::string& locale) {
+  Microsoft::WRL::ComPtr<IDWriteFactory> factory;
+  CreateDWriteFactory(&factory);
+
+  Microsoft::WRL::ComPtr<IDWriteFontCollection> font_collection;
+  if (FAILED(factory->GetSystemFontCollection(&font_collection))) {
+    return absl::nullopt;
+  }
+
+  UINT32 index = 0;
+  BOOL exists;
+  std::wstring font_name_wide = base::UTF8ToWide(font_name);
+  if (FAILED(font_collection->FindFamilyName(font_name_wide.c_str(), &index,
+                                             &exists)) ||
+      !exists) {
+    return absl::nullopt;
+  }
+
+  Microsoft::WRL::ComPtr<IDWriteFontFamily> font_family;
+  Microsoft::WRL::ComPtr<IDWriteLocalizedStrings> family_names;
+  if (FAILED(font_collection->GetFontFamily(index, &font_family)) ||
+      FAILED(font_family->GetFamilyNames(&family_names))) {
+    return absl::nullopt;
+  }
+
+  return RetrieveLocalizedString(family_names.Get(), locale);
+}
+
+}  // namespace win
+}  // namespace gfx
diff --git a/ui/gfx/win/direct_write.h b/ui/gfx/win/direct_write.h
new file mode 100644
index 0000000..2cbb4a5
--- /dev/null
+++ b/ui/gfx/win/direct_write.h
@@ -0,0 +1,40 @@
+// Copyright 2014 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.
+
+#ifndef UI_GFX_WIN_DIRECT_WRITE_H_
+#define UI_GFX_WIN_DIRECT_WRITE_H_
+
+#include <dwrite.h>
+
+#include "base/strings/string_piece.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+namespace win {
+
+GFX_EXPORT void InitializeDirectWrite();
+
+// Creates a DirectWrite factory.
+GFX_EXPORT void CreateDWriteFactory(IDWriteFactory** factory);
+
+// Returns the global DirectWrite factory.
+GFX_EXPORT IDWriteFactory* GetDirectWriteFactory();
+
+// Retrieves the localized string for a given locale. If locale is empty,
+// retrieves the first element of |names|.
+GFX_EXPORT absl::optional<std::string> RetrieveLocalizedString(
+    IDWriteLocalizedStrings* names,
+    const std::string& locale);
+
+// Retrieves the localized font name for a given locale. If locale is empty,
+// retrieves the default native font name.
+GFX_EXPORT absl::optional<std::string> RetrieveLocalizedFontName(
+    base::StringPiece font_name,
+    const std::string& locale);
+
+}  // namespace win
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_DIRECT_WRITE_H_
diff --git a/ui/gfx/win/direct_write_unittest.cc b/ui/gfx/win/direct_write_unittest.cc
new file mode 100644
index 0000000..1c136c8
--- /dev/null
+++ b/ui/gfx/win/direct_write_unittest.cc
@@ -0,0 +1,28 @@
+// Copyright 2019 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 "ui/gfx/win/direct_write.h"
+
+#include "base/i18n/rtl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(DirectWrite, RetrieveLocalizedFontName) {
+  // Retrieve the en-US localized names.
+  EXPECT_EQ(gfx::win::RetrieveLocalizedFontName("MS Gothic", "en-US"),
+            "MS Gothic");
+  EXPECT_EQ(gfx::win::RetrieveLocalizedFontName("Malgun Gothic", "en-US"),
+            "Malgun Gothic");
+
+  // Retrieve the localized names.
+  EXPECT_EQ(gfx::win::RetrieveLocalizedFontName("MS Gothic", "ja-JP"),
+            "MS ゴシック");
+  EXPECT_EQ(gfx::win::RetrieveLocalizedFontName("Malgun Gothic", "ko-KR"),
+            "맑은 고딕");
+
+  // Retrieve the default font name.
+  EXPECT_EQ(gfx::win::RetrieveLocalizedFontName("MS ゴシック", ""),
+            "MS Gothic");
+  EXPECT_EQ(gfx::win::RetrieveLocalizedFontName("맑은 고딕", ""),
+            "Malgun Gothic");
+}
diff --git a/ui/gfx/win/hwnd_util.cc b/ui/gfx/win/hwnd_util.cc
new file mode 100644
index 0000000..286b766
--- /dev/null
+++ b/ui/gfx/win/hwnd_util.cc
@@ -0,0 +1,210 @@
+// Copyright (c) 2012 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 "ui/gfx/win/hwnd_util.h"
+
+#include <windows.h>
+
+#include "base/debug/gdi_debug_util_win.h"
+#include "base/logging.h"
+#include "base/notreached.h"
+#include "base/strings/string_util.h"
+#include "base/win/win_util.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace gfx {
+
+namespace {
+
+// Adjust the window to fit.
+void AdjustWindowToFit(HWND hwnd, const RECT& bounds, bool fit_to_monitor) {
+  if (fit_to_monitor) {
+    // Get the monitor.
+    HMONITOR hmon = MonitorFromRect(&bounds, MONITOR_DEFAULTTONEAREST);
+    if (hmon) {
+      MONITORINFO mi;
+      mi.cbSize = sizeof(mi);
+      GetMonitorInfo(hmon, &mi);
+      Rect window_rect(bounds);
+      Rect monitor_rect(mi.rcWork);
+      Rect new_window_rect = window_rect;
+      new_window_rect.AdjustToFit(monitor_rect);
+      if (new_window_rect != window_rect) {
+        // Window doesn't fit on monitor, move and possibly resize.
+        SetWindowPos(hwnd, 0, new_window_rect.x(), new_window_rect.y(),
+                     new_window_rect.width(), new_window_rect.height(),
+                     SWP_NOACTIVATE | SWP_NOZORDER);
+        return;
+      }
+      // Else fall through.
+    } else {
+      NOTREACHED() << "Unable to find default monitor";
+      // Fall through.
+    }
+  }  // Else fall through.
+
+  // The window is not being fit to monitor, or the window fits on the monitor
+  // as is, or we have no monitor info; reset the bounds.
+  ::SetWindowPos(hwnd, 0, bounds.left, bounds.top,
+                 bounds.right - bounds.left, bounds.bottom - bounds.top,
+                 SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+// Don't inline these functions so they show up in crash reports.
+
+NOINLINE void CrashAccessDenied(DWORD last_error) {
+  LOG(FATAL) << last_error;
+}
+
+// Crash isn't one of the ones we commonly see.
+NOINLINE void CrashOther(DWORD last_error) {
+  LOG(FATAL) << last_error;
+}
+
+}  // namespace
+
+std::wstring GetClassName(HWND window) {
+  // GetClassNameW will return a truncated result (properly null terminated) if
+  // the given buffer is not large enough.  So, it is not possible to determine
+  // that we got the entire class name if the result is exactly equal to the
+  // size of the buffer minus one.
+  DWORD buffer_size = MAX_PATH;
+  while (true) {
+    std::wstring output;
+    DWORD size_ret = GetClassNameW(
+        window, base::WriteInto(&output, buffer_size), buffer_size);
+    if (size_ret == 0)
+      break;
+    if (size_ret < (buffer_size - 1)) {
+      output.resize(size_ret);
+      return output;
+    }
+    buffer_size *= 2;
+  }
+  return std::wstring();  // error
+}
+
+#pragma warning(push)
+#pragma warning(disable:4312 4244)
+
+WNDPROC SetWindowProc(HWND hwnd, WNDPROC proc) {
+  // The reason we don't return the SetwindowLongPtr() value is that it returns
+  // the orignal window procedure and not the current one. I don't know if it is
+  // a bug or an intended feature.
+  WNDPROC oldwindow_proc =
+      reinterpret_cast<WNDPROC>(GetWindowLongPtr(hwnd, GWLP_WNDPROC));
+  SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(proc));
+  return oldwindow_proc;
+}
+
+void* SetWindowUserData(HWND hwnd, void* user_data) {
+  return
+      reinterpret_cast<void*>(SetWindowLongPtr(hwnd, GWLP_USERDATA,
+          reinterpret_cast<LONG_PTR>(user_data)));
+}
+
+void* GetWindowUserData(HWND hwnd) {
+  DWORD process_id = 0;
+  GetWindowThreadProcessId(hwnd, &process_id);
+  // A window outside the current process needs to be ignored.
+  if (process_id != ::GetCurrentProcessId())
+    return NULL;
+  return reinterpret_cast<void*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
+}
+
+#pragma warning(pop)
+
+bool DoesWindowBelongToActiveWindow(HWND window) {
+  DCHECK(window);
+  HWND top_window = ::GetAncestor(window, GA_ROOT);
+  if (!top_window)
+    return false;
+
+  HWND active_top_window = ::GetAncestor(::GetForegroundWindow(), GA_ROOT);
+  return (top_window == active_top_window);
+}
+
+void CenterAndSizeWindow(HWND parent,
+                         HWND window,
+                         const Size& pref) {
+  DCHECK(window && pref.width() > 0 && pref.height() > 0);
+
+  // Calculate the ideal bounds.
+  RECT window_bounds;
+  RECT center_bounds = {0};
+  if (parent) {
+    // If there is a parent, center over the parents bounds.
+    ::GetWindowRect(parent, &center_bounds);
+  }
+
+  if (::IsRectEmpty(&center_bounds)) {
+    // No parent or no parent rect. Center over the monitor the window is on.
+    HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
+    if (monitor) {
+      MONITORINFO mi = {0};
+      mi.cbSize = sizeof(mi);
+      GetMonitorInfo(monitor, &mi);
+      center_bounds = mi.rcWork;
+    } else {
+      NOTREACHED() << "Unable to get default monitor";
+    }
+  }
+
+  window_bounds.left = center_bounds.left;
+  if (pref.width() < (center_bounds.right - center_bounds.left)) {
+    window_bounds.left +=
+        (center_bounds.right - center_bounds.left - pref.width()) / 2;
+  }
+  window_bounds.right = window_bounds.left + pref.width();
+
+  window_bounds.top = center_bounds.top;
+  if (pref.height() < (center_bounds.bottom - center_bounds.top)) {
+    window_bounds.top +=
+        (center_bounds.bottom - center_bounds.top - pref.height()) / 2;
+  }
+  window_bounds.bottom = window_bounds.top + pref.height();
+
+  // If we're centering a child window, we are positioning in client
+  // coordinates, and as such we need to offset the target rectangle by the
+  // position of the parent window.
+  if (::GetWindowLong(window, GWL_STYLE) & WS_CHILD) {
+    DCHECK(parent && ::GetParent(window) == parent);
+    POINT topleft = { window_bounds.left, window_bounds.top };
+    ::MapWindowPoints(HWND_DESKTOP, parent, &topleft, 1);
+    window_bounds.left = topleft.x;
+    window_bounds.top = topleft.y;
+    window_bounds.right = window_bounds.left + pref.width();
+    window_bounds.bottom = window_bounds.top + pref.height();
+  }
+
+  AdjustWindowToFit(window, window_bounds, !parent);
+}
+
+void CheckWindowCreated(HWND hwnd, DWORD last_error) {
+  if (!hwnd) {
+    switch (last_error) {
+      case ERROR_NOT_ENOUGH_MEMORY:
+        base::debug::CollectGDIUsageAndDie();
+        break;
+      case ERROR_ACCESS_DENIED:
+        CrashAccessDenied(last_error);
+        break;
+      default:
+        CrashOther(last_error);
+        break;
+    }
+    LOG(FATAL) << last_error;
+  }
+}
+
+extern "C" {
+  typedef HWND (*RootWindow)();
+}
+
+HWND GetWindowToParentTo(bool get_real_hwnd) {
+  return get_real_hwnd ? ::GetDesktopWindow() : HWND_DESKTOP;
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/win/hwnd_util.h b/ui/gfx/win/hwnd_util.h
new file mode 100644
index 0000000..d4d8eaf
--- /dev/null
+++ b/ui/gfx/win/hwnd_util.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 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.
+
+#ifndef UI_GFX_WIN_HWND_UTIL_H_
+#define UI_GFX_WIN_HWND_UTIL_H_
+
+#include <windows.h>
+
+#include <string>
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+class Size;
+
+// A version of the GetClassNameW API that returns the class name in an
+// std::wstring. An empty result indicates a failure to get the class name.
+GFX_EXPORT std::wstring GetClassName(HWND hwnd);
+
+// Useful for subclassing a HWND.  Returns the previous window procedure.
+GFX_EXPORT WNDPROC SetWindowProc(HWND hwnd, WNDPROC wndproc);
+
+// Pointer-friendly wrappers around Get/SetWindowLong(..., GWLP_USERDATA, ...)
+// Returns the previously set value.
+GFX_EXPORT void* SetWindowUserData(HWND hwnd, void* user_data);
+GFX_EXPORT void* GetWindowUserData(HWND hwnd);
+
+// Returns true if the specified window is the current active top window or one
+// of its children.
+GFX_EXPORT bool DoesWindowBelongToActiveWindow(HWND window);
+
+// Sizes the window to have a window size of |pref|, then centers the window
+// over |parent|, ensuring the window fits on screen.
+GFX_EXPORT void CenterAndSizeWindow(HWND parent,
+                                    HWND window,
+                                    const gfx::Size& pref);
+
+// If |hwnd| is nullptr logs various thing and CHECKs. |last_error| must contain
+// the result of ::GetLastError(), called immediately after CreateWindow().
+GFX_EXPORT void CheckWindowCreated(HWND hwnd, DWORD last_error);
+
+// Returns the window you can use to parent a top level window.
+// Note that in some cases we create child windows not parented to its final
+// container so in those cases you should pass true in |get_real_hwnd|.
+GFX_EXPORT HWND GetWindowToParentTo(bool get_real_hwnd);
+
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_HWND_UTIL_H_
diff --git a/ui/gfx/win/msg_util.h b/ui/gfx/win/msg_util.h
new file mode 100644
index 0000000..7c6b42b
--- /dev/null
+++ b/ui/gfx/win/msg_util.h
@@ -0,0 +1,2261 @@
+// Copyright 2014 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.
+
+#ifndef UI_GFX_WIN_MSG_UTIL_H_
+#define UI_GFX_WIN_MSG_UTIL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/notreached.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/size.h"
+
+// Based on WTL version 8.0 atlcrack.h
+
+// This differs from the original atlcrack.h by removing usage of CPoint,
+// CSize, etc.
+
+///////////////////////////////////////////////////////////////////////////////
+// Message map macro for cracked handlers
+
+// Note about message maps with cracked handlers:
+// For ATL 3.0, a message map using cracked handlers MUST use
+// CR_BEGIN_MSG_MAP_EX. For ATL 7.0 or higher, you can use CR_BEGIN_MSG_MAP for
+// CWindowImpl/CDialogImpl derived classes, but must use CR_BEGIN_MSG_MAP_EX for
+// classes that don't derive from CWindowImpl/CDialogImpl.
+// Classes using the CR_BEGIN_MSG_MAP_EX/CR_END_MSG_MAP set of macros must
+// also include a CR_MSG_MAP_CLASS_DECLARATIONS macro after all members in
+// the class definition since the macros add a
+// base::WeakPtrFactory which is only allowed if last in the class.
+
+#define CR_BEGIN_MSG_MAP_EX(theClass)                                       \
+ public:                                                                    \
+  /* "handled" management for cracked handlers */                           \
+  void SetMsgHandled(BOOL handled) { msg_handled_ = handled; }              \
+  BOOL ProcessWindowMessage(HWND hwnd, UINT msg, WPARAM w_param,            \
+                            LPARAM l_param, LRESULT& l_result,              \
+                            DWORD msg_map_id = 0) override {                \
+    auto ref(theClass::msg_handler_weak_factory_.GetWeakPtr());             \
+    BOOL old_msg_handled = msg_handled_;                                    \
+    BOOL ret = _ProcessWindowMessage(hwnd, msg, w_param, l_param, l_result, \
+                                     msg_map_id);                           \
+    if (ref.get())                                                          \
+      msg_handled_ = old_msg_handled;                                       \
+    return ret;                                                             \
+  }                                                                         \
+  BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam,           \
+                             LPARAM lParam, LRESULT& lResult,               \
+                             DWORD dwMsgMapID) {                            \
+    auto ref(theClass::msg_handler_weak_factory_.GetWeakPtr());             \
+    BOOL bHandled = TRUE;                                                   \
+    hWnd;                                                                   \
+    uMsg;                                                                   \
+    wParam;                                                                 \
+    lParam;                                                                 \
+    lResult;                                                                \
+    bHandled;                                                               \
+    switch (dwMsgMapID) {                                                   \
+      case 0:
+
+// Replacement for atlwin.h's END_MSG_MAP for removing ATL usage.
+#define CR_END_MSG_MAP()                                      \
+  break;                                                      \
+  default:                                                    \
+    NOTREACHED() << "Invalid message map ID: " << dwMsgMapID; \
+    break;                                                    \
+    }                                                         \
+    return FALSE;                                             \
+    }
+
+// This macro must be last in the class since it contains a
+// base::WeakPtrFactory which must be last in the class.
+#define CR_MSG_MAP_CLASS_DECLARATIONS(theClass) \
+ private:                                       \
+  BOOL msg_handled_{false};                     \
+  base::WeakPtrFactory<theClass> msg_handler_weak_factory_{this};
+
+#define CR_GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
+#define CR_GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
+
+///////////////////////////////////////////////////////////////////////////////
+// Standard Windows message macros
+
+// int OnCreate(LPCREATESTRUCT lpCreateStruct)
+#define CR_MSG_WM_CREATE(func)                       \
+  if (uMsg == WM_CREATE) {                           \
+    SetMsgHandled(TRUE);                             \
+    lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
+    if (!ref.get() || msg_handled_)                  \
+      return TRUE;                                   \
+  }
+
+// BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
+#define CR_MSG_WM_INITDIALOG(func)                 \
+  if (uMsg == WM_INITDIALOG) {                     \
+    SetMsgHandled(TRUE);                           \
+    lResult = (LRESULT)func((HWND)wParam, lParam); \
+    if (!ref.get() || msg_handled_)                \
+      return TRUE;                                 \
+  }
+
+// BOOL OnCopyData(CWindow wnd, PCOPYDATASTRUCT pCopyDataStruct)
+#define CR_MSG_WM_COPYDATA(func)                                    \
+  if (uMsg == WM_COPYDATA) {                                        \
+    SetMsgHandled(TRUE);                                            \
+    lResult = (LRESULT)func((HWND)wParam, (PCOPYDATASTRUCT)lParam); \
+    if (!ref.get() || msg_handled_)                                 \
+      return TRUE;                                                  \
+  }
+
+// void OnDestroy()
+#define CR_MSG_WM_DESTROY(func)     \
+  if (uMsg == WM_DESTROY) {         \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnMove(CPoint ptPos)
+#define CR_MSG_WM_MOVE(func)                                            \
+  if (uMsg == WM_MOVE) {                                                \
+    SetMsgHandled(TRUE);                                                \
+    func(gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnSize(UINT nType, gfx::Size size)
+#define CR_MSG_WM_SIZE(func)                                           \
+  if (uMsg == WM_SIZE) {                                               \
+    SetMsgHandled(TRUE);                                               \
+    func((UINT)wParam,                                                 \
+         gfx::Size(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                       \
+    if (!ref.get() || msg_handled_)                                    \
+      return TRUE;                                                     \
+  }
+
+// void OnActivate(UINT nState, BOOL bMinimized, CWindow wndOther)
+#define CR_MSG_WM_ACTIVATE(func)                                    \
+  if (uMsg == WM_ACTIVATE) {                                        \
+    SetMsgHandled(TRUE);                                            \
+    func((UINT)LOWORD(wParam), (BOOL)HIWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                    \
+    if (!ref.get() || msg_handled_)                                 \
+      return TRUE;                                                  \
+  }
+
+// void OnSetFocus(CWindow wndOld)
+#define CR_MSG_WM_SETFOCUS(func)    \
+  if (uMsg == WM_SETFOCUS) {        \
+    SetMsgHandled(TRUE);            \
+    func((HWND)wParam);             \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnKillFocus(CWindow wndFocus)
+#define CR_MSG_WM_KILLFOCUS(func)   \
+  if (uMsg == WM_KILLFOCUS) {       \
+    SetMsgHandled(TRUE);            \
+    func((HWND)wParam);             \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnEnable(BOOL bEnable)
+#define CR_MSG_WM_ENABLE(func)      \
+  if (uMsg == WM_ENABLE) {          \
+    SetMsgHandled(TRUE);            \
+    func((BOOL)wParam);             \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnPaint(CDCHandle dc)
+#define CR_MSG_WM_PAINT(func)       \
+  if (uMsg == WM_PAINT) {           \
+    SetMsgHandled(TRUE);            \
+    func((HDC)wParam);              \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnClose()
+#define CR_MSG_WM_CLOSE(func)       \
+  if (uMsg == WM_CLOSE) {           \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// BOOL OnQueryEndSession(UINT nSource, UINT uLogOff)
+#define CR_MSG_WM_QUERYENDSESSION(func)                  \
+  if (uMsg == WM_QUERYENDSESSION) {                      \
+    SetMsgHandled(TRUE);                                 \
+    lResult = (LRESULT)func((UINT)wParam, (UINT)lParam); \
+    if (!ref.get() || msg_handled_)                      \
+      return TRUE;                                       \
+  }
+
+// BOOL OnQueryOpen()
+#define CR_MSG_WM_QUERYOPEN(func)   \
+  if (uMsg == WM_QUERYOPEN) {       \
+    SetMsgHandled(TRUE);            \
+    lResult = (LRESULT)func();      \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// BOOL OnEraseBkgnd(CDCHandle dc)
+#define CR_MSG_WM_ERASEBKGND(func)        \
+  if (uMsg == WM_ERASEBKGND) {            \
+    SetMsgHandled(TRUE);                  \
+    lResult = (LRESULT)func((HDC)wParam); \
+    if (!ref.get() || msg_handled_)       \
+      return TRUE;                        \
+  }
+
+// void OnSysColorChange()
+#define CR_MSG_WM_SYSCOLORCHANGE(func) \
+  if (uMsg == WM_SYSCOLORCHANGE) {     \
+    SetMsgHandled(TRUE);               \
+    func();                            \
+    lResult = 0;                       \
+    if (!ref.get() || msg_handled_)    \
+      return TRUE;                     \
+  }
+
+// void OnEndSession(BOOL bEnding, UINT uLogOff)
+#define CR_MSG_WM_ENDSESSION(func)    \
+  if (uMsg == WM_ENDSESSION) {        \
+    SetMsgHandled(TRUE);              \
+    func((BOOL)wParam, (UINT)lParam); \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnShowWindow(BOOL bShow, UINT nStatus)
+#define CR_MSG_WM_SHOWWINDOW(func)   \
+  if (uMsg == WM_SHOWWINDOW) {       \
+    SetMsgHandled(TRUE);             \
+    func((BOOL)wParam, (int)lParam); \
+    lResult = 0;                     \
+    if (!ref.get() || msg_handled_)  \
+      return TRUE;                   \
+  }
+
+// HBRUSH OnCtlColorEdit(CDCHandle dc, CEdit edit)
+#define CR_MSG_WM_CTLCOLOREDIT(func)                    \
+  if (uMsg == WM_CTLCOLOREDIT) {                        \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnCtlColorListBox(CDCHandle dc, CListBox listBox)
+#define CR_MSG_WM_CTLCOLORLISTBOX(func)                 \
+  if (uMsg == WM_CTLCOLORLISTBOX) {                     \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnCtlColorBtn(CDCHandle dc, CButton button)
+#define CR_MSG_WM_CTLCOLORBTN(func)                     \
+  if (uMsg == WM_CTLCOLORBTN) {                         \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnCtlColorDlg(CDCHandle dc, CWindow wnd)
+#define CR_MSG_WM_CTLCOLORDLG(func)                     \
+  if (uMsg == WM_CTLCOLORDLG) {                         \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar)
+#define CR_MSG_WM_CTLCOLORSCROLLBAR(func)               \
+  if (uMsg == WM_CTLCOLORSCROLLBAR) {                   \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnCtlColorStatic(CDCHandle dc, CStatic wndStatic)
+#define CR_MSG_WM_CTLCOLORSTATIC(func)                  \
+  if (uMsg == WM_CTLCOLORSTATIC) {                      \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// void OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
+#define CR_MSG_WM_SETTINGCHANGE(func)    \
+  if (uMsg == WM_SETTINGCHANGE) {        \
+    SetMsgHandled(TRUE);                 \
+    func((UINT)wParam, (LPCTSTR)lParam); \
+    lResult = 0;                         \
+    if (!ref.get() || msg_handled_)      \
+      return TRUE;                       \
+  }
+
+// void OnDevModeChange(LPCTSTR lpDeviceName)
+#define CR_MSG_WM_DEVMODECHANGE(func) \
+  if (uMsg == WM_DEVMODECHANGE) {     \
+    SetMsgHandled(TRUE);              \
+    func((LPCTSTR)lParam);            \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnActivateApp(BOOL bActive, DWORD dwThreadID)
+#define CR_MSG_WM_ACTIVATEAPP(func)    \
+  if (uMsg == WM_ACTIVATEAPP) {        \
+    SetMsgHandled(TRUE);               \
+    func((BOOL)wParam, (DWORD)lParam); \
+    lResult = 0;                       \
+    if (!ref.get() || msg_handled_)    \
+      return TRUE;                     \
+  }
+
+// void OnFontChange()
+#define CR_MSG_WM_FONTCHANGE(func)  \
+  if (uMsg == WM_FONTCHANGE) {      \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnTimeChange()
+#define CR_MSG_WM_TIMECHANGE(func)  \
+  if (uMsg == WM_TIMECHANGE) {      \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnCancelMode()
+#define CR_MSG_WM_CANCELMODE(func)  \
+  if (uMsg == WM_CANCELMODE) {      \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message)
+#define CR_MSG_WM_SETCURSOR(func)                               \
+  if (uMsg == WM_SETCURSOR) {                                   \
+    SetMsgHandled(TRUE);                                        \
+    lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), \
+                            (UINT)HIWORD(lParam));              \
+    if (!ref.get() || msg_handled_)                             \
+      return TRUE;                                              \
+  }
+
+// int OnMouseActivate(CWindow wndTopLevel, UINT nHitTest, UINT message)
+#define CR_MSG_WM_MOUSEACTIVATE(func)                           \
+  if (uMsg == WM_MOUSEACTIVATE) {                               \
+    SetMsgHandled(TRUE);                                        \
+    lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), \
+                            (UINT)HIWORD(lParam));              \
+    if (!ref.get() || msg_handled_)                             \
+      return TRUE;                                              \
+  }
+
+// void OnChildActivate()
+#define CR_MSG_WM_CHILDACTIVATE(func) \
+  if (uMsg == WM_CHILDACTIVATE) {     \
+    SetMsgHandled(TRUE);              \
+    func();                           \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnGetMinMaxInfo(LPMINMAXINFO lpMMI)
+#define CR_MSG_WM_GETMINMAXINFO(func) \
+  if (uMsg == WM_GETMINMAXINFO) {     \
+    SetMsgHandled(TRUE);              \
+    func((LPMINMAXINFO)lParam);       \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnIconEraseBkgnd(CDCHandle dc)
+#define CR_MSG_WM_ICONERASEBKGND(func) \
+  if (uMsg == WM_ICONERASEBKGND) {     \
+    SetMsgHandled(TRUE);               \
+    func((HDC)wParam);                 \
+    lResult = 0;                       \
+    if (!ref.get() || msg_handled_)    \
+      return TRUE;                     \
+  }
+
+// void OnSpoolerStatus(UINT nStatus, UINT nJobs)
+#define CR_MSG_WM_SPOOLERSTATUS(func)         \
+  if (uMsg == WM_SPOOLERSTATUS) {             \
+    SetMsgHandled(TRUE);                      \
+    func((UINT)wParam, (UINT)LOWORD(lParam)); \
+    lResult = 0;                              \
+    if (!ref.get() || msg_handled_)           \
+      return TRUE;                            \
+  }
+
+// void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
+#define CR_MSG_WM_DRAWITEM(func)                  \
+  if (uMsg == WM_DRAWITEM) {                      \
+    SetMsgHandled(TRUE);                          \
+    func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \
+    lResult = TRUE;                               \
+    if (!ref.get() || msg_handled_)               \
+      return TRUE;                                \
+  }
+
+// void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
+#define CR_MSG_WM_MEASUREITEM(func)                  \
+  if (uMsg == WM_MEASUREITEM) {                      \
+    SetMsgHandled(TRUE);                             \
+    func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \
+    lResult = TRUE;                                  \
+    if (!ref.get() || msg_handled_)                  \
+      return TRUE;                                   \
+  }
+
+// void OnDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct)
+#define CR_MSG_WM_DELETEITEM(func)                  \
+  if (uMsg == WM_DELETEITEM) {                      \
+    SetMsgHandled(TRUE);                            \
+    func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \
+    lResult = TRUE;                                 \
+    if (!ref.get() || msg_handled_)                 \
+      return TRUE;                                  \
+  }
+
+// int OnCharToItem(UINT nChar, UINT nIndex, CListBox listBox)
+#define CR_MSG_WM_CHARTOITEM(func)                                      \
+  if (uMsg == WM_CHARTOITEM) {                                          \
+    SetMsgHandled(TRUE);                                                \
+    lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), \
+                            (HWND)lParam);                              \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// int OnVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox)
+#define CR_MSG_WM_VKEYTOITEM(func)                                      \
+  if (uMsg == WM_VKEYTOITEM) {                                          \
+    SetMsgHandled(TRUE);                                                \
+    lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), \
+                            (HWND)lParam);                              \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// HCURSOR OnQueryDragIcon()
+#define CR_MSG_WM_QUERYDRAGICON(func) \
+  if (uMsg == WM_QUERYDRAGICON) {     \
+    SetMsgHandled(TRUE);              \
+    lResult = (LRESULT)func();        \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// int OnCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
+#define CR_MSG_WM_COMPAREITEM(func)                                     \
+  if (uMsg == WM_COMPAREITEM) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnCompacting(UINT nCpuTime)
+#define CR_MSG_WM_COMPACTING(func)  \
+  if (uMsg == WM_COMPACTING) {      \
+    SetMsgHandled(TRUE);            \
+    func((UINT)wParam);             \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct)
+#define CR_MSG_WM_NCCREATE(func)                     \
+  if (uMsg == WM_NCCREATE) {                         \
+    SetMsgHandled(TRUE);                             \
+    lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
+    if (!ref.get() || msg_handled_)                  \
+      return TRUE;                                   \
+  }
+
+// void OnNcDestroy()
+#define CR_MSG_WM_NCDESTROY(func)   \
+  if (uMsg == WM_NCDESTROY) {       \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam)
+#define CR_MSG_WM_NCCALCSIZE(func)        \
+  if (uMsg == WM_NCCALCSIZE) {            \
+    SetMsgHandled(TRUE);                  \
+    lResult = func((BOOL)wParam, lParam); \
+    if (!ref.get() || msg_handled_)       \
+      return TRUE;                        \
+  }
+
+// UINT OnNcHitTest(gfx::Point point)
+#define CR_MSG_WM_NCHITTEST(func)                                      \
+  if (uMsg == WM_NCHITTEST) {                                          \
+    SetMsgHandled(TRUE);                                               \
+    lResult = (LRESULT)func(                                           \
+        gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    if (!ref.get() || msg_handled_)                                    \
+      return TRUE;                                                     \
+  }
+
+// void OnNcPaint(CRgn rgn)
+#define CR_MSG_WM_NCPAINT(func)     \
+  if (uMsg == WM_NCPAINT) {         \
+    SetMsgHandled(TRUE);            \
+    func((HRGN)wParam);             \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// BOOL OnNcActivate(BOOL bActive)
+#define CR_MSG_WM_NCACTIVATE(func)         \
+  if (uMsg == WM_NCACTIVATE) {             \
+    SetMsgHandled(TRUE);                   \
+    lResult = (LRESULT)func((BOOL)wParam); \
+    if (!ref.get() || msg_handled_)        \
+      return TRUE;                         \
+  }
+
+// UINT OnGetDlgCode(LPMSG lpMsg)
+#define CR_MSG_WM_GETDLGCODE(func)          \
+  if (uMsg == WM_GETDLGCODE) {              \
+    SetMsgHandled(TRUE);                    \
+    lResult = (LRESULT)func((LPMSG)lParam); \
+    if (!ref.get() || msg_handled_)         \
+      return TRUE;                          \
+  }
+
+// void OnNcMouseMove(UINT nHitTest, gfx::Point point)
+#define CR_MSG_WM_NCMOUSEMOVE(func)                                     \
+  if (uMsg == WM_NCMOUSEMOVE) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNcLButtonDown(UINT nHitTest, gfx::Point point)
+#define CR_MSG_WM_NCLBUTTONDOWN(func)                                   \
+  if (uMsg == WM_NCLBUTTONDOWN) {                                       \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNcLButtonUp(UINT nHitTest, gfx::Point point)
+#define CR_MSG_WM_NCLBUTTONUP(func)                                     \
+  if (uMsg == WM_NCLBUTTONUP) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNcLButtonDblClk(UINT nHitTest, gfx::Point point)
+#define CR_MSG_WM_NCLBUTTONDBLCLK(func)                                 \
+  if (uMsg == WM_NCLBUTTONDBLCLK) {                                     \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNcRButtonDown(UINT nHitTest, gfx::Point point)
+#define CR_MSG_WM_NCRBUTTONDOWN(func)                                   \
+  if (uMsg == WM_NCRBUTTONDOWN) {                                       \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNcRButtonUp(UINT nHitTest, gfx::Point point)
+#define CR_MSG_WM_NCRBUTTONUP(func)                                     \
+  if (uMsg == WM_NCRBUTTONUP) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNcRButtonDblClk(UINT nHitTest, CPoint point)
+#define CR_MSG_WM_NCRBUTTONDBLCLK(func)                                 \
+  if (uMsg == WM_NCRBUTTONDBLCLK) {                                     \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNcMButtonDown(UINT nHitTest, CPoint point)
+#define CR_MSG_WM_NCMBUTTONDOWN(func)                                   \
+  if (uMsg == WM_NCMBUTTONDOWN) {                                       \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNcMButtonUp(UINT nHitTest, CPoint point)
+#define CR_MSG_WM_NCMBUTTONUP(func)                                     \
+  if (uMsg == WM_NCMBUTTONUP) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNcMButtonDblClk(UINT nHitTest, CPoint point)
+#define CR_MSG_WM_NCMBUTTONDBLCLK(func)                                 \
+  if (uMsg == WM_NCMBUTTONDBLCLK) {                                     \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define CR_MSG_WM_KEYDOWN(func)                \
+  if (uMsg == WM_KEYDOWN) {                    \
+    SetMsgHandled(TRUE);                       \
+    func((TCHAR)wParam, (UINT)lParam & 0xFFFF, \
+         (UINT)((lParam & 0xFFFF0000) >> 16)); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define CR_MSG_WM_KEYUP(func)                  \
+  if (uMsg == WM_KEYUP) {                      \
+    SetMsgHandled(TRUE);                       \
+    func((TCHAR)wParam, (UINT)lParam & 0xFFFF, \
+         (UINT)((lParam & 0xFFFF0000) >> 16)); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define CR_MSG_WM_CHAR(func)                   \
+  if (uMsg == WM_CHAR) {                       \
+    SetMsgHandled(TRUE);                       \
+    func((TCHAR)wParam, (UINT)lParam & 0xFFFF, \
+         (UINT)((lParam & 0xFFFF0000) >> 16)); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define CR_MSG_WM_DEADCHAR(func)               \
+  if (uMsg == WM_DEADCHAR) {                   \
+    SetMsgHandled(TRUE);                       \
+    func((TCHAR)wParam, (UINT)lParam & 0xFFFF, \
+         (UINT)((lParam & 0xFFFF0000) >> 16)); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define CR_MSG_WM_SYSKEYDOWN(func)             \
+  if (uMsg == WM_SYSKEYDOWN) {                 \
+    SetMsgHandled(TRUE);                       \
+    func((TCHAR)wParam, (UINT)lParam & 0xFFFF, \
+         (UINT)((lParam & 0xFFFF0000) >> 16)); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define CR_MSG_WM_SYSKEYUP(func)               \
+  if (uMsg == WM_SYSKEYUP) {                   \
+    SetMsgHandled(TRUE);                       \
+    func((TCHAR)wParam, (UINT)lParam & 0xFFFF, \
+         (UINT)((lParam & 0xFFFF0000) >> 16)); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define CR_MSG_WM_SYSCHAR(func)                \
+  if (uMsg == WM_SYSCHAR) {                    \
+    SetMsgHandled(TRUE);                       \
+    func((TCHAR)wParam, (UINT)lParam & 0xFFFF, \
+         (UINT)((lParam & 0xFFFF0000) >> 16)); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnSysDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+#define CR_MSG_WM_SYSDEADCHAR(func)            \
+  if (uMsg == WM_SYSDEADCHAR) {                \
+    SetMsgHandled(TRUE);                       \
+    func((TCHAR)wParam, (UINT)lParam & 0xFFFF, \
+         (UINT)((lParam & 0xFFFF0000) >> 16)); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnSysCommand(UINT nID, LPARAM lParam)
+#define CR_MSG_WM_SYSCOMMAND(func)                                      \
+  if (uMsg == WM_SYSCOMMAND) {                                          \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnTCard(UINT idAction, DWORD dwActionData)
+#define CR_MSG_WM_TCARD(func)          \
+  if (uMsg == WM_TCARD) {              \
+    SetMsgHandled(TRUE);               \
+    func((UINT)wParam, (DWORD)lParam); \
+    lResult = 0;                       \
+    if (!ref.get() || msg_handled_)    \
+      return TRUE;                     \
+  }
+
+// void OnTimer(UINT_PTR nIDEvent)
+#define CR_MSG_WM_TIMER(func)       \
+  if (uMsg == WM_TIMER) {           \
+    SetMsgHandled(TRUE);            \
+    func((UINT_PTR)wParam);         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
+#define CR_MSG_WM_HSCROLL(func)                                     \
+  if (uMsg == WM_HSCROLL) {                                         \
+    SetMsgHandled(TRUE);                                            \
+    func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                    \
+    if (!ref.get() || msg_handled_)                                 \
+      return TRUE;                                                  \
+  }
+
+// void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
+#define CR_MSG_WM_VSCROLL(func)                                     \
+  if (uMsg == WM_VSCROLL) {                                         \
+    SetMsgHandled(TRUE);                                            \
+    func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                    \
+    if (!ref.get() || msg_handled_)                                 \
+      return TRUE;                                                  \
+  }
+
+// void OnInitMenu(CMenu menu)
+#define CR_MSG_WM_INITMENU(func)    \
+  if (uMsg == WM_INITMENU) {        \
+    SetMsgHandled(TRUE);            \
+    func((HMENU)wParam);            \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnInitMenuPopup(CMenu menuPopup, UINT nIndex, BOOL bSysMenu)
+#define CR_MSG_WM_INITMENUPOPUP(func)                                \
+  if (uMsg == WM_INITMENUPOPUP) {                                    \
+    SetMsgHandled(TRUE);                                             \
+    func((HMENU)wParam, (UINT)LOWORD(lParam), (BOOL)HIWORD(lParam)); \
+    lResult = 0;                                                     \
+    if (!ref.get() || msg_handled_)                                  \
+      return TRUE;                                                   \
+  }
+
+// void OnMenuSelect(UINT nItemID, UINT nFlags, CMenu menu)
+#define CR_MSG_WM_MENUSELECT(func)                                   \
+  if (uMsg == WM_MENUSELECT) {                                       \
+    SetMsgHandled(TRUE);                                             \
+    func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \
+    lResult = 0;                                                     \
+    if (!ref.get() || msg_handled_)                                  \
+      return TRUE;                                                   \
+  }
+
+// LRESULT OnMenuChar(UINT nChar, UINT nFlags, CMenu menu)
+#define CR_MSG_WM_MENUCHAR(func)                                          \
+  if (uMsg == WM_MENUCHAR) {                                              \
+    SetMsgHandled(TRUE);                                                  \
+    lResult =                                                             \
+        func((TCHAR)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \
+    if (!ref.get() || msg_handled_)                                       \
+      return TRUE;                                                        \
+  }
+
+// LRESULT OnNotify(int idCtrl, LPNMHDR pnmh)
+#define CR_MSG_WM_NOTIFY(func)                    \
+  if (uMsg == WM_NOTIFY) {                        \
+    SetMsgHandled(TRUE);                          \
+    lResult = func((int)wParam, (LPNMHDR)lParam); \
+    if (!ref.get() || msg_handled_)               \
+      return TRUE;                                \
+  }
+
+// void OnEnterIdle(UINT nWhy, CWindow wndWho)
+#define CR_MSG_WM_ENTERIDLE(func)     \
+  if (uMsg == WM_ENTERIDLE) {         \
+    SetMsgHandled(TRUE);              \
+    func((UINT)wParam, (HWND)lParam); \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnMouseMove(UINT nFlags, CPoint point)
+#define CR_MSG_WM_MOUSEMOVE(func)                                       \
+  if (uMsg == WM_MOUSEMOVE) {                                           \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
+#define CR_MSG_WM_MOUSEWHEEL(func)                                     \
+  if (uMsg == WM_MOUSEWHEEL) {                                         \
+    SetMsgHandled(TRUE);                                               \
+    lResult = (LRESULT)func(                                           \
+        (UINT)LOWORD(wParam), (short)HIWORD(wParam),                   \
+        gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    if (!ref.get() || msg_handled_)                                    \
+      return TRUE;                                                     \
+  }
+
+// void OnLButtonDown(UINT nFlags, CPoint point)
+#define CR_MSG_WM_LBUTTONDOWN(func)                                     \
+  if (uMsg == WM_LBUTTONDOWN) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnLButtonUp(UINT nFlags, CPoint point)
+#define CR_MSG_WM_LBUTTONUP(func)                                       \
+  if (uMsg == WM_LBUTTONUP) {                                           \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnLButtonDblClk(UINT nFlags, CPoint point)
+#define CR_MSG_WM_LBUTTONDBLCLK(func)                                   \
+  if (uMsg == WM_LBUTTONDBLCLK) {                                       \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnRButtonDown(UINT nFlags, CPoint point)
+#define CR_MSG_WM_RBUTTONDOWN(func)                                     \
+  if (uMsg == WM_RBUTTONDOWN) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnRButtonUp(UINT nFlags, CPoint point)
+#define CR_MSG_WM_RBUTTONUP(func)                                       \
+  if (uMsg == WM_RBUTTONUP) {                                           \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnRButtonDblClk(UINT nFlags, CPoint point)
+#define CR_MSG_WM_RBUTTONDBLCLK(func)                                   \
+  if (uMsg == WM_RBUTTONDBLCLK) {                                       \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnMButtonDown(UINT nFlags, CPoint point)
+#define CR_MSG_WM_MBUTTONDOWN(func)                                     \
+  if (uMsg == WM_MBUTTONDOWN) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnMButtonUp(UINT nFlags, CPoint point)
+#define CR_MSG_WM_MBUTTONUP(func)                                       \
+  if (uMsg == WM_MBUTTONUP) {                                           \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnMButtonDblClk(UINT nFlags, CPoint point)
+#define CR_MSG_WM_MBUTTONDBLCLK(func)                                   \
+  if (uMsg == WM_MBUTTONDBLCLK) {                                       \
+    SetMsgHandled(TRUE);                                                \
+    func((UINT)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnParentNotify(UINT message, UINT nChildID, LPARAM lParam)
+#define CR_MSG_WM_PARENTNOTIFY(func)                          \
+  if (uMsg == WM_PARENTNOTIFY) {                              \
+    SetMsgHandled(TRUE);                                      \
+    func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \
+    lResult = 0;                                              \
+    if (!ref.get() || msg_handled_)                           \
+      return TRUE;                                            \
+  }
+
+// void OnMDIActivate(CWindow wndActivate, CWindow wndDeactivate)
+#define CR_MSG_WM_MDIACTIVATE(func)   \
+  if (uMsg == WM_MDIACTIVATE) {       \
+    SetMsgHandled(TRUE);              \
+    func((HWND)wParam, (HWND)lParam); \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnRenderFormat(UINT nFormat)
+#define CR_MSG_WM_RENDERFORMAT(func) \
+  if (uMsg == WM_RENDERFORMAT) {     \
+    SetMsgHandled(TRUE);             \
+    func((UINT)wParam);              \
+    lResult = 0;                     \
+    if (!ref.get() || msg_handled_)  \
+      return TRUE;                   \
+  }
+
+// void OnRenderAllFormats()
+#define CR_MSG_WM_RENDERALLFORMATS(func) \
+  if (uMsg == WM_RENDERALLFORMATS) {     \
+    SetMsgHandled(TRUE);                 \
+    func();                              \
+    lResult = 0;                         \
+    if (!ref.get() || msg_handled_)      \
+      return TRUE;                       \
+  }
+
+// void OnDestroyClipboard()
+#define CR_MSG_WM_DESTROYCLIPBOARD(func) \
+  if (uMsg == WM_DESTROYCLIPBOARD) {     \
+    SetMsgHandled(TRUE);                 \
+    func();                              \
+    lResult = 0;                         \
+    if (!ref.get() || msg_handled_)      \
+      return TRUE;                       \
+  }
+
+// void OnDrawClipboard()
+#define CR_MSG_WM_DRAWCLIPBOARD(func) \
+  if (uMsg == WM_DRAWCLIPBOARD) {     \
+    SetMsgHandled(TRUE);              \
+    func();                           \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnPaintClipboard(CWindow wndViewer, const LPPAINTSTRUCT lpPaintStruct)
+#define CR_MSG_WM_PAINTCLIPBOARD(func)                                      \
+  if (uMsg == WM_PAINTCLIPBOARD) {                                          \
+    SetMsgHandled(TRUE);                                                    \
+    func((HWND)wParam, (const LPPAINTSTRUCT)::GlobalLock((HGLOBAL)lParam)); \
+    ::GlobalUnlock((HGLOBAL)lParam);                                        \
+    lResult = 0;                                                            \
+    if (!ref.get() || msg_handled_)                                         \
+      return TRUE;                                                          \
+  }
+
+// void OnVScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos)
+#define CR_MSG_WM_VSCROLLCLIPBOARD(func)                            \
+  if (uMsg == WM_VSCROLLCLIPBOARD) {                                \
+    SetMsgHandled(TRUE);                                            \
+    func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
+    lResult = 0;                                                    \
+    if (!ref.get() || msg_handled_)                                 \
+      return TRUE;                                                  \
+  }
+
+// void OnContextMenu(CWindow wnd, CPoint point)
+#define CR_MSG_WM_CONTEXTMENU(func)                                     \
+  if (uMsg == WM_CONTEXTMENU) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func((HWND)wParam,                                                  \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnSizeClipboard(CWindow wndViewer, const LPRECT lpRect)
+#define CR_MSG_WM_SIZECLIPBOARD(func)                                \
+  if (uMsg == WM_SIZECLIPBOARD) {                                    \
+    SetMsgHandled(TRUE);                                             \
+    func((HWND)wParam, (const LPRECT)::GlobalLock((HGLOBAL)lParam)); \
+    ::GlobalUnlock((HGLOBAL)lParam);                                 \
+    lResult = 0;                                                     \
+    if (!ref.get() || msg_handled_)                                  \
+      return TRUE;                                                   \
+  }
+
+// void OnAskCbFormatName(UINT nMaxCount, LPTSTR lpszString)
+#define CR_MSG_WM_ASKCBFORMATNAME(func)  \
+  if (uMsg == WM_ASKCBFORMATNAME) {      \
+    SetMsgHandled(TRUE);                 \
+    func((DWORD)wParam, (LPTSTR)lParam); \
+    lResult = 0;                         \
+    if (!ref.get() || msg_handled_)      \
+      return TRUE;                       \
+  }
+
+// void OnChangeCbChain(CWindow wndRemove, CWindow wndAfter)
+#define CR_MSG_WM_CHANGECBCHAIN(func) \
+  if (uMsg == WM_CHANGECBCHAIN) {     \
+    SetMsgHandled(TRUE);              \
+    func((HWND)wParam, (HWND)lParam); \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnHScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos)
+#define CR_MSG_WM_HSCROLLCLIPBOARD(func)                            \
+  if (uMsg == WM_HSCROLLCLIPBOARD) {                                \
+    SetMsgHandled(TRUE);                                            \
+    func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
+    lResult = 0;                                                    \
+    if (!ref.get() || msg_handled_)                                 \
+      return TRUE;                                                  \
+  }
+
+// BOOL OnQueryNewPalette()
+#define CR_MSG_WM_QUERYNEWPALETTE(func) \
+  if (uMsg == WM_QUERYNEWPALETTE) {     \
+    SetMsgHandled(TRUE);                \
+    lResult = (LRESULT)func();          \
+    if (!ref.get() || msg_handled_)     \
+      return TRUE;                      \
+  }
+
+// void OnPaletteChanged(CWindow wndFocus)
+#define CR_MSG_WM_PALETTECHANGED(func) \
+  if (uMsg == WM_PALETTECHANGED) {     \
+    SetMsgHandled(TRUE);               \
+    func((HWND)wParam);                \
+    lResult = 0;                       \
+    if (!ref.get() || msg_handled_)    \
+      return TRUE;                     \
+  }
+
+// void OnPaletteIsChanging(CWindow wndPalChg)
+#define CR_MSG_WM_PALETTEISCHANGING(func) \
+  if (uMsg == WM_PALETTEISCHANGING) {     \
+    SetMsgHandled(TRUE);                  \
+    func((HWND)wParam);                   \
+    lResult = 0;                          \
+    if (!ref.get() || msg_handled_)       \
+      return TRUE;                        \
+  }
+
+// void OnDropFiles(HDROP hDropInfo)
+#define CR_MSG_WM_DROPFILES(func)   \
+  if (uMsg == WM_DROPFILES) {       \
+    SetMsgHandled(TRUE);            \
+    func((HDROP)wParam);            \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnWindowPosChanging(LPWINDOWPOS lpWndPos)
+#define CR_MSG_WM_WINDOWPOSCHANGING(func) \
+  if (uMsg == WM_WINDOWPOSCHANGING) {     \
+    SetMsgHandled(TRUE);                  \
+    func((LPWINDOWPOS)lParam);            \
+    lResult = 0;                          \
+    if (!ref.get() || msg_handled_)       \
+      return TRUE;                        \
+  }
+
+// void OnWindowPosChanged(LPWINDOWPOS lpWndPos)
+#define CR_MSG_WM_WINDOWPOSCHANGED(func) \
+  if (uMsg == WM_WINDOWPOSCHANGED) {     \
+    SetMsgHandled(TRUE);                 \
+    func((LPWINDOWPOS)lParam);           \
+    lResult = 0;                         \
+    if (!ref.get() || msg_handled_)      \
+      return TRUE;                       \
+  }
+
+// void OnExitMenuLoop(BOOL fIsTrackPopupMenu)
+#define CR_MSG_WM_EXITMENULOOP(func) \
+  if (uMsg == WM_EXITMENULOOP) {     \
+    SetMsgHandled(TRUE);             \
+    func((BOOL)wParam);              \
+    lResult = 0;                     \
+    if (!ref.get() || msg_handled_)  \
+      return TRUE;                   \
+  }
+
+// void OnEnterMenuLoop(BOOL fIsTrackPopupMenu)
+#define CR_MSG_WM_ENTERMENULOOP(func) \
+  if (uMsg == WM_ENTERMENULOOP) {     \
+    SetMsgHandled(TRUE);              \
+    func((BOOL)wParam);               \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
+#define CR_MSG_WM_STYLECHANGED(func)           \
+  if (uMsg == WM_STYLECHANGED) {               \
+    SetMsgHandled(TRUE);                       \
+    func((UINT)wParam, (LPSTYLESTRUCT)lParam); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnStyleChanging(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
+#define CR_MSG_WM_STYLECHANGING(func)          \
+  if (uMsg == WM_STYLECHANGING) {              \
+    SetMsgHandled(TRUE);                       \
+    func((UINT)wParam, (LPSTYLESTRUCT)lParam); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnSizing(UINT fwSide, LPRECT pRect)
+#define CR_MSG_WM_SIZING(func)          \
+  if (uMsg == WM_SIZING) {              \
+    SetMsgHandled(TRUE);                \
+    func((UINT)wParam, (LPRECT)lParam); \
+    lResult = TRUE;                     \
+    if (!ref.get() || msg_handled_)     \
+      return TRUE;                      \
+  }
+
+// void OnMoving(UINT fwSide, LPRECT pRect)
+#define CR_MSG_WM_MOVING(func)          \
+  if (uMsg == WM_MOVING) {              \
+    SetMsgHandled(TRUE);                \
+    func((UINT)wParam, (LPRECT)lParam); \
+    lResult = TRUE;                     \
+    if (!ref.get() || msg_handled_)     \
+      return TRUE;                      \
+  }
+
+// void OnCaptureChanged(CWindow wnd)
+#define CR_MSG_WM_CAPTURECHANGED(func) \
+  if (uMsg == WM_CAPTURECHANGED) {     \
+    SetMsgHandled(TRUE);               \
+    func((HWND)lParam);                \
+    lResult = 0;                       \
+    if (!ref.get() || msg_handled_)    \
+      return TRUE;                     \
+  }
+
+// BOOL OnDeviceChange(UINT nEventType, DWORD dwData)
+#define CR_MSG_WM_DEVICECHANGE(func)                      \
+  if (uMsg == WM_DEVICECHANGE) {                          \
+    SetMsgHandled(TRUE);                                  \
+    lResult = (LRESULT)func((UINT)wParam, (DWORD)lParam); \
+    if (!ref.get() || msg_handled_)                       \
+      return TRUE;                                        \
+  }
+
+// void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define CR_MSG_WM_COMMAND(func)                                    \
+  if (uMsg == WM_COMMAND) {                                        \
+    SetMsgHandled(TRUE);                                           \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                   \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// void OnDisplayChange(UINT uBitsPerPixel, gfx::Size sizeScreen)
+#define CR_MSG_WM_DISPLAYCHANGE(func)                                  \
+  if (uMsg == WM_DISPLAYCHANGE) {                                      \
+    SetMsgHandled(TRUE);                                               \
+    func((UINT)wParam,                                                 \
+         gfx::Size(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                       \
+    if (!ref.get() || msg_handled_)                                    \
+      return TRUE;                                                     \
+  }
+
+// void OnEnterSizeMove()
+#define CR_MSG_WM_ENTERSIZEMOVE(func) \
+  if (uMsg == WM_ENTERSIZEMOVE) {     \
+    SetMsgHandled(TRUE);              \
+    func();                           \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnExitSizeMove()
+#define CR_MSG_WM_EXITSIZEMOVE(func) \
+  if (uMsg == WM_EXITSIZEMOVE) {     \
+    SetMsgHandled(TRUE);             \
+    func();                          \
+    lResult = 0;                     \
+    if (!ref.get() || msg_handled_)  \
+      return TRUE;                   \
+  }
+
+// HFONT OnGetFont()
+#define CR_MSG_WM_GETFONT(func)     \
+  if (uMsg == WM_GETFONT) {         \
+    SetMsgHandled(TRUE);            \
+    lResult = (LRESULT)func();      \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// LRESULT OnGetHotKey()
+#define CR_MSG_WM_GETHOTKEY(func)   \
+  if (uMsg == WM_GETHOTKEY) {       \
+    SetMsgHandled(TRUE);            \
+    lResult = func();               \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// HICON OnGetIcon()
+#define CR_MSG_WM_GETICON(func)            \
+  if (uMsg == WM_GETICON) {                \
+    SetMsgHandled(TRUE);                   \
+    lResult = (LRESULT)func((UINT)wParam); \
+    if (!ref.get() || msg_handled_)        \
+      return TRUE;                         \
+  }
+
+// int OnGetText(int cchTextMax, LPTSTR lpszText)
+#define CR_MSG_WM_GETTEXT(func)                           \
+  if (uMsg == WM_GETTEXT) {                               \
+    SetMsgHandled(TRUE);                                  \
+    lResult = (LRESULT)func((int)wParam, (LPTSTR)lParam); \
+    if (!ref.get() || msg_handled_)                       \
+      return TRUE;                                        \
+  }
+
+// int OnGetTextLength()
+#define CR_MSG_WM_GETTEXTLENGTH(func) \
+  if (uMsg == WM_GETTEXTLENGTH) {     \
+    SetMsgHandled(TRUE);              \
+    lResult = (LRESULT)func();        \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// void OnHelp(LPHELPINFO lpHelpInfo)
+#define CR_MSG_WM_HELP(func)        \
+  if (uMsg == WM_HELP) {            \
+    SetMsgHandled(TRUE);            \
+    func((LPHELPINFO)lParam);       \
+    lResult = TRUE;                 \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnHotKey(int nHotKeyID, UINT uModifiers, UINT uVirtKey)
+#define CR_MSG_WM_HOTKEY(func)                                     \
+  if (uMsg == WM_HOTKEY) {                                         \
+    SetMsgHandled(TRUE);                                           \
+    func((int)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
+    lResult = 0;                                                   \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// void OnInputLangChange(DWORD dwCharSet, HKL hKbdLayout)
+#define CR_MSG_WM_INPUTLANGCHANGE(func) \
+  if (uMsg == WM_INPUTLANGCHANGE) {     \
+    SetMsgHandled(TRUE);                \
+    func((DWORD)wParam, (HKL)lParam);   \
+    lResult = TRUE;                     \
+    if (!ref.get() || msg_handled_)     \
+      return TRUE;                      \
+  }
+
+// void OnInputLangChangeRequest(BOOL bSysCharSet, HKL hKbdLayout)
+#define CR_MSG_WM_INPUTLANGCHANGEREQUEST(func) \
+  if (uMsg == WM_INPUTLANGCHANGEREQUEST) {     \
+    SetMsgHandled(TRUE);                       \
+    func((BOOL)wParam, (HKL)lParam);           \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnNextDlgCtl(BOOL bHandle, WPARAM wCtlFocus)
+#define CR_MSG_WM_NEXTDLGCTL(func)      \
+  if (uMsg == WM_NEXTDLGCTL) {          \
+    SetMsgHandled(TRUE);                \
+    func((BOOL)LOWORD(lParam), wParam); \
+    lResult = 0;                        \
+    if (!ref.get() || msg_handled_)     \
+      return TRUE;                      \
+  }
+
+// void OnNextMenu(int nVirtKey, LPMDINEXTMENU lpMdiNextMenu)
+#define CR_MSG_WM_NEXTMENU(func)              \
+  if (uMsg == WM_NEXTMENU) {                  \
+    SetMsgHandled(TRUE);                      \
+    func((int)wParam, (LPMDINEXTMENU)lParam); \
+    lResult = 0;                              \
+    if (!ref.get() || msg_handled_)           \
+      return TRUE;                            \
+  }
+
+// int OnNotifyFormat(CWindow wndFrom, int nCommand)
+#define CR_MSG_WM_NOTIFYFORMAT(func)                    \
+  if (uMsg == WM_NOTIFYFORMAT) {                        \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HWND)wParam, (int)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// BOOL OnPowerBroadcast(DWORD dwPowerEvent, DWORD dwData)
+#define CR_MSG_WM_POWERBROADCAST(func)                     \
+  if (uMsg == WM_POWERBROADCAST) {                         \
+    SetMsgHandled(TRUE);                                   \
+    lResult = (LRESULT)func((DWORD)wParam, (DWORD)lParam); \
+    if (!ref.get() || msg_handled_)                        \
+      return TRUE;                                         \
+  }
+
+// void OnPrint(CDCHandle dc, UINT uFlags)
+#define CR_MSG_WM_PRINT(func)        \
+  if (uMsg == WM_PRINT) {            \
+    SetMsgHandled(TRUE);             \
+    func((HDC)wParam, (UINT)lParam); \
+    lResult = 0;                     \
+    if (!ref.get() || msg_handled_)  \
+      return TRUE;                   \
+  }
+
+// void OnPrintClient(CDCHandle dc, UINT uFlags)
+#define CR_MSG_WM_PRINTCLIENT(func)  \
+  if (uMsg == WM_PRINTCLIENT) {      \
+    SetMsgHandled(TRUE);             \
+    func((HDC)wParam, (UINT)lParam); \
+    lResult = 0;                     \
+    if (!ref.get() || msg_handled_)  \
+      return TRUE;                   \
+  }
+
+// void OnRasDialEvent(RASCONNSTATE rasconnstate, DWORD dwError)
+#define CR_MSG_WM_RASDIALEVENT(func)           \
+  if (uMsg == WM_RASDIALEVENT) {               \
+    SetMsgHandled(TRUE);                       \
+    func((RASCONNSTATE)wParam, (DWORD)lParam); \
+    lResult = TRUE;                            \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnSetFont(CFont font, BOOL bRedraw)
+#define CR_MSG_WM_SETFONT(func)                \
+  if (uMsg == WM_SETFONT) {                    \
+    SetMsgHandled(TRUE);                       \
+    func((HFONT)wParam, (BOOL)LOWORD(lParam)); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// int OnSetHotKey(int nVirtKey, UINT uFlags)
+#define CR_MSG_WM_SETHOTKEY(func)                          \
+  if (uMsg == WM_SETHOTKEY) {                              \
+    SetMsgHandled(TRUE);                                   \
+    lResult = (LRESULT)func((int)LOBYTE(LOWORD(wParam)),   \
+                            (UINT)HIBYTE(LOWORD(wParam))); \
+    if (!ref.get() || msg_handled_)                        \
+      return TRUE;                                         \
+  }
+
+// HICON OnSetIcon(UINT uType, HICON hIcon)
+#define CR_MSG_WM_SETICON(func)                           \
+  if (uMsg == WM_SETICON) {                               \
+    SetMsgHandled(TRUE);                                  \
+    lResult = (LRESULT)func((UINT)wParam, (HICON)lParam); \
+    if (!ref.get() || msg_handled_)                       \
+      return TRUE;                                        \
+  }
+
+// void OnSetRedraw(BOOL bRedraw)
+#define CR_MSG_WM_SETREDRAW(func)   \
+  if (uMsg == WM_SETREDRAW) {       \
+    SetMsgHandled(TRUE);            \
+    func((BOOL)wParam);             \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// int OnSetText(LPCTSTR lpstrText)
+#define CR_MSG_WM_SETTEXT(func)               \
+  if (uMsg == WM_SETTEXT) {                   \
+    SetMsgHandled(TRUE);                      \
+    lResult = (LRESULT)func((LPCTSTR)lParam); \
+    if (!ref.get() || msg_handled_)           \
+      return TRUE;                            \
+  }
+
+// void OnUserChanged()
+#define CR_MSG_WM_USERCHANGED(func) \
+  if (uMsg == WM_USERCHANGED) {     \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+///////////////////////////////////////////////////////////////////////////////
+// New NT4 & NT5 messages
+
+#if (_WIN32_WINNT >= 0x0400)
+
+// void OnMouseHover(WPARAM wParam, CPoint ptPos)
+#define CR_MSG_WM_MOUSEHOVER(func)                                      \
+  if (uMsg == WM_MOUSEHOVER) {                                          \
+    SetMsgHandled(TRUE);                                                \
+    func(wParam,                                                        \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnMouseLeave()
+#define CR_MSG_WM_MOUSELEAVE(func)  \
+  if (uMsg == WM_MOUSELEAVE) {      \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+#endif /* _WIN32_WINNT >= 0x0400 */
+
+#if (WINVER >= 0x0500)
+
+// void OnMenuRButtonUp(WPARAM wParam, CMenu menu)
+#define CR_MSG_WM_MENURBUTTONUP(func) \
+  if (uMsg == WM_MENURBUTTONUP) {     \
+    SetMsgHandled(TRUE);              \
+    func(wParam, (HMENU)lParam);      \
+    lResult = 0;                      \
+    if (!ref.get() || msg_handled_)   \
+      return TRUE;                    \
+  }
+
+// LRESULT OnMenuDrag(WPARAM wParam, CMenu menu)
+#define CR_MSG_WM_MENUDRAG(func)           \
+  if (uMsg == WM_MENUDRAG) {               \
+    SetMsgHandled(TRUE);                   \
+    lResult = func(wParam, (HMENU)lParam); \
+    if (!ref.get() || msg_handled_)        \
+      return TRUE;                         \
+  }
+
+// LRESULT OnMenuGetObject(PMENUGETOBJECTINFO info)
+#define CR_MSG_WM_MENUGETOBJECT(func)           \
+  if (uMsg == WM_MENUGETOBJECT) {               \
+    SetMsgHandled(TRUE);                        \
+    lResult = func((PMENUGETOBJECTINFO)lParam); \
+    if (!ref.get() || msg_handled_)             \
+      return TRUE;                              \
+  }
+
+// void OnUnInitMenuPopup(UINT nID, CMenu menu)
+#define CR_MSG_WM_UNINITMENUPOPUP(func)        \
+  if (uMsg == WM_UNINITMENUPOPUP) {            \
+    SetMsgHandled(TRUE);                       \
+    func((UINT)HIWORD(lParam), (HMENU)wParam); \
+    lResult = 0;                               \
+    if (!ref.get() || msg_handled_)            \
+      return TRUE;                             \
+  }
+
+// void OnMenuCommand(WPARAM nIndex, CMenu menu)
+#define CR_MSG_WM_MENUCOMMAND(func) \
+  if (uMsg == WM_MENUCOMMAND) {     \
+    SetMsgHandled(TRUE);            \
+    func(wParam, (HMENU)lParam);    \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+#endif /* WINVER >= 0x0500 */
+
+#if (_WIN32_WINNT >= 0x0500)
+
+// BOOL OnAppCommand(CWindow wndFocus, short cmd, WORD uDevice, int dwKeys)
+#define CR_MSG_WM_APPCOMMAND(func)                                             \
+  if (uMsg == WM_APPCOMMAND) {                                                 \
+    SetMsgHandled(TRUE);                                                       \
+    lResult =                                                                  \
+        (LRESULT)func((HWND)wParam, GET_APPCOMMAND_LPARAM(lParam),             \
+                      GET_DEVICE_LPARAM(lParam), GET_KEYSTATE_LPARAM(lParam)); \
+    if (!ref.get() || msg_handled_)                                            \
+      return TRUE;                                                             \
+  }
+
+// void OnNCXButtonDown(int fwButton, short nHittest, CPoint ptPos)
+#define CR_MSG_WM_NCXBUTTONDOWN(func)                                   \
+  if (uMsg == WM_NCXBUTTONDOWN) {                                       \
+    SetMsgHandled(TRUE);                                                \
+    func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam),      \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNCXButtonUp(int fwButton, short nHittest, CPoint ptPos)
+#define CR_MSG_WM_NCXBUTTONUP(func)                                     \
+  if (uMsg == WM_NCXBUTTONUP) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam),      \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnNCXButtonDblClk(int fwButton, short nHittest, CPoint ptPos)
+#define CR_MSG_WM_NCXBUTTONDBLCLK(func)                                 \
+  if (uMsg == WM_NCXBUTTONDBLCLK) {                                     \
+    SetMsgHandled(TRUE);                                                \
+    func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam),      \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnXButtonDown(int fwButton, int dwKeys, CPoint ptPos)
+#define CR_MSG_WM_XBUTTONDOWN(func)                                     \
+  if (uMsg == WM_XBUTTONDOWN) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam),       \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnXButtonUp(int fwButton, int dwKeys, CPoint ptPos)
+#define CR_MSG_WM_XBUTTONUP(func)                                       \
+  if (uMsg == WM_XBUTTONUP) {                                           \
+    SetMsgHandled(TRUE);                                                \
+    func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam),       \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnXButtonDblClk(int fwButton, int dwKeys, CPoint ptPos)
+#define CR_MSG_WM_XBUTTONDBLCLK(func)                                   \
+  if (uMsg == WM_XBUTTONDBLCLK) {                                       \
+    SetMsgHandled(TRUE);                                                \
+    func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam),       \
+         gfx::Point(CR_GET_X_LPARAM(lParam), CR_GET_Y_LPARAM(lParam))); \
+    lResult = 0;                                                        \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnChangeUIState(WORD nAction, WORD nState)
+#define CR_MSG_WM_CHANGEUISTATE(func)     \
+  if (uMsg == WM_CHANGEUISTATE) {         \
+    SetMsgHandled(TRUE);                  \
+    func(LOWORD(wParam), HIWORD(wParam)); \
+    lResult = 0;                          \
+    if (!ref.get() || msg_handled_)       \
+      return TRUE;                        \
+  }
+
+// void OnUpdateUIState(WORD nAction, WORD nState)
+#define CR_MSG_WM_UPDATEUISTATE(func)     \
+  if (uMsg == WM_UPDATEUISTATE) {         \
+    SetMsgHandled(TRUE);                  \
+    func(LOWORD(wParam), HIWORD(wParam)); \
+    lResult = 0;                          \
+    if (!ref.get() || msg_handled_)       \
+      return TRUE;                        \
+  }
+
+// LRESULT OnQueryUIState()
+#define CR_MSG_WM_QUERYUISTATE(func) \
+  if (uMsg == WM_QUERYUISTATE) {     \
+    SetMsgHandled(TRUE);             \
+    lResult = func();                \
+    if (!ref.get() || msg_handled_)  \
+      return TRUE;                   \
+  }
+
+#endif  // (_WIN32_WINNT >= 0x0500)
+
+#if (_WIN32_WINNT >= 0x0501)
+
+// void OnInput(WPARAM RawInputCode, HRAWINPUT hRawInput)
+#define CR_MSG_WM_INPUT(func)                                  \
+  if (uMsg == WM_INPUT) {                                      \
+    SetMsgHandled(TRUE);                                       \
+    func(GET_RAWINPUT_CODE_WPARAM(wParam), (HRAWINPUT)lParam); \
+    lResult = 0;                                               \
+    if (!ref.get() || msg_handled_)                            \
+      return TRUE;                                             \
+  }
+
+// void OnUniChar(TCHAR nChar, UINT nRepCnt, UINT nFlags)
+#define CR_MSG_WM_UNICHAR(func)                            \
+  if (uMsg == WM_UNICHAR) {                                \
+    SetMsgHandled(TRUE);                                   \
+    func((TCHAR)wParam, (UINT)lParam & 0xFFFF,             \
+         (UINT)((lParam & 0xFFFF0000) >> 16));             \
+    if (!ref.get() || msg_handled_) {                      \
+      lResult = (wParam == UNICODE_NOCHAR) ? TRUE : FALSE; \
+      return TRUE;                                         \
+    }                                                      \
+  }
+
+// OnThemeChanged()
+#define CR_MSG_WM_THEMECHANGED(func) \
+  if (uMsg == WM_THEMECHANGED) {     \
+    SetMsgHandled(TRUE);             \
+    func();                          \
+    lResult = 0;                     \
+    if (!ref.get() || msg_handled_)  \
+      return TRUE;                   \
+  }
+
+#endif /* _WIN32_WINNT >= 0x0501 */
+
+///////////////////////////////////////////////////////////////////////////////
+// ATL defined messages
+
+// BOOL OnForwardMsg(LPMSG Msg, DWORD nUserData)
+#define CR_MSG_WM_FORWARDMSG(func)                         \
+  if (uMsg == WM_FORWARDMSG) {                             \
+    SetMsgHandled(TRUE);                                   \
+    lResult = (LRESULT)func((LPMSG)lParam, (DWORD)wParam); \
+    if (!ref.get() || msg_handled_)                        \
+      return TRUE;                                         \
+  }
+
+///////////////////////////////////////////////////////////////////////////////
+// Dialog specific messages
+
+// LRESULT OnDMGetDefID()
+#define MSG_DM_GETDEFID(func)       \
+  if (uMsg == DM_GETDEFID) {        \
+    SetMsgHandled(TRUE);            \
+    lResult = func();               \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnDMSetDefID(UINT DefID)
+#define MSG_DM_SETDEFID(func)       \
+  if (uMsg == DM_SETDEFID) {        \
+    SetMsgHandled(TRUE);            \
+    func((UINT)wParam);             \
+    lResult = TRUE;                 \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnDMReposition()
+#define MSG_DM_REPOSITION(func)     \
+  if (uMsg == DM_REPOSITION) {      \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+///////////////////////////////////////////////////////////////////////////////
+// Reflected messages
+
+// void OnReflectedCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define MSG_OCM_COMMAND(func)                                      \
+  if (uMsg == OCM_COMMAND) {                                       \
+    SetMsgHandled(TRUE);                                           \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                   \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// LRESULT OnReflectedNotify(int idCtrl, LPNMHDR pnmh)
+#define MSG_OCM_NOTIFY(func)                      \
+  if (uMsg == OCM_NOTIFY) {                       \
+    SetMsgHandled(TRUE);                          \
+    lResult = func((int)wParam, (LPNMHDR)lParam); \
+    if (!ref.get() || msg_handled_)               \
+      return TRUE;                                \
+  }
+
+// void OnReflectedParentNotify(UINT message, UINT nChildID, LPARAM lParam)
+#define MSG_OCM_PARENTNOTIFY(func)                            \
+  if (uMsg == OCM_PARENTNOTIFY) {                             \
+    SetMsgHandled(TRUE);                                      \
+    func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \
+    lResult = 0;                                              \
+    if (!ref.get() || msg_handled_)                           \
+      return TRUE;                                            \
+  }
+
+// void OnReflectedDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
+#define MSG_OCM_DRAWITEM(func)                    \
+  if (uMsg == OCM_DRAWITEM) {                     \
+    SetMsgHandled(TRUE);                          \
+    func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \
+    lResult = TRUE;                               \
+    if (!ref.get() || msg_handled_)               \
+      return TRUE;                                \
+  }
+
+// void OnReflectedMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT
+// lpMeasureItemStruct)
+#define MSG_OCM_MEASUREITEM(func)                    \
+  if (uMsg == OCM_MEASUREITEM) {                     \
+    SetMsgHandled(TRUE);                             \
+    func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \
+    lResult = TRUE;                                  \
+    if (!ref.get() || msg_handled_)                  \
+      return TRUE;                                   \
+  }
+
+// int OnReflectedCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT
+// lpCompareItemStruct)
+#define MSG_OCM_COMPAREITEM(func)                                       \
+  if (uMsg == OCM_COMPAREITEM) {                                        \
+    SetMsgHandled(TRUE);                                                \
+    lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnReflectedDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct)
+#define MSG_OCM_DELETEITEM(func)                    \
+  if (uMsg == OCM_DELETEITEM) {                     \
+    SetMsgHandled(TRUE);                            \
+    func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \
+    lResult = TRUE;                                 \
+    if (!ref.get() || msg_handled_)                 \
+      return TRUE;                                  \
+  }
+
+// int OnReflectedVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox)
+#define MSG_OCM_VKEYTOITEM(func)                                        \
+  if (uMsg == OCM_VKEYTOITEM) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), \
+                            (HWND)lParam);                              \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// int OnReflectedCharToItem(UINT nChar, UINT nIndex, CListBox listBox)
+#define MSG_OCM_CHARTOITEM(func)                                        \
+  if (uMsg == OCM_CHARTOITEM) {                                         \
+    SetMsgHandled(TRUE);                                                \
+    lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), \
+                            (HWND)lParam);                              \
+    if (!ref.get() || msg_handled_)                                     \
+      return TRUE;                                                      \
+  }
+
+// void OnReflectedHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
+#define MSG_OCM_HSCROLL(func)                                       \
+  if (uMsg == OCM_HSCROLL) {                                        \
+    SetMsgHandled(TRUE);                                            \
+    func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                    \
+    if (!ref.get() || msg_handled_)                                 \
+      return TRUE;                                                  \
+  }
+
+// void OnReflectedVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
+#define MSG_OCM_VSCROLL(func)                                       \
+  if (uMsg == OCM_VSCROLL) {                                        \
+    SetMsgHandled(TRUE);                                            \
+    func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                    \
+    if (!ref.get() || msg_handled_)                                 \
+      return TRUE;                                                  \
+  }
+
+// HBRUSH OnReflectedCtlColorEdit(CDCHandle dc, CEdit edit)
+#define MSG_OCM_CTLCOLOREDIT(func)                      \
+  if (uMsg == OCM_CTLCOLOREDIT) {                       \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnReflectedCtlColorListBox(CDCHandle dc, CListBox listBox)
+#define MSG_OCM_CTLCOLORLISTBOX(func)                   \
+  if (uMsg == OCM_CTLCOLORLISTBOX) {                    \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnReflectedCtlColorBtn(CDCHandle dc, CButton button)
+#define MSG_OCM_CTLCOLORBTN(func)                       \
+  if (uMsg == OCM_CTLCOLORBTN) {                        \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnReflectedCtlColorDlg(CDCHandle dc, CWindow wnd)
+#define MSG_OCM_CTLCOLORDLG(func)                       \
+  if (uMsg == OCM_CTLCOLORDLG) {                        \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnReflectedCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar)
+#define MSG_OCM_CTLCOLORSCROLLBAR(func)                 \
+  if (uMsg == OCM_CTLCOLORSCROLLBAR) {                  \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+// HBRUSH OnReflectedCtlColorStatic(CDCHandle dc, CStatic wndStatic)
+#define MSG_OCM_CTLCOLORSTATIC(func)                    \
+  if (uMsg == OCM_CTLCOLORSTATIC) {                     \
+    SetMsgHandled(TRUE);                                \
+    lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
+    if (!ref.get() || msg_handled_)                     \
+      return TRUE;                                      \
+  }
+
+///////////////////////////////////////////////////////////////////////////////
+// Edit specific messages
+
+// void OnClear()
+#define CR_MSG_WM_CLEAR(func)       \
+  if (uMsg == WM_CLEAR) {           \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnCopy()
+#define CR_MSG_WM_COPY(func)        \
+  if (uMsg == WM_COPY) {            \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnCut()
+#define CR_MSG_WM_CUT(func)         \
+  if (uMsg == WM_CUT) {             \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnPaste()
+#define CR_MSG_WM_PASTE(func)       \
+  if (uMsg == WM_PASTE) {           \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+// void OnUndo()
+#define CR_MSG_WM_UNDO(func)        \
+  if (uMsg == WM_UNDO) {            \
+    SetMsgHandled(TRUE);            \
+    func();                         \
+    lResult = 0;                    \
+    if (!ref.get() || msg_handled_) \
+      return TRUE;                  \
+  }
+
+///////////////////////////////////////////////////////////////////////////////
+// Generic message handlers
+
+// LRESULT OnMessageHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam)
+#define CR_MESSAGE_HANDLER_EX(msg, func)  \
+  if (uMsg == msg) {                      \
+    SetMsgHandled(TRUE);                  \
+    lResult = func(uMsg, wParam, lParam); \
+    if (!ref.get() || msg_handled_)       \
+      return TRUE;                        \
+  }
+
+// LRESULT OnMessageRangeHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam)
+#define CR_MESSAGE_RANGE_HANDLER_EX(msgFirst, msgLast, func) \
+  if (uMsg >= msgFirst && uMsg <= msgLast) {                 \
+    SetMsgHandled(TRUE);                                     \
+    lResult = func(uMsg, wParam, lParam);                    \
+    if (!ref.get() || msg_handled_)                          \
+      return TRUE;                                           \
+  }
+
+///////////////////////////////////////////////////////////////////////////////
+// Commands and notifications
+
+// void OnCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define CR_COMMAND_HANDLER_EX(id, code, func)                                 \
+  if (uMsg == WM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) { \
+    SetMsgHandled(TRUE);                                                      \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam);            \
+    lResult = 0;                                                              \
+    if (!ref.get() || msg_handled_)                                           \
+      return TRUE;                                                            \
+  }
+
+// void OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define CR_COMMAND_ID_HANDLER_EX(id, func)                         \
+  if (uMsg == WM_COMMAND && id == LOWORD(wParam)) {                \
+    SetMsgHandled(TRUE);                                           \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                   \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// void OnCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define CR_COMMAND_CODE_HANDLER_EX(code, func)                     \
+  if (uMsg == WM_COMMAND && code == HIWORD(wParam)) {              \
+    SetMsgHandled(TRUE);                                           \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                   \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// LRESULT OnNotifyHandlerEX(LPNMHDR pnmh)
+#define CR_NOTIFY_HANDLER_EX(id, cd, func)                  \
+  if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && \
+      id == ((LPNMHDR)lParam)->idFrom) {                    \
+    SetMsgHandled(TRUE);                                    \
+    lResult = func((LPNMHDR)lParam);                        \
+    if (!ref.get() || msg_handled_)                         \
+      return TRUE;                                          \
+  }
+
+// LRESULT OnNotifyIDHandlerEX(LPNMHDR pnmh)
+#define CR_NOTIFY_ID_HANDLER_EX(id, func)                     \
+  if (uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) { \
+    SetMsgHandled(TRUE);                                      \
+    lResult = func((LPNMHDR)lParam);                          \
+    if (!ref.get() || msg_handled_)                           \
+      return TRUE;                                            \
+  }
+
+// LRESULT OnNotifyCodeHandlerEX(LPNMHDR pnmh)
+#define CR_NOTIFY_CODE_HANDLER_EX(cd, func)                 \
+  if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) { \
+    SetMsgHandled(TRUE);                                    \
+    lResult = func((LPNMHDR)lParam);                        \
+    if (!ref.get() || msg_handled_)                         \
+      return TRUE;                                          \
+  }
+
+// void OnCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define CR_COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func)         \
+  if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst &&           \
+      LOWORD(wParam) <= idLast) {                                  \
+    SetMsgHandled(TRUE);                                           \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                   \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// void OnCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
+#define CR_COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \
+  if (uMsg == WM_COMMAND && code == HIWORD(wParam) &&                 \
+      LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) {        \
+    SetMsgHandled(TRUE);                                              \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam);    \
+    lResult = 0;                                                      \
+    if (!ref.get() || msg_handled_)                                   \
+      return TRUE;                                                    \
+  }
+
+// LRESULT OnNotifyRangeHandlerEX(LPNMHDR pnmh)
+#define CR_NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func)          \
+  if (uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && \
+      ((LPNMHDR)lParam)->idFrom <= idLast) {                       \
+    SetMsgHandled(TRUE);                                           \
+    lResult = func((LPNMHDR)lParam);                               \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// LRESULT OnNotifyRangeCodeHandlerEX(LPNMHDR pnmh)
+#define CR_NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \
+  if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code &&        \
+      ((LPNMHDR)lParam)->idFrom >= idFirst &&                      \
+      ((LPNMHDR)lParam)->idFrom <= idLast) {                       \
+    SetMsgHandled(TRUE);                                           \
+    lResult = func((LPNMHDR)lParam);                               \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// LRESULT OnReflectedCommandHandlerEX(UINT uNotifyCode, int nID, CWindow
+// wndCtl)
+#define CR_REFLECTED_COMMAND_HANDLER_EX(id, code, func)                        \
+  if (uMsg == OCM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) { \
+    SetMsgHandled(TRUE);                                                       \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam);             \
+    lResult = 0;                                                               \
+    if (!ref.get() || msg_handled_)                                            \
+      return TRUE;                                                             \
+  }
+
+// LRESULT OnReflectedCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow
+// wndCtl)
+#define CR_REFLECTED_COMMAND_ID_HANDLER_EX(id, func)               \
+  if (uMsg == OCM_COMMAND && id == LOWORD(wParam)) {               \
+    SetMsgHandled(TRUE);                                           \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                   \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// LRESULT OnReflectedCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow
+// wndCtl)
+#define CR_REFLECTED_COMMAND_CODE_HANDLER_EX(code, func)           \
+  if (uMsg == OCM_COMMAND && code == HIWORD(wParam)) {             \
+    SetMsgHandled(TRUE);                                           \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
+    lResult = 0;                                                   \
+    if (!ref.get() || msg_handled_)                                \
+      return TRUE;                                                 \
+  }
+
+// LRESULT OnReflectedNotifyHandlerEX(LPNMHDR pnmh)
+#define CR_REFLECTED_NOTIFY_HANDLER_EX(id, cd, func)         \
+  if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && \
+      id == ((LPNMHDR)lParam)->idFrom) {                     \
+    SetMsgHandled(TRUE);                                     \
+    lResult = func((LPNMHDR)lParam);                         \
+    if (!ref.get() || msg_handled_)                          \
+      return TRUE;                                           \
+  }
+
+// LRESULT OnReflectedNotifyIDHandlerEX(LPNMHDR pnmh)
+#define CR_REFLECTED_NOTIFY_ID_HANDLER_EX(id, func)            \
+  if (uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) { \
+    SetMsgHandled(TRUE);                                       \
+    lResult = func((LPNMHDR)lParam);                           \
+    if (!ref.get() || msg_handled_)                            \
+      return TRUE;                                             \
+  }
+
+// LRESULT OnReflectedNotifyCodeHandlerEX(LPNMHDR pnmh)
+#define CR_REFLECTED_NOTIFY_CODE_HANDLER_EX(cd, func)        \
+  if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) { \
+    SetMsgHandled(TRUE);                                     \
+    lResult = func((LPNMHDR)lParam);                         \
+    if (!ref.get() || msg_handled_)                          \
+      return TRUE;                                           \
+  }
+
+// void OnReflectedCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow
+// wndCtl)
+#define CR_REFLECTED_COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \
+  if (uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst &&            \
+      LOWORD(wParam) <= idLast) {                                    \
+    SetMsgHandled(TRUE);                                             \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam);   \
+    lResult = 0;                                                     \
+    if (!ref.get() || msg_handled_)                                  \
+      return TRUE;                                                   \
+  }
+
+// void OnReflectedCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow
+// wndCtl)
+#define CR_REFLECTED_COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, \
+                                                   func)                  \
+  if (uMsg == OCM_COMMAND && code == HIWORD(wParam) &&                    \
+      LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) {            \
+    SetMsgHandled(TRUE);                                                  \
+    func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam);        \
+    lResult = 0;                                                          \
+    if (!ref.get() || msg_handled_)                                       \
+      return TRUE;                                                        \
+  }
+
+// LRESULT OnReflectedNotifyRangeHandlerEX(LPNMHDR pnmh)
+#define CR_REFLECTED_NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \
+  if (uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && \
+      ((LPNMHDR)lParam)->idFrom <= idLast) {                        \
+    SetMsgHandled(TRUE);                                            \
+    lResult = func((LPNMHDR)lParam);                                \
+    if (!ref.get() || msg_handled_)                                 \
+      return TRUE;                                                  \
+  }
+
+// LRESULT OnReflectedNotifyRangeCodeHandlerEX(LPNMHDR pnmh)
+#define CR_REFLECTED_NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \
+  if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code &&                 \
+      ((LPNMHDR)lParam)->idFrom >= idFirst &&                                \
+      ((LPNMHDR)lParam)->idFrom <= idLast) {                                 \
+    SetMsgHandled(TRUE);                                                     \
+    lResult = func((LPNMHDR)lParam);                                         \
+    if (!ref.get() || msg_handled_)                                          \
+      return TRUE;                                                           \
+  }
+
+#define CR_DEFLATE_RECT(rect, by)   \
+  {                                 \
+    (rect)->left += (by)->left;     \
+    (rect)->top += (by)->top;       \
+    (rect)->right -= (by)->right;   \
+    (rect)->bottom -= (by)->bottom; \
+  }
+
+#define CR_POINT_INITIALIZER_FROM_LPARAM(lparam) \
+  { LOWORD(lparam), HIWORD(lparam) }
+
+#endif  // UI_GFX_WIN_MSG_UTIL_H_
diff --git a/ui/gfx/win/physical_size.cc b/ui/gfx/win/physical_size.cc
new file mode 100644
index 0000000..39978f7
--- /dev/null
+++ b/ui/gfx/win/physical_size.cc
@@ -0,0 +1,163 @@
+// Copyright 2016 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 "ui/gfx/win/physical_size.h"
+
+#include <windows.h>
+#include <setupapi.h>
+
+#include <iostream>
+#include <memory>
+
+#include "base/check_op.h"
+#include "base/memory/free_deleter.h"
+#include "base/scoped_generic.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/registry.h"
+
+// This GUID {E6F07B5F-EE97-4A90-B076-33F57BF4EAA7} was taken from
+// https://msdn.microsoft.com/en-us/library/windows/hardware/ff545901.aspx
+const GUID GUID_DEVICEINTERFACE_MONITOR = {
+    0xE6F07B5F,
+    0xEE97,
+    0x4A90,
+    {0xB0, 0x76, 0x33, 0xF5, 0x7B, 0xF4, 0xEA, 0xA7}};
+
+namespace {
+
+struct DeviceInfoListScopedTraits {
+  static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; }
+
+  static void Free(HDEVINFO h) { SetupDiDestroyDeviceInfoList(h); }
+};
+
+bool GetSizeFromRegistry(HDEVINFO device_info_list,
+                         SP_DEVINFO_DATA* device_info,
+                         int* width_mm,
+                         int* height_mm) {
+  base::win::RegKey reg_key(SetupDiOpenDevRegKey(
+      device_info_list, device_info, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ));
+  if (!reg_key.Valid())
+    return false;
+
+  BYTE data[128];  // EDID block is exactly 128 bytes long.
+  ZeroMemory(&data[0], sizeof(data));
+  DWORD data_length = sizeof(data);
+  LONG return_value =
+      reg_key.ReadValue(L"EDID", &data[0], &data_length, nullptr);
+  if (return_value != ERROR_SUCCESS)
+    return false;
+
+  // Byte 54 is the start of the first descriptor block, which contains the
+  // required timing information with the highest preference, and 12 bytes
+  // into that block is the size information.
+  // 66: width least significant bits
+  // 67: height least significant bits
+  // 68: 4 bits for each of width and height most significant bits
+  if (data[54] == 0)
+    return false;
+  const int w = ((data[68] & 0xF0) << 4) + data[66];
+  const int h = ((data[68] & 0x0F) << 8) + data[67];
+
+  if (w <= 0 || h <= 0)
+    return false;
+
+  *width_mm = w;
+  *height_mm = h;
+
+  return true;
+}
+
+bool GetInterfaceDetailAndDeviceInfo(
+    HDEVINFO device_info_list,
+    SP_DEVICE_INTERFACE_DATA* interface_data,
+    std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter>*
+        interface_detail,
+    SP_DEVINFO_DATA* device_info) {
+  DCHECK_EQ(sizeof(*device_info), device_info->cbSize);
+  DWORD buffer_size;
+  // This call populates device_info. It will also fail, but if the error is
+  // "insufficient buffer" then it will set buffer_size and we can call again
+  // with an allocated buffer.
+  SetupDiGetDeviceInterfaceDetail(device_info_list, interface_data, nullptr, 0,
+                                  &buffer_size, device_info);
+  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+    return false;
+
+  interface_detail->reset(
+      reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(malloc(buffer_size)));
+  (*interface_detail)->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+  return SetupDiGetDeviceInterfaceDetail(device_info_list, interface_data,
+                                         interface_detail->get(), buffer_size,
+                                         nullptr, nullptr) != 0;
+}
+
+}  // namespace
+
+namespace gfx {
+
+// The physical size information is only available by looking in the EDID block
+// via setup. However setup has the device path and not the device name that we
+// use to identify displays. Therefore after looking up a device via setup we
+// need to find the display again via EnumDisplayDevices (matching device path
+// to the device ID of the display's interface) so we can return the device name
+// (available from the interface's attached monitor).
+std::vector<PhysicalDisplaySize> GetPhysicalSizeForDisplays() {
+  std::vector<PhysicalDisplaySize> out;
+
+  base::ScopedGeneric<HDEVINFO, DeviceInfoListScopedTraits> device_info_list(
+      SetupDiGetClassDevs(&GUID_DEVICEINTERFACE_MONITOR, nullptr, nullptr,
+                          DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+
+  if (!device_info_list.is_valid())
+    return out;
+
+  SP_DEVICE_INTERFACE_DATA interface_data = {};
+  interface_data.cbSize = sizeof(interface_data);
+  int interface_index = 0;
+  while (SetupDiEnumDeviceInterfaces(device_info_list.get(), nullptr,
+                                     &GUID_DEVICEINTERFACE_MONITOR,
+                                     interface_index++, &interface_data)) {
+    std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter>
+        interface_detail;
+    SP_DEVINFO_DATA device_info = {};
+    device_info.cbSize = sizeof(device_info);
+    bool get_info_succeeded =
+        GetInterfaceDetailAndDeviceInfo(device_info_list.get(), &interface_data,
+                                        &interface_detail, &device_info);
+    if (!get_info_succeeded)
+      continue;
+
+    DISPLAY_DEVICE display_device = {};
+    display_device.cb = sizeof(display_device);
+    int display_index = 0;
+    while (EnumDisplayDevices(nullptr, display_index++, &display_device,
+                              EDD_GET_DEVICE_INTERFACE_NAME)) {
+      DISPLAY_DEVICE attached_device = {};
+      attached_device.cb = sizeof(attached_device);
+      int attached_index = 0;
+      while (EnumDisplayDevices(display_device.DeviceName, attached_index++,
+                                &attached_device,
+                                EDD_GET_DEVICE_INTERFACE_NAME)) {
+        wchar_t* attached_device_id = attached_device.DeviceID;
+        wchar_t* setup_device_path = interface_detail->DevicePath;
+        if (wcsicmp(attached_device_id, setup_device_path) == 0) {
+          int width_mm;
+          int height_mm;
+          bool found = GetSizeFromRegistry(device_info_list.get(), &device_info,
+                                           &width_mm, &height_mm);
+          if (found) {
+            out.push_back(
+                PhysicalDisplaySize(base::WideToUTF8(display_device.DeviceName),
+                                    width_mm, height_mm));
+          }
+          break;
+        }
+      }
+    }
+  }
+  return out;
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/win/physical_size.h b/ui/gfx/win/physical_size.h
new file mode 100644
index 0000000..5b768ad
--- /dev/null
+++ b/ui/gfx/win/physical_size.h
@@ -0,0 +1,31 @@
+// Copyright 2016 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.
+
+#ifndef UI_GFX_WIN_PHYSICAL_SIZE_H_
+#define UI_GFX_WIN_PHYSICAL_SIZE_H_
+
+#include <string>
+#include <vector>
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+struct PhysicalDisplaySize {
+  PhysicalDisplaySize(const std::string& display_name,
+                      int width_mm,
+                      int height_mm)
+      : display_name(display_name), width_mm(width_mm), height_mm(height_mm) {}
+
+  std::string display_name;
+  int width_mm;
+  int height_mm;
+};
+
+// Gets the physical size for all displays.
+GFX_EXPORT std::vector<PhysicalDisplaySize> GetPhysicalSizeForDisplays();
+
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_PHYSICAL_SIZE_H_
diff --git a/ui/gfx/win/rendering_window_manager.cc b/ui/gfx/win/rendering_window_manager.cc
new file mode 100644
index 0000000..8536882
--- /dev/null
+++ b/ui/gfx/win/rendering_window_manager.cc
@@ -0,0 +1,80 @@
+// Copyright 2016 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 "ui/gfx/win/rendering_window_manager.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+
+namespace gfx {
+
+// static
+RenderingWindowManager* RenderingWindowManager::GetInstance() {
+  static base::NoDestructor<RenderingWindowManager> instance;
+  return instance.get();
+}
+
+void RenderingWindowManager::RegisterParent(HWND parent) {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  registered_hwnds_.emplace(parent, nullptr);
+}
+
+void RenderingWindowManager::RegisterChild(HWND parent,
+                                           HWND child,
+                                           DWORD expected_child_process_id) {
+  if (!child)
+    return;
+
+  // This can be called from any thread, if we're not on the correct thread then
+  // PostTask back to the UI thread before doing anything.
+  if (!task_runner_->BelongsToCurrentThread()) {
+    task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&RenderingWindowManager::RegisterChild,
+                                  base::Unretained(this), parent, child,
+                                  expected_child_process_id));
+    return;
+  }
+
+  // Check that |parent| was registered as a HWND that could have a child HWND.
+  auto it = registered_hwnds_.find(parent);
+  if (it == registered_hwnds_.end())
+    return;
+
+  // Check that |child| belongs to the GPU process.
+  DWORD child_process_id = 0;
+  DWORD child_thread_id = GetWindowThreadProcessId(child, &child_process_id);
+  if (!child_thread_id || child_process_id != expected_child_process_id) {
+    DLOG(ERROR) << "Child HWND not owned by GPU process.";
+    return;
+  }
+
+  it->second = child;
+
+  ::SetParent(child, parent);
+  // Move D3D window behind Chrome's window to avoid losing some messages.
+  ::SetWindowPos(child, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+}
+
+void RenderingWindowManager::UnregisterParent(HWND parent) {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  registered_hwnds_.erase(parent);
+}
+
+bool RenderingWindowManager::HasValidChildWindow(HWND parent) {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  auto it = registered_hwnds_.find(parent);
+  if (it == registered_hwnds_.end())
+    return false;
+  return !!it->second && ::IsWindow(it->second);
+}
+
+RenderingWindowManager::RenderingWindowManager()
+    : task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
+
+RenderingWindowManager::~RenderingWindowManager() = default;
+
+}  // namespace gfx
diff --git a/ui/gfx/win/rendering_window_manager.h b/ui/gfx/win/rendering_window_manager.h
new file mode 100644
index 0000000..dd729b1
--- /dev/null
+++ b/ui/gfx/win/rendering_window_manager.h
@@ -0,0 +1,59 @@
+// Copyright 2016 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.
+
+#ifndef UI_GFX_WIN_RENDERING_WINDOW_MANAGER_H_
+#define UI_GFX_WIN_RENDERING_WINDOW_MANAGER_H_
+
+#include <windows.h>
+
+#include "base/containers/flat_map.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/no_destructor.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace gfx {
+
+// This keeps track of whether a given HWND has a child window which the GPU
+// process renders into. This should only be used from the UI thread unless
+// otherwise noted.
+class GFX_EXPORT RenderingWindowManager {
+ public:
+  // The first call to GetInstance() should happen on the UI thread.
+  static RenderingWindowManager* GetInstance();
+
+  RenderingWindowManager(const RenderingWindowManager&) = delete;
+  RenderingWindowManager& operator=(const RenderingWindowManager&) = delete;
+
+  void RegisterParent(HWND parent);
+  // Registers |child| as child window for |parent|. Allows the GPU process to
+  // draw into the |child| HWND instead of |parent|. This will fail and do
+  // nothing if:
+  //   1. |parent| isn't registered.
+  //   2. |child| doesn't belong to |expected_child_process_id|.
+  //
+  // Can be called from any thread, as long GetInstance() has already been
+  // called on the UI thread at least once.
+  void RegisterChild(HWND parent, HWND child, DWORD expected_child_process_id);
+  void UnregisterParent(HWND parent);
+  bool HasValidChildWindow(HWND parent);
+
+ private:
+  friend class base::NoDestructor<RenderingWindowManager>;
+
+  RenderingWindowManager();
+  ~RenderingWindowManager();
+
+  // UI thread task runner.
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  // Map from registered parent HWND to child HWND.
+  base::flat_map<HWND, HWND> registered_hwnds_;
+};
+
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_RENDERING_WINDOW_MANAGER_H_
diff --git a/ui/gfx/win/scoped_set_map_mode.h b/ui/gfx/win/scoped_set_map_mode.h
new file mode 100644
index 0000000..f5669fe
--- /dev/null
+++ b/ui/gfx/win/scoped_set_map_mode.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 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.
+
+#ifndef UI_GFX_WIN_SCOPED_SET_MAP_MODE_H_
+#define UI_GFX_WIN_SCOPED_SET_MAP_MODE_H_
+
+#include <windows.h>
+
+#include "base/check_op.h"
+#include "base/macros.h"
+
+namespace gfx {
+
+// Helper class for setting and restore the map mode on a DC.
+class ScopedSetMapMode {
+ public:
+  ScopedSetMapMode(HDC hdc, int map_mode)
+      : hdc_(hdc),
+        old_map_mode_(SetMapMode(hdc, map_mode)) {
+    DCHECK(hdc_);
+    DCHECK_NE(map_mode, 0);
+    DCHECK_NE(old_map_mode_, 0);
+  }
+
+  ScopedSetMapMode(const ScopedSetMapMode&) = delete;
+  ScopedSetMapMode& operator=(const ScopedSetMapMode&) = delete;
+
+  ~ScopedSetMapMode() {
+    const int mode = SetMapMode(hdc_, old_map_mode_);
+    DCHECK_NE(mode, 0);
+  }
+
+ private:
+  HDC hdc_;
+  int old_map_mode_;
+};
+
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_SCOPED_SET_MAP_MODE_H_
diff --git a/ui/gfx/win/singleton_hwnd.cc b/ui/gfx/win/singleton_hwnd.cc
new file mode 100644
index 0000000..1476b11
--- /dev/null
+++ b/ui/gfx/win/singleton_hwnd.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 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 "ui/gfx/win/singleton_hwnd.h"
+
+#include "base/memory/singleton.h"
+#include "base/task/current_thread.h"
+#include "ui/gfx/win/singleton_hwnd_observer.h"
+
+namespace gfx {
+
+// static
+SingletonHwnd* SingletonHwnd::GetInstance() {
+  return base::Singleton<SingletonHwnd>::get();
+}
+
+BOOL SingletonHwnd::ProcessWindowMessage(HWND window,
+                                         UINT message,
+                                         WPARAM wparam,
+                                         LPARAM lparam,
+                                         LRESULT& result,
+                                         DWORD msg_map_id) {
+  if (!base::CurrentUIThread::IsSet()) {
+    // If there is no MessageLoop and SingletonHwnd is receiving messages, this
+    // means it is receiving messages via an external message pump such as COM
+    // uninitialization.
+    //
+    // It is unsafe to forward these messages as observers may depend on the
+    // existence of a MessageLoop to proceed.
+    return false;
+  }
+
+  for (SingletonHwndObserver& observer : observer_list_)
+    observer.OnWndProc(window, message, wparam, lparam);
+  return false;
+}
+
+SingletonHwnd::SingletonHwnd() {
+  if (!base::CurrentUIThread::IsSet()) {
+    // Creating this window in (e.g.) a renderer inhibits shutdown on
+    // Windows. See http://crbug.com/230122 and http://crbug.com/236039.
+    return;
+  }
+  WindowImpl::Init(NULL, Rect());
+}
+
+SingletonHwnd::~SingletonHwnd() {
+  // WindowImpl will clean up the hwnd value on WM_NCDESTROY.
+  if (hwnd())
+    DestroyWindow(hwnd());
+
+  // Tell all of our current observers to clean themselves up.
+  for (SingletonHwndObserver& observer : observer_list_)
+    observer.ClearWndProc();
+}
+
+void SingletonHwnd::AddObserver(SingletonHwndObserver* observer) {
+  observer_list_.AddObserver(observer);
+}
+
+void SingletonHwnd::RemoveObserver(SingletonHwndObserver* observer) {
+  observer_list_.RemoveObserver(observer);
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/win/singleton_hwnd.h b/ui/gfx/win/singleton_hwnd.h
new file mode 100644
index 0000000..36daf55
--- /dev/null
+++ b/ui/gfx/win/singleton_hwnd.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 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.
+
+#ifndef UI_GFX_WIN_SINGLETON_HWND_H_
+#define UI_GFX_WIN_SINGLETON_HWND_H_
+
+#include <windows.h>
+
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/win/window_impl.h"
+
+namespace base {
+template<typename T> struct DefaultSingletonTraits;
+}
+
+namespace gfx {
+
+class SingletonHwndObserver;
+
+// Singleton message-only HWND that allows interested clients to receive WM_*
+// notifications.
+class GFX_EXPORT SingletonHwnd : public WindowImpl {
+ public:
+  static SingletonHwnd* GetInstance();
+
+  SingletonHwnd(const SingletonHwnd&) = delete;
+  SingletonHwnd& operator=(const SingletonHwnd&) = delete;
+
+  // Windows callback for WM_* notifications.
+  BOOL ProcessWindowMessage(HWND window,
+                            UINT message,
+                            WPARAM wparam,
+                            LPARAM lparam,
+                            LRESULT& result,
+                            DWORD msg_map_id) override;
+
+ private:
+  friend class SingletonHwndObserver;
+  friend struct base::DefaultSingletonTraits<SingletonHwnd>;
+
+  SingletonHwnd();
+  ~SingletonHwnd() override;
+
+  // Add/remove SingletonHwndObserver to forward WM_* notifications.
+  void AddObserver(SingletonHwndObserver* observer);
+  void RemoveObserver(SingletonHwndObserver* observer);
+
+  // List of registered observers.
+  base::ObserverList<SingletonHwndObserver, true>::Unchecked observer_list_;
+};
+
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_SINGLETON_HWND_H_
diff --git a/ui/gfx/win/singleton_hwnd_hot_key_observer.cc b/ui/gfx/win/singleton_hwnd_hot_key_observer.cc
new file mode 100644
index 0000000..be3d7c2
--- /dev/null
+++ b/ui/gfx/win/singleton_hwnd_hot_key_observer.cc
@@ -0,0 +1,96 @@
+// Copyright 2019 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 "ui/gfx/win/singleton_hwnd_hot_key_observer.h"
+
+#include "base/bind.h"
+#include "base/containers/flat_set.h"
+#include "base/memory/ptr_util.h"
+#include "base/no_destructor.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/win/singleton_hwnd.h"
+
+namespace gfx {
+
+namespace {
+
+base::flat_set<int>& GetUsedHotKeyIDs() {
+  static base::NoDestructor<base::flat_set<int>> used_hot_key_ids;
+  return *used_hot_key_ids;
+}
+
+absl::optional<int> GetAvailableHotKeyID() {
+  // Valid hot key IDs are in the range 0x0000 to 0xBFFF. See
+  // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registerhotkey
+  for (int i = 0x0000; i < 0xBFFF; i++) {
+    if (!GetUsedHotKeyIDs().contains(i))
+      return i;
+  }
+  return absl::nullopt;
+}
+
+void SetHotKeyIDUsed(int id) {
+  DCHECK(!GetUsedHotKeyIDs().contains(id));
+  GetUsedHotKeyIDs().insert(id);
+}
+
+void SetHotKeyIDAvailable(int id) {
+  DCHECK(GetUsedHotKeyIDs().contains(id));
+  GetUsedHotKeyIDs().erase(id);
+}
+
+}  // anonymous namespace
+
+std::unique_ptr<SingletonHwndHotKeyObserver>
+SingletonHwndHotKeyObserver::Create(
+    const SingletonHwndObserver::WndProc& wnd_proc,
+    UINT key_code,
+    int modifiers) {
+  absl::optional<int> hot_key_id = GetAvailableHotKeyID();
+
+  // If there are no available hot key IDs, return null.
+  if (!hot_key_id.has_value())
+    return nullptr;
+
+  // If we fail to register the hot key, return null. Most likely reason for
+  // failure is that another application has already registered the hot key.
+  if (!RegisterHotKey(gfx::SingletonHwnd::GetInstance()->hwnd(), *hot_key_id,
+                      modifiers, key_code)) {
+    return nullptr;
+  }
+
+  return base::WrapUnique(
+      new SingletonHwndHotKeyObserver(wnd_proc, *hot_key_id));
+}
+
+SingletonHwndHotKeyObserver::SingletonHwndHotKeyObserver(
+    const SingletonHwndObserver::WndProc& wnd_proc,
+    int hot_key_id)
+    : observer_(base::BindRepeating(&SingletonHwndHotKeyObserver::OnWndProc,
+                                    base::Unretained(this))),
+      wnd_proc_(wnd_proc),
+      hot_key_id_(hot_key_id) {
+  SetHotKeyIDUsed(hot_key_id);
+}
+
+SingletonHwndHotKeyObserver::~SingletonHwndHotKeyObserver() {
+  bool success = !!UnregisterHotKey(gfx::SingletonHwnd::GetInstance()->hwnd(),
+                                    hot_key_id_);
+  // This call should always succeed, as long as we pass in the right HWND and
+  // an id we've used to register before.
+  DCHECK(success);
+  SetHotKeyIDAvailable(hot_key_id_);
+}
+
+void SingletonHwndHotKeyObserver::OnWndProc(HWND hwnd,
+                                            UINT message,
+                                            WPARAM wparam,
+                                            LPARAM lparam) {
+  // Only propagate WM_HOTKEY messages for this particular hot key to the owner
+  // of this observer.
+  if (message == WM_HOTKEY && static_cast<int>(wparam) == hot_key_id_)
+    wnd_proc_.Run(hwnd, message, wparam, lparam);
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/win/singleton_hwnd_hot_key_observer.h b/ui/gfx/win/singleton_hwnd_hot_key_observer.h
new file mode 100644
index 0000000..5b003ce
--- /dev/null
+++ b/ui/gfx/win/singleton_hwnd_hot_key_observer.h
@@ -0,0 +1,53 @@
+// Copyright 2019 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.
+
+#ifndef UI_GFX_WIN_SINGLETON_HWND_HOT_KEY_OBSERVER_H_
+#define UI_GFX_WIN_SINGLETON_HWND_HOT_KEY_OBSERVER_H_
+
+#include "base/win/windows_types.h"
+#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/win/singleton_hwnd_observer.h"
+
+namespace gfx {
+
+// We need to avoid duplicate hot key IDs for SingletonHwndObservers that call
+// RegisterHotKey for SingletonHwnd. This class properly handles getting a
+// unique hot key ID, registers the hotkey on construction, and unregisters the
+// hot key on destruction.
+//
+// This class should always be used instead of directly registering hot keys on
+// the SingletonHwnd with a SingletonHwndObserver in order to prevent duplicate
+// hot key IDs.
+class GFX_EXPORT SingletonHwndHotKeyObserver {
+ public:
+  // Registers a hot key with the given |key_code| and |modifiers| and returns
+  // a SingletonHwndHotKeyObserver if successful. Returns null if the hot key
+  // fails to register, which can happen if another application has already
+  // registered the hot key.
+  static std::unique_ptr<SingletonHwndHotKeyObserver> Create(
+      const SingletonHwndObserver::WndProc& wnd_proc,
+      UINT key_code,
+      int modifiers);
+
+  SingletonHwndHotKeyObserver(const SingletonHwndHotKeyObserver&) = delete;
+  SingletonHwndHotKeyObserver& operator=(const SingletonHwndHotKeyObserver&) =
+      delete;
+
+  ~SingletonHwndHotKeyObserver();
+
+ private:
+  SingletonHwndHotKeyObserver(const SingletonHwndObserver::WndProc& wnd_proc,
+                              int hot_key_id);
+
+  // Called by SingletonHwndObserver.
+  void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
+
+  SingletonHwndObserver observer_;
+  SingletonHwndObserver::WndProc wnd_proc_;
+  const int hot_key_id_;
+};
+
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_SINGLETON_HWND_HOT_KEY_OBSERVER_H_
diff --git a/ui/gfx/win/singleton_hwnd_observer.cc b/ui/gfx/win/singleton_hwnd_observer.cc
new file mode 100644
index 0000000..f439105
--- /dev/null
+++ b/ui/gfx/win/singleton_hwnd_observer.cc
@@ -0,0 +1,35 @@
+// Copyright 2015 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 "ui/gfx/win/singleton_hwnd_observer.h"
+
+#include "ui/gfx/win/singleton_hwnd.h"
+
+namespace gfx {
+
+SingletonHwndObserver::SingletonHwndObserver(const WndProc& wnd_proc)
+    : wnd_proc_(wnd_proc) {
+  DCHECK(!wnd_proc.is_null());
+  SingletonHwnd::GetInstance()->AddObserver(this);
+}
+
+SingletonHwndObserver::~SingletonHwndObserver() {
+  ClearWndProc();
+}
+
+void SingletonHwndObserver::ClearWndProc() {
+  if (!wnd_proc_.is_null()) {
+    SingletonHwnd::GetInstance()->RemoveObserver(this);
+    wnd_proc_.Reset();
+  }
+}
+
+void SingletonHwndObserver::OnWndProc(HWND hwnd,
+                                      UINT message,
+                                      WPARAM wparam,
+                                      LPARAM lparam) {
+  wnd_proc_.Run(hwnd, message, wparam, lparam);
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/win/singleton_hwnd_observer.h b/ui/gfx/win/singleton_hwnd_observer.h
new file mode 100644
index 0000000..cc2ef8a
--- /dev/null
+++ b/ui/gfx/win/singleton_hwnd_observer.h
@@ -0,0 +1,44 @@
+// Copyright 2015 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.
+
+#ifndef UI_GFX_WIN_SINGLETON_HWND_OBSERVER_H_
+#define UI_GFX_WIN_SINGLETON_HWND_OBSERVER_H_
+
+#include <windows.h>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+class SingletonHwnd;
+
+// Singleton lifetime management is tricky. This observer handles the correct
+// cleanup if either the SingletonHwnd or forwarded object is destroyed first.
+// Note that if you want to register a hot key on the SingletonHwnd, you need to
+// use a SingletonHwndHotKeyObserver instead for each hot key.
+class GFX_EXPORT SingletonHwndObserver {
+ public:
+  using WndProc = base::RepeatingCallback<void(HWND, UINT, WPARAM, LPARAM)>;
+
+  explicit SingletonHwndObserver(const WndProc& wnd_proc);
+
+  SingletonHwndObserver(const SingletonHwndObserver&) = delete;
+  SingletonHwndObserver& operator=(const SingletonHwndObserver&) = delete;
+
+  ~SingletonHwndObserver();
+
+ private:
+  friend class SingletonHwnd;
+
+  void ClearWndProc();
+  void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
+
+  WndProc wnd_proc_;
+};
+
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_SINGLETON_HWND_OBSERVER_H_
diff --git a/ui/gfx/win/text_analysis_source.cc b/ui/gfx/win/text_analysis_source.cc
new file mode 100644
index 0000000..13fef96
--- /dev/null
+++ b/ui/gfx/win/text_analysis_source.cc
@@ -0,0 +1,95 @@
+// Copyright 2016 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 "ui/gfx/win/text_analysis_source.h"
+
+#include "base/check.h"
+
+namespace gfx {
+namespace win {
+
+HRESULT TextAnalysisSource::Create(
+    IDWriteTextAnalysisSource** text_analysis_out,
+    const std::wstring& text,
+    const std::wstring& locale_name,
+    IDWriteNumberSubstitution* number_substitution,
+    DWRITE_READING_DIRECTION reading_direction) {
+  return Microsoft::WRL::MakeAndInitialize<gfx::win::TextAnalysisSource>(
+      text_analysis_out, text, locale_name, number_substitution,
+      reading_direction);
+}
+
+TextAnalysisSource::TextAnalysisSource() = default;
+TextAnalysisSource::~TextAnalysisSource() = default;
+
+HRESULT TextAnalysisSource::GetLocaleName(UINT32 text_position,
+                                          UINT32* text_length,
+                                          const WCHAR** locale_name) {
+  if (text_position >= text_.length() || !text_length || !locale_name)
+    return E_INVALIDARG;
+  *text_length = text_.length() - text_position;
+  *locale_name = locale_name_.c_str();
+  return S_OK;
+}
+
+HRESULT TextAnalysisSource::GetNumberSubstitution(
+    UINT32 text_position,
+    UINT32* text_length,
+    IDWriteNumberSubstitution** number_substitution) {
+  if (text_position >= text_.length() || !text_length || !number_substitution)
+    return E_INVALIDARG;
+  *text_length = text_.length() - text_position;
+  number_substitution_.CopyTo(number_substitution);
+  return S_OK;
+}
+
+DWRITE_READING_DIRECTION TextAnalysisSource::GetParagraphReadingDirection() {
+  return reading_direction_;
+}
+
+HRESULT TextAnalysisSource::GetTextAtPosition(UINT32 text_position,
+                                              const WCHAR** text_string,
+                                              UINT32* text_length) {
+  if (!text_length || !text_string)
+    return E_INVALIDARG;
+  if (text_position >= text_.length()) {
+    *text_string = nullptr;
+    *text_length = 0;
+    return S_OK;
+  }
+  *text_string = text_.c_str() + text_position;
+  *text_length = text_.length() - text_position;
+  return S_OK;
+}
+
+HRESULT TextAnalysisSource::GetTextBeforePosition(UINT32 text_position,
+                                                  const WCHAR** text_string,
+                                                  UINT32* text_length) {
+  if (!text_length || !text_string)
+    return E_INVALIDARG;
+  if (text_position < 1 || text_position > text_.length()) {
+    *text_string = nullptr;
+    *text_length = 0;
+    return S_OK;
+  }
+  *text_string = text_.c_str();
+  *text_length = text_position;
+  return S_OK;
+}
+
+HRESULT TextAnalysisSource::RuntimeClassInitialize(
+    const std::wstring& text,
+    const std::wstring& locale_name,
+    IDWriteNumberSubstitution* number_substitution,
+    DWRITE_READING_DIRECTION reading_direction) {
+  DCHECK(number_substitution);
+  text_ = text;
+  locale_name_ = locale_name;
+  number_substitution_ = number_substitution;
+  reading_direction_ = reading_direction;
+  return S_OK;
+}
+
+}  // namespace win
+}  // namespace gfx
diff --git a/ui/gfx/win/text_analysis_source.h b/ui/gfx/win/text_analysis_source.h
new file mode 100644
index 0000000..93ce417
--- /dev/null
+++ b/ui/gfx/win/text_analysis_source.h
@@ -0,0 +1,78 @@
+// Copyright 2016 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.
+
+#ifndef UI_GFX_WIN_TEXT_ANALYSIS_SOURCE_H_
+#define UI_GFX_WIN_TEXT_ANALYSIS_SOURCE_H_
+
+#include <dwrite.h>
+#include <wrl.h>
+
+#include <string>
+
+#include "base/macros.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+namespace win {
+
+// Implements an IDWriteTextAnalysisSource, describing a single pre-defined
+// chunk of text with a uniform locale, reading direction, and number
+// substitution.
+class TextAnalysisSource
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
+          IDWriteTextAnalysisSource> {
+ public:
+  // Factory method to avoid exporting the class and all it derives from.
+  static GFX_EXPORT HRESULT
+  Create(IDWriteTextAnalysisSource** text_analysis_out,
+         const std::wstring& text,
+         const std::wstring& locale_name,
+         IDWriteNumberSubstitution* number_substitution,
+         DWRITE_READING_DIRECTION reading_direction);
+
+  // Use Create() to construct these objects. Direct calls to the constructor
+  // are an error - it is only public because a WRL helper function creates the
+  // objects.
+  TextAnalysisSource();
+
+  TextAnalysisSource& operator=(const TextAnalysisSource&) = delete;
+
+  // IDWriteTextAnalysisSource:
+  HRESULT STDMETHODCALLTYPE GetLocaleName(UINT32 text_position,
+                                          UINT32* text_length,
+                                          const WCHAR** locale_name) override;
+  HRESULT STDMETHODCALLTYPE GetNumberSubstitution(
+      UINT32 text_position,
+      UINT32* text_length,
+      IDWriteNumberSubstitution** number_substitution) override;
+  DWRITE_READING_DIRECTION STDMETHODCALLTYPE
+  GetParagraphReadingDirection() override;
+  HRESULT STDMETHODCALLTYPE GetTextAtPosition(UINT32 text_position,
+                                              const WCHAR** text_string,
+                                              UINT32* text_length) override;
+  HRESULT STDMETHODCALLTYPE GetTextBeforePosition(UINT32 text_position,
+                                                  const WCHAR** text_string,
+                                                  UINT32* text_length) override;
+
+  HRESULT STDMETHODCALLTYPE
+  RuntimeClassInitialize(const std::wstring& text,
+                         const std::wstring& locale_name,
+                         IDWriteNumberSubstitution* number_substitution,
+                         DWRITE_READING_DIRECTION reading_direction);
+
+ protected:
+  ~TextAnalysisSource() override;
+
+ private:
+  std::wstring text_;
+  std::wstring locale_name_;
+  Microsoft::WRL::ComPtr<IDWriteNumberSubstitution> number_substitution_;
+  DWRITE_READING_DIRECTION reading_direction_;
+};
+
+}  // namespace win
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_TEXT_ANALYSIS_SOURCE_H_
diff --git a/ui/gfx/win/text_analysis_source_unittest.cc b/ui/gfx/win/text_analysis_source_unittest.cc
new file mode 100644
index 0000000..7886218
--- /dev/null
+++ b/ui/gfx/win/text_analysis_source_unittest.cc
@@ -0,0 +1,133 @@
+// Copyright 2016 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 "ui/gfx/win/text_analysis_source.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/win/direct_write.h"
+
+namespace mswr = Microsoft::WRL;
+
+namespace gfx {
+namespace win {
+
+namespace {
+
+DWRITE_READING_DIRECTION kReadingDirection =
+    DWRITE_READING_DIRECTION_TOP_TO_BOTTOM;
+const wchar_t* kLocale = L"hi-in";
+const wchar_t kText[] = L"sample text";
+const size_t kTextLength = _countof(kText) - 1;
+
+}  // namespace
+
+class TextAnalysisSourceTest : public testing::Test {
+ public:
+  TextAnalysisSourceTest() {
+    mswr::ComPtr<IDWriteFactory> factory;
+    CreateDWriteFactory(&factory);
+
+    mswr::ComPtr<IDWriteNumberSubstitution> number_substitution;
+    factory->CreateNumberSubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE,
+                                      kLocale, true /* ignoreUserOverride */,
+                                      &number_substitution);
+
+    TextAnalysisSource::Create(&source_, kText, kLocale,
+                               number_substitution.Get(), kReadingDirection);
+  }
+
+  TextAnalysisSourceTest(const TextAnalysisSourceTest&) = delete;
+  TextAnalysisSourceTest& operator=(const TextAnalysisSourceTest&) = delete;
+
+ protected:
+  mswr::ComPtr<IDWriteTextAnalysisSource> source_;
+};
+
+TEST_F(TextAnalysisSourceTest, TestGetLocaleName) {
+  UINT32 length = 0;
+  const wchar_t* locale_name = nullptr;
+  HRESULT hr = E_FAIL;
+  hr = source_->GetLocaleName(0, &length, &locale_name);
+
+  EXPECT_TRUE(SUCCEEDED(hr));
+  EXPECT_EQ(kTextLength, length);
+  EXPECT_STREQ(kLocale, locale_name);
+
+  // Attempting to get a locale for a location that does not have a text chunk
+  // should fail.
+  hr = source_->GetLocaleName(kTextLength, &length, &locale_name);
+
+  EXPECT_TRUE(FAILED(hr));
+}
+
+TEST_F(TextAnalysisSourceTest, TestGetNumberSubstitution) {
+  UINT32 length = 0;
+  mswr::ComPtr<IDWriteNumberSubstitution> number_substitution;
+  HRESULT hr = E_FAIL;
+  hr = source_->GetNumberSubstitution(0, &length, &number_substitution);
+
+  EXPECT_TRUE(SUCCEEDED(hr));
+  EXPECT_EQ(kTextLength, length);
+  EXPECT_NE(nullptr, number_substitution.Get());
+
+  // Attempting to get a number substitution for a location that does not have
+  // a text chunk should fail.
+  hr = source_->GetNumberSubstitution(kTextLength, &length,
+                                      &number_substitution);
+
+  EXPECT_TRUE(FAILED(hr));
+}
+
+TEST_F(TextAnalysisSourceTest, TestGetParagraphReadingDirection) {
+  EXPECT_EQ(kReadingDirection, source_->GetParagraphReadingDirection());
+}
+
+TEST_F(TextAnalysisSourceTest, TestGetTextAtPosition) {
+  UINT32 length = 0;
+  const wchar_t* text = nullptr;
+  HRESULT hr = E_FAIL;
+  hr = source_->GetTextAtPosition(0, &text, &length);
+
+  EXPECT_TRUE(SUCCEEDED(hr));
+  EXPECT_EQ(kTextLength, length);
+  EXPECT_STREQ(kText, text);
+
+  hr = source_->GetTextAtPosition(5, &text, &length);
+
+  EXPECT_TRUE(SUCCEEDED(hr));
+  EXPECT_EQ(kTextLength - 5, length);
+  EXPECT_STREQ(kText + 5, text);
+
+  // Trying to get a text chunk past the end should return null.
+  hr = source_->GetTextAtPosition(kTextLength, &text, &length);
+
+  EXPECT_TRUE(SUCCEEDED(hr));
+  EXPECT_EQ(nullptr, text);
+}
+
+TEST_F(TextAnalysisSourceTest, TestGetTextBeforePosition) {
+  UINT32 length = 0;
+  const wchar_t* text = nullptr;
+  HRESULT hr = E_FAIL;
+  // Trying to get a text chunk before the beginning should return null.
+  hr = source_->GetTextBeforePosition(0, &text, &length);
+
+  EXPECT_TRUE(SUCCEEDED(hr));
+  EXPECT_EQ(nullptr, text);
+
+  hr = source_->GetTextBeforePosition(5, &text, &length);
+
+  EXPECT_TRUE(SUCCEEDED(hr));
+  EXPECT_EQ(5u, length);
+  EXPECT_STREQ(kText, text);
+
+  hr = source_->GetTextBeforePosition(kTextLength, &text, &length);
+
+  EXPECT_TRUE(SUCCEEDED(hr));
+  EXPECT_EQ(kTextLength, length);
+  EXPECT_STREQ(kText, text);
+}
+
+}  // namespace win
+}  // namespace gfx
diff --git a/ui/gfx/win/window_impl.cc b/ui/gfx/win/window_impl.cc
new file mode 100644
index 0000000..0fdf80b
--- /dev/null
+++ b/ui/gfx/win/window_impl.cc
@@ -0,0 +1,317 @@
+// Copyright (c) 2012 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 "ui/gfx/win/window_impl.h"
+
+#include <list>
+
+#include "base/bind.h"
+#include "base/cxx17_backports.h"
+#include "base/debug/alias.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/synchronization/lock.h"
+#include "base/win/win_util.h"
+#include "base/win/wrapped_window_proc.h"
+#include "ui/gfx/win/crash_id_helper.h"
+#include "ui/gfx/win/hwnd_util.h"
+
+namespace gfx {
+
+static const DWORD kWindowDefaultChildStyle =
+    WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+static const DWORD kWindowDefaultStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowImpl class tracking.
+
+// Several external scripts rely explicitly on this base class name for
+// acquiring the window handle and will break if this is modified!
+// static
+const wchar_t* const WindowImpl::kBaseClassName = L"Chrome_WidgetWin_";
+
+// WindowImpl class information used for registering unique windows.
+struct ClassInfo {
+  ClassInfo(int style, HICON icon, HICON small_icon)
+      : style(style), icon(icon), small_icon(small_icon) {}
+
+  // Compares two ClassInfos. Returns true if all members match.
+  bool Equals(const ClassInfo& other) const {
+    return (other.style == style && other.icon == icon &&
+            other.small_icon == small_icon);
+  }
+
+  UINT style;
+  HICON icon;
+  HICON small_icon;
+};
+
+// WARNING: this class may be used on multiple threads.
+class ClassRegistrar {
+ public:
+  ClassRegistrar(const ClassRegistrar&) = delete;
+  ClassRegistrar& operator=(const ClassRegistrar&) = delete;
+
+  ~ClassRegistrar();
+
+  static ClassRegistrar* GetInstance();
+
+  void UnregisterClasses();
+
+  // Returns the atom identifying the class matching |class_info|,
+  // creating and registering a new class if the class is not yet known.
+  ATOM RetrieveClassAtom(const ClassInfo& class_info);
+
+ private:
+  // Represents a registered window class.
+  struct RegisteredClass {
+    RegisteredClass(const ClassInfo& info,
+                    const std::wstring& name,
+                    ATOM atom,
+                    HINSTANCE instance);
+
+    // Info used to create the class.
+    ClassInfo info;
+
+    // The name given to the window class
+    std::wstring name;
+
+    // The atom identifying the window class.
+    ATOM atom;
+
+    // The handle of the module containing the window proceedure.
+    HMODULE instance;
+  };
+
+  ClassRegistrar();
+  friend struct base::DefaultSingletonTraits<ClassRegistrar>;
+
+  typedef std::list<RegisteredClass> RegisteredClasses;
+  RegisteredClasses registered_classes_;
+
+  // Counter of how many classes have been registered so far.
+  int registered_count_;
+
+  base::Lock lock_;
+};
+
+ClassRegistrar::~ClassRegistrar() {}
+
+// static
+ClassRegistrar* ClassRegistrar::GetInstance() {
+  return base::Singleton<ClassRegistrar,
+                         base::LeakySingletonTraits<ClassRegistrar>>::get();
+}
+
+void ClassRegistrar::UnregisterClasses() {
+  for (RegisteredClasses::iterator i = registered_classes_.begin();
+        i != registered_classes_.end(); ++i) {
+     if (UnregisterClass(MAKEINTATOM(i->atom), i->instance)) {
+       registered_classes_.erase(i);
+     } else {
+       LOG(ERROR) << "Failed to unregister class " << i->name
+                  << ". Error = " << GetLastError();
+     }
+   }
+}
+
+ATOM ClassRegistrar::RetrieveClassAtom(const ClassInfo& class_info) {
+  base::AutoLock auto_lock(lock_);
+  for (RegisteredClasses::const_iterator i = registered_classes_.begin();
+       i != registered_classes_.end(); ++i) {
+    if (class_info.Equals(i->info))
+      return i->atom;
+  }
+
+  // No class found, need to register one.
+  std::wstring name = std::wstring(WindowImpl::kBaseClassName) +
+                      base::NumberToWString(registered_count_++);
+
+  WNDCLASSEX window_class;
+  base::win::InitializeWindowClass(
+      name.c_str(), &base::win::WrappedWindowProc<WindowImpl::WndProc>,
+      class_info.style, 0, 0, NULL,
+      reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)), NULL,
+      class_info.icon, class_info.small_icon, &window_class);
+  HMODULE instance = window_class.hInstance;
+  ATOM atom = RegisterClassEx(&window_class);
+  if (!atom) {
+    // Perhaps the Window session has run out of atoms; see
+    // https://crbug.com/653493.
+    auto last_error = ::GetLastError();
+    base::debug::Alias(&last_error);
+    wchar_t name_copy[64];
+    base::wcslcpy(name_copy, name.c_str(), base::size(name_copy));
+    base::debug::Alias(name_copy);
+    PCHECK(atom);
+  }
+
+  registered_classes_.push_back(RegisteredClass(
+      class_info, name, atom, instance));
+
+  return atom;
+}
+
+ClassRegistrar::RegisteredClass::RegisteredClass(const ClassInfo& info,
+                                                 const std::wstring& name,
+                                                 ATOM atom,
+                                                 HMODULE instance)
+    : info(info), name(name), atom(atom), instance(instance) {}
+
+ClassRegistrar::ClassRegistrar() : registered_count_(0) {}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowImpl, public
+
+WindowImpl::WindowImpl(const std::string& debugging_id)
+    : debugging_id_(debugging_id), class_style_(CS_DBLCLKS) {}
+
+WindowImpl::~WindowImpl() {
+  ClearUserData();
+}
+
+// static
+void WindowImpl::UnregisterClassesAtExit() {
+  base::AtExitManager::RegisterTask(
+      base::BindOnce(&ClassRegistrar::UnregisterClasses,
+                     base::Unretained(ClassRegistrar::GetInstance())));
+}
+
+void WindowImpl::Init(HWND parent, const Rect& bounds) {
+  if (window_style_ == 0)
+    window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle;
+
+  if (parent == HWND_DESKTOP) {
+    // Only non-child windows can have HWND_DESKTOP (0) as their parent.
+    CHECK((window_style_ & WS_CHILD) == 0);
+    parent = GetWindowToParentTo(false);
+  } else if (parent == ::GetDesktopWindow()) {
+    // Any type of window can have the "Desktop Window" as their parent.
+    parent = GetWindowToParentTo(true);
+  } else if (parent != HWND_MESSAGE) {
+    CHECK(::IsWindow(parent));
+  }
+
+  int x, y, width, height;
+  if (bounds.IsEmpty()) {
+    x = y = width = height = CW_USEDEFAULT;
+  } else {
+    x = bounds.x();
+    y = bounds.y();
+    width = bounds.width();
+    height = bounds.height();
+  }
+
+  ATOM atom = GetWindowClassAtom();
+  auto weak_this = weak_factory_.GetWeakPtr();
+  HWND hwnd = CreateWindowEx(window_ex_style_,
+                             reinterpret_cast<wchar_t*>(atom), NULL,
+                             window_style_, x, y, width, height,
+                             parent, NULL, NULL, this);
+  const DWORD create_window_error = ::GetLastError();
+
+  // First nccalcszie (during CreateWindow) for captioned windows is
+  // deliberately ignored so force a second one here to get the right
+  // non-client set up.
+  if (hwnd && (window_style_ & WS_CAPTION)) {
+    SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
+                 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
+                 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
+  }
+
+  if (!hwnd_ && create_window_error == 0) {
+    bool still_alive = !!weak_this;
+    base::debug::Alias(&still_alive);
+    base::debug::Alias(&hwnd);
+    base::debug::Alias(&atom);
+    bool got_create = got_create_;
+    base::debug::Alias(&got_create);
+    bool got_valid_hwnd = got_valid_hwnd_;
+    base::debug::Alias(&got_valid_hwnd);
+    WNDCLASSEX class_info;
+    memset(&class_info, 0, sizeof(WNDCLASSEX));
+    class_info.cbSize = sizeof(WNDCLASSEX);
+    BOOL got_class = GetClassInfoEx(GetModuleHandle(NULL),
+                                    reinterpret_cast<wchar_t*>(atom),
+                                    &class_info);
+    base::debug::Alias(&got_class);
+    bool procs_match = got_class && class_info.lpfnWndProc ==
+        base::win::WrappedWindowProc<&WindowImpl::WndProc>;
+    base::debug::Alias(&procs_match);
+    CHECK(false);
+  }
+
+  CheckWindowCreated(hwnd_, create_window_error);
+
+  // The window procedure should have set the data for us.
+  CHECK_EQ(this, GetWindowUserData(hwnd));
+}
+
+HICON WindowImpl::GetDefaultWindowIcon() const {
+  return nullptr;
+}
+
+HICON WindowImpl::GetSmallWindowIcon() const {
+  return nullptr;
+}
+
+LRESULT WindowImpl::OnWndProc(UINT message, WPARAM w_param, LPARAM l_param) {
+  LRESULT result = 0;
+
+  HWND hwnd = hwnd_;
+  if (message == WM_NCDESTROY)
+    hwnd_ = nullptr;
+
+  // Handle the message if it's in our message map; otherwise, let the system
+  // handle it.
+  if (!ProcessWindowMessage(hwnd, message, w_param, l_param, result))
+    result = DefWindowProc(hwnd, message, w_param, l_param);
+
+  return result;
+}
+
+void WindowImpl::ClearUserData() {
+  if (::IsWindow(hwnd_))
+    gfx::SetWindowUserData(hwnd_, nullptr);
+}
+
+// static
+LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd,
+                                     UINT message,
+                                     WPARAM w_param,
+                                     LPARAM l_param) {
+  WindowImpl* window = nullptr;
+  if (message == WM_NCCREATE) {
+    CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(l_param);
+    window = reinterpret_cast<WindowImpl*>(cs->lpCreateParams);
+    DCHECK(window);
+    gfx::SetWindowUserData(hwnd, window);
+    window->hwnd_ = hwnd;
+    window->got_create_ = true;
+    if (hwnd)
+      window->got_valid_hwnd_ = true;
+  } else {
+    window = reinterpret_cast<WindowImpl*>(GetWindowUserData(hwnd));
+  }
+
+  if (!window)
+    return 0;
+
+  auto logger =
+      CrashIdHelper::Get()->OnWillProcessMessages(window->debugging_id_);
+  return window->OnWndProc(message, w_param, l_param);
+}
+
+ATOM WindowImpl::GetWindowClassAtom() {
+  HICON icon = GetDefaultWindowIcon();
+  HICON small_icon = GetSmallWindowIcon();
+  ClassInfo class_info(initial_class_style(), icon, small_icon);
+  return ClassRegistrar::GetInstance()->RetrieveClassAtom(class_info);
+}
+
+}  // namespace gfx
diff --git a/ui/gfx/win/window_impl.h b/ui/gfx/win/window_impl.h
new file mode 100644
index 0000000..2a5683b
--- /dev/null
+++ b/ui/gfx/win/window_impl.h
@@ -0,0 +1,136 @@
+// Copyright (c) 2012 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.
+
+#ifndef UI_GFX_WIN_WINDOW_IMPL_H_
+#define UI_GFX_WIN_WINDOW_IMPL_H_
+
+#include <string>
+
+#include "base/check_op.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/win/msg_util.h"
+
+namespace gfx {
+
+// An interface implemented by classes that use message maps.
+// ProcessWindowMessage is implemented by the BEGIN_MESSAGE_MAP_EX macro.
+class MessageMapInterface {
+ public:
+  // Processes one message from the window's message queue.
+  virtual BOOL ProcessWindowMessage(HWND window,
+                                    UINT message,
+                                    WPARAM w_param,
+                                    LPARAM l_param,
+                                    LRESULT& result,
+                                    DWORD msg_map_id = 0) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// WindowImpl
+//  A convenience class that encapsulates the details of creating and
+//  destroying a HWND.  This class also hosts the windows procedure used by all
+//  Windows.
+//
+///////////////////////////////////////////////////////////////////////////////
+class GFX_EXPORT WindowImpl : public MessageMapInterface {
+ public:
+  // |debugging_id| is reported with crashes to help attribute the code that
+  // created the WindowImpl.
+  explicit WindowImpl(const std::string& debugging_id = std::string());
+
+  WindowImpl(const WindowImpl&) = delete;
+  WindowImpl& operator=(const WindowImpl&) = delete;
+
+  virtual ~WindowImpl();
+
+  // Causes all generated windows classes to be unregistered at exit.
+  // This can cause result in errors for tests that don't destroy all instances
+  // of windows, but is necessary if the tests unload the classes WndProc.
+  static void UnregisterClassesAtExit();
+
+  // Initializes the Window with a parent and an initial desired size.
+  void Init(HWND parent, const gfx::Rect& bounds);
+
+  // Returns the default window icon to use for windows of this type.
+  virtual HICON GetDefaultWindowIcon() const;
+  virtual HICON GetSmallWindowIcon() const;
+
+  // Returns the HWND associated with this Window.
+  HWND hwnd() const { return hwnd_; }
+
+  // Sets the window styles. This is ONLY used when the window is created.
+  // In other words, if you invoke this after invoking Init, nothing happens.
+  void set_window_style(DWORD style) { window_style_ = style; }
+  DWORD window_style() const { return window_style_; }
+
+  // Sets the extended window styles. See comment about |set_window_style|.
+  void set_window_ex_style(DWORD style) { window_ex_style_ = style; }
+  DWORD window_ex_style() const { return window_ex_style_; }
+
+  // Sets the class style to use. The default is CS_DBLCLKS.
+  void set_initial_class_style(UINT class_style) {
+    // We dynamically generate the class name, so don't register it globally!
+    DCHECK_EQ((class_style & CS_GLOBALCLASS), 0u);
+    class_style_ = class_style;
+  }
+  UINT initial_class_style() const { return class_style_; }
+
+  const std::string& debugging_id() const { return debugging_id_; }
+
+ protected:
+  // Handles the WndProc callback for this object.
+  virtual LRESULT OnWndProc(UINT message, WPARAM w_param, LPARAM l_param);
+
+  // Subclasses must call this method from their destructors to ensure that
+  // this object is properly disassociated from the HWND during destruction,
+  // otherwise it's possible this object may still exist while a subclass is
+  // destroyed.
+  void ClearUserData();
+
+ private:
+  friend class ClassRegistrar;
+
+  // The window procedure used by all Windows.
+  static LRESULT CALLBACK WndProc(HWND window,
+                                  UINT message,
+                                  WPARAM w_param,
+                                  LPARAM l_param);
+
+  // Gets the window class atom to use when creating the corresponding HWND.
+  // If necessary, this registers the window class.
+  ATOM GetWindowClassAtom();
+
+  // All classes registered by WindowImpl start with this name.
+  static const wchar_t* const kBaseClassName;
+
+  const std::string debugging_id_;
+
+  // Window Styles used when creating the window.
+  DWORD window_style_ = 0;
+
+  // Window Extended Styles used when creating the window.
+  DWORD window_ex_style_ = 0;
+
+  // Style of the class to use.
+  UINT class_style_;
+
+  // Our hwnd.
+  HWND hwnd_ = nullptr;
+
+  // For debugging.
+  // TODO(sky): nuke this when get crash data.
+  bool got_create_ = false;
+  bool got_valid_hwnd_ = false;
+  // For tracking whether this object has been destroyed. Must be last.
+  base::WeakPtrFactory<WindowImpl> weak_factory_{this};
+};
+
+}  // namespace gfx
+
+#endif  // UI_GFX_WIN_WINDOW_IMPL_H_