https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ef3e7a3717e13a97a652a961e5217a249778f4d4

commit ef3e7a3717e13a97a652a961e5217a249778f4d4
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sun Feb 28 12:45:16 2021 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sun Feb 28 12:45:16 2021 +0900

    [SDK][ATL] Implement UnsubclassWindow methods (#3492)
    
    I want UnsubclassWindow methods.
    - Implement CWindowImpl::UnsubclassWindow method.
    - Implement CContainedWindowT::UnsubclassWindow method.
    - Add SubclassWindow testcase to atl_apitest test program.
    - Fix generic text mapping of <atlwin.h>.
    CORE-9281
---
 modules/rostests/apitests/atl/CMakeLists.txt       |   3 +-
 modules/rostests/apitests/atl/SubclassWindow.cpp   | 428 +++++++++++++++++++++
 modules/rostests/apitests/atl/devenv/.gitignore    |  16 +
 modules/rostests/apitests/atl/devenv/ATLTest.sln   |  10 +
 .../apitests/atl/devenv/SubclassWindow.vcxproj     | 189 +++++++++
 modules/rostests/apitests/atl/testlist.c           |   2 +
 sdk/lib/atl/atlwin.h                               |  89 +++--
 7 files changed, 712 insertions(+), 25 deletions(-)

diff --git a/modules/rostests/apitests/atl/CMakeLists.txt 
b/modules/rostests/apitests/atl/CMakeLists.txt
index 555529b7e38..8f12a5071aa 100644
--- a/modules/rostests/apitests/atl/CMakeLists.txt
+++ b/modules/rostests/apitests/atl/CMakeLists.txt
@@ -16,7 +16,8 @@ list(APPEND SOURCE
     CRegKey.cpp
     CSimpleArray.cpp
     CSimpleMap.cpp
-    CString.cpp)
+    CString.cpp
+    SubclassWindow.cpp)
 
 list(APPEND PCH_SKIP_SOURCE
     testlist.c)
diff --git a/modules/rostests/apitests/atl/SubclassWindow.cpp 
b/modules/rostests/apitests/atl/SubclassWindow.cpp
new file mode 100644
index 00000000000..f372b1e7f9e
--- /dev/null
+++ b/modules/rostests/apitests/atl/SubclassWindow.cpp
@@ -0,0 +1,428 @@
+/*
+ * PROJECT:         ReactOS api tests
+ * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
+ * PURPOSE:         Test for SubclassWindow/UnsubclassWindow
+ * PROGRAMMER:      Katayama Hirofumi MZ ([email protected])
+ */
+
+#ifdef HAVE_APITEST
+    #include <apitest.h>
+    #define ATLASSUME(x) /*empty*/
+    #define ATLASSERT(x) /*empty*/
+#else
+    #include "atltest.h"
+    #define ATLASSUME(x) do { \
+        trace("ATLASSUME(%s) %s.\n", #x, ((x) ? "success" : "failure")); \
+    } while (0)
+    #define ATLASSERT(x) do { \
+        trace("ATLASSERT(%s) %s.\n", #x, ((x) ? "success" : "failure")); \
+    } while (0)
+#endif
+
+#include <atlbase.h>
+#include <atlwin.h>
+
+#ifdef _WIN64
+    #define INVALID_HWND ((HWND)(ULONG_PTR)0xDEADBEEFDEADBEEFULL)
+#else
+    #define INVALID_HWND ((HWND)(ULONG_PTR)0xDEADBEEF)
+#endif
+
+static BOOL s_flag = TRUE;
+
+class CMyCtrl1 : public CWindowImpl<CMyCtrl1, CWindow>
+{
+public:
+    static LPCWSTR GetWndClassName()
+    {
+        if (s_flag)
+            return L"EDIT";
+        else
+            return L"STATIC";
+    }
+
+    CMyCtrl1()
+    {
+    }
+    virtual ~CMyCtrl1()
+    {
+    }
+
+    BEGIN_MSG_MAP(CMyCtrl1)
+    END_MSG_MAP()
+};
+
+class CMyCtrl2
+    : public CContainedWindowT<CWindowImpl<CMyCtrl2, CWindow> >
+{
+public:
+    static LPCWSTR GetWndClassName()
+    {
+        if (s_flag)
+            return L"EDIT";
+        else
+            return L"STATIC";
+    }
+
+    CMyCtrl2() : CContainedWindowT<CWindowImpl<CMyCtrl2, CWindow> >(this)
+    {
+    }
+    virtual ~CMyCtrl2()
+    {
+    }
+
+    BEGIN_MSG_MAP(CMyCtrl2)
+    END_MSG_MAP()
+};
+
+static HWND MyCreateWindow(DWORD style)
+{
+    return CreateWindowW(L"EDIT", NULL, style,
+                         CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
+                         NULL, NULL, GetModuleHandleW(NULL), NULL);
+}
+
+static LRESULT CALLBACK
+MyWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    return 0;
+}
+
+START_TEST(SubclassWindow)
+{
+    const DWORD style = WS_POPUPWINDOW | ES_MULTILINE;
+    HWND hwnd1, hwnd2;
+    WNDPROC fn1, fn2;
+    BOOL b;
+    trace("DefWindowProcA == %p\n", DefWindowProcA);
+    trace("DefWindowProcW == %p\n", DefWindowProcW);
+    trace("MyWindowProc == %p\n", MyWindowProc);
+
+    //
+    // Ctrl1
+    //
+    {
+        CMyCtrl1 Ctrl1;
+        s_flag = TRUE; // "EDIT"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl1.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
+        fn1 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        hwnd2 = Ctrl1.UnsubclassWindow();
+        ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
+        fn2 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 != fn2, "fn1 == fn2\n");
+        ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
+        DestroyWindow(hwnd2);
+        ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
+    }
+
+    {
+        CMyCtrl1 Ctrl1;
+        s_flag = TRUE; // "EDIT"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl1.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
+        fn1 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        DestroyWindow(hwnd1); // destroy now
+        hwnd2 = Ctrl1.UnsubclassWindow();
+        ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
+        fn2 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn2 == fn1, "fn2 was %p\n", fn2);
+        DestroyWindow(hwnd2);
+        ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
+    }
+
+    {
+        CMyCtrl1 Ctrl1;
+        s_flag = FALSE; // "STATIC"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl1.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
+        fn1 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        hwnd2 = Ctrl1.UnsubclassWindow();
+        ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
+        fn2 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 != fn2, "fn1 == fn2\n");
+        ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
+        DestroyWindow(hwnd2);
+        ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
+    }
+
+    {
+        CMyCtrl1 Ctrl1;
+        s_flag = FALSE; // "STATIC"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl1.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
+        fn1 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        DestroyWindow(hwnd1); // destroy now
+        hwnd2 = Ctrl1.UnsubclassWindow();
+        ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
+        fn2 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 == fn2, "fn1 != fn2\n");
+        DestroyWindow(hwnd2);
+        ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
+    }
+
+    {
+        CMyCtrl1 Ctrl1;
+        s_flag = TRUE; // "EDIT"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl1.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
+        Ctrl1.m_pfnSuperWindowProc = MyWindowProc;
+        hwnd2 = Ctrl1.UnsubclassWindow();
+        ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
+        fn2 = Ctrl1.m_pfnSuperWindowProc;
+        ok(fn1 == fn2, "fn2 was %p\n", fn2);
+        ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
+        DestroyWindow(hwnd2);
+        ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
+    }
+
+    //
+    // Ctrl2 (Not Forced)
+    //
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = TRUE; // "EDIT"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
+        ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != fn2, "fn1 == fn2\n");
+        ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+    }
+
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = TRUE; // "EDIT"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        DestroyWindow(hwnd1); // destroy now
+        hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
+        ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == fn2, "fn1 == fn2\n");
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+    }
+
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = FALSE; // "STATIC"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
+        ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != fn2, "fn1 == fn2\n");
+        ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+    }
+
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = FALSE; // "STATIC"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        DestroyWindow(hwnd1); // destroy now
+        hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
+        ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn2 != DefWindowProc, "fn2 was %p\n", fn2); // 
ntdll.dll!NtdllEditWndProc_W
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+    }
+
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = TRUE; // "EDIT"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        Ctrl2.m_pfnSuperWindowProc = MyWindowProc;
+        hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
+        ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
+        ok(Ctrl2.m_hWnd == NULL, "hwnd != NULL\n");
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "hwnd != NULL\n");
+    }
+
+    //
+    // Ctrl2 (Forced)
+    //
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = TRUE; // "EDIT"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
+        ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != fn2, "fn1 == fn2\n");
+        ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+    }
+
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = TRUE; // "EDIT"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        DestroyWindow(hwnd1); // destroy now
+        hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
+        ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn2 == fn1, "fn2 was %p\n", fn2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+    }
+
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = FALSE; // "STATIC"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
+        ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != fn2, "fn1 == fn2\n");
+        ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+    }
+
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = FALSE; // "STATIC"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
+        DestroyWindow(hwnd1); // destroy now
+        hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
+        ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn2 != DefWindowProc, "fn2 was %p\n", fn2); // 
ntdll.dll!NtdllEditWndProc_W
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+    }
+
+    {
+        CMyCtrl2 Ctrl2;
+        s_flag = TRUE; // "EDIT"
+        hwnd1 = MyCreateWindow(style);
+        ok(hwnd1 != NULL, "hwnd1 was NULL\n");
+        fn1 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
+        b = Ctrl2.SubclassWindow(hwnd1);
+        ok_int(b, TRUE);
+        ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
+        Ctrl2.m_pfnSuperWindowProc = MyWindowProc;
+        hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
+        ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
+        fn2 = Ctrl2.m_pfnSuperWindowProc;
+        ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
+        ok(Ctrl2.m_hWnd == NULL, "hwnd != NULL\n");
+        DestroyWindow(hwnd2);
+        ok(Ctrl2.m_hWnd == NULL, "hwnd != NULL\n");
+    }
+}
diff --git a/modules/rostests/apitests/atl/devenv/.gitignore 
b/modules/rostests/apitests/atl/devenv/.gitignore
new file mode 100644
index 00000000000..15eeeeb1607
--- /dev/null
+++ b/modules/rostests/apitests/atl/devenv/.gitignore
@@ -0,0 +1,16 @@
+*.opendb
+*.db
+x64/
+.vs/
+CAtlArray/
+CAtlFileMapping/
+CAtlList/
+CComHeapPtr/
+CComObject/
+CComQIPtr/
+CHeapPtrList/
+CImage/
+CSimpleArray/
+CSimpleMap/
+CString/
+SubclassWindow/
diff --git a/modules/rostests/apitests/atl/devenv/ATLTest.sln 
b/modules/rostests/apitests/atl/devenv/ATLTest.sln
index 8fd0e07a092..9811121c7fd 100644
--- a/modules/rostests/apitests/atl/devenv/ATLTest.sln
+++ b/modules/rostests/apitests/atl/devenv/ATLTest.sln
@@ -25,6 +25,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = 
"CHeapPtrList", "CHeapPtrLis
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CComHeapPtr", 
"CComHeapPtr.vcxproj", "{F10E34E3-FB53-4650-985A-28BD1905D65C}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SubclassWindow", 
"SubclassWindow.vcxproj", "{ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|x64 = Debug|x64
@@ -121,6 +123,14 @@ Global
                {F10E34E3-FB53-4650-985A-28BD1905D65C}.Release|x64.Build.0 = 
Release|x64
                {F10E34E3-FB53-4650-985A-28BD1905D65C}.Release|x86.ActiveCfg = 
Release|Win32
                {F10E34E3-FB53-4650-985A-28BD1905D65C}.Release|x86.Build.0 = 
Release|Win32
+               {ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}.Debug|x64.ActiveCfg = 
Debug|x64
+               {ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}.Debug|x64.Build.0 = 
Debug|x64
+               {ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}.Debug|x86.ActiveCfg = 
Debug|Win32
+               {ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}.Debug|x86.Build.0 = 
Debug|Win32
+               {ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}.Release|x64.ActiveCfg = 
Release|x64
+               {ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}.Release|x64.Build.0 = 
Release|x64
+               {ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}.Release|x86.ActiveCfg = 
Release|Win32
+               {ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}.Release|x86.Build.0 = 
Release|Win32
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
diff --git a/modules/rostests/apitests/atl/devenv/SubclassWindow.vcxproj 
b/modules/rostests/apitests/atl/devenv/SubclassWindow.vcxproj
new file mode 100644
index 00000000000..5b1569b871c
--- /dev/null
+++ b/modules/rostests/apitests/atl/devenv/SubclassWindow.vcxproj
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" 
xmlns="http://schemas.microsoft.com/developer/msbuild/2003";>
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{ABACDAE7-3936-17E1-7525-96C4A7DA4CD2}</ProjectGuid>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+    <Keyword>AtlProj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" 
Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140_xp</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" 
Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140_xp</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" 
Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140_xp</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" 
Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140_xp</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" 
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" 
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" 
Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" 
Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" 
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" 
Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" 
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" 
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" 
Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" 
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" 
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" 
Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <IgnoreImportLibrary>true</IgnoreImportLibrary>
+    <LinkIncremental>true</LinkIncremental>
+    <IntDir>$(ProjectName)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <IgnoreImportLibrary>true</IgnoreImportLibrary>
+    <LinkIncremental>true</LinkIncremental>
+    <IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <IgnoreImportLibrary>true</IgnoreImportLibrary>
+    <LinkIncremental>false</LinkIncremental>
+    <IntDir>$(ProjectName)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <IgnoreImportLibrary>true</IgnoreImportLibrary>
+    <LinkIncremental>false</LinkIncremental>
+    <IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup 
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      
<PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup 
Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup 
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      
<PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <ResourceCompile>
+      <Culture>0x0409</Culture>
+      
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="../SubclassWindow.cpp">
+      <RuntimeLibrary 
Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MultiThreaded</RuntimeLibrary>
+      <RuntimeLibrary 
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MultiThreaded</RuntimeLibrary>
+      <RuntimeLibrary 
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MultiThreadedDebug</RuntimeLibrary>
+      <RuntimeLibrary 
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">MultiThreadedDebug</RuntimeLibrary>
+      <PrecompiledHeader 
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader 
Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader 
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader 
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\resource.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\atl_apitest.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\cstring.inl" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/modules/rostests/apitests/atl/testlist.c 
b/modules/rostests/apitests/atl/testlist.c
index 028063f826e..213ce2419c4 100644
--- a/modules/rostests/apitests/atl/testlist.c
+++ b/modules/rostests/apitests/atl/testlist.c
@@ -16,6 +16,7 @@ extern void func_CRegKey(void);
 extern void func_CSimpleArray(void);
 extern void func_CSimpleMap(void);
 extern void func_CString(void);
+extern void func_SubclassWindow(void);
 
 const struct test winetest_testlist[] =
 {
@@ -34,5 +35,6 @@ const struct test winetest_testlist[] =
     { "CSimpleArray", func_CSimpleArray },
     { "CSimpleMap", func_CSimpleMap },
     { "CString", func_CString },
+    { "SubclassWindow", func_SubclassWindow },
     { 0, 0 }
 };
diff --git a/sdk/lib/atl/atlwin.h b/sdk/lib/atl/atlwin.h
index 70f0413b41a..d8994988d40 100644
--- a/sdk/lib/atl/atlwin.h
+++ b/sdk/lib/atl/atlwin.h
@@ -1482,28 +1482,49 @@ public:
 
     BOOL SubclassWindow(HWND hWnd)
     {
-        CWindowImplBaseT<TBase, TWinTraits> *pThis;
-        WNDPROC newWindowProc;
-        WNDPROC oldWindowProc;
-        BOOL result;
-
         ATLASSERT(m_hWnd == NULL);
         ATLASSERT(::IsWindow(hWnd));
 
+        CWindowImplBaseT<TBase, TWinTraits> *pThis;
         pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
 
-        result = m_thunk.Init(GetWindowProc(), this);
+        BOOL result = m_thunk.Init(GetWindowProc(), this);
         if (result == FALSE)
             return FALSE;
-        newWindowProc = m_thunk.GetWNDPROC();
-        oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, 
GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
+
+        WNDPROC newWindowProc = m_thunk.GetWNDPROC();
+        WNDPROC oldWindowProc = reinterpret_cast<WNDPROC>(
+            ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, 
reinterpret_cast<LONG_PTR>(newWindowProc)));
         if (oldWindowProc == NULL)
             return FALSE;
-        m_pfnSuperWindowProc = oldWindowProc;
+
+        pThis->m_pfnSuperWindowProc = oldWindowProc;
         pThis->m_hWnd = hWnd;
         return TRUE;
     }
 
+    HWND UnsubclassWindow(BOOL bForce = FALSE)
+    {
+        ATLASSERT(m_hWnd != NULL);
+        ATLASSERT(::IsWindow(m_hWnd));
+
+        CWindowImplBaseT<TBase, TWinTraits>* pThis;
+        pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
+
+        HWND hwndOld = pThis->m_hWnd;
+        WNDPROC oldWindowProc = m_thunk.GetWNDPROC();
+        WNDPROC subclassedProc = reinterpret_cast<WNDPROC>(
+            ::GetWindowLongPtr(hwndOld, GWLP_WNDPROC));
+        if (!bForce && oldWindowProc != subclassedProc)
+            return NULL;
+
+        ::SetWindowLongPtr(hwndOld, GWLP_WNDPROC,
+                           (LONG_PTR)pThis->m_pfnSuperWindowProc);
+        pThis->m_pfnSuperWindowProc = ::DefWindowProc;
+        pThis->m_hWnd = NULL;
+        return hwndOld;
+    }
+
     virtual WNDPROC GetWindowProc()
     {
         return WindowProc;
@@ -1609,7 +1630,7 @@ public:
             MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
         if (rect.m_lpRect == NULL)
             rect.m_lpRect = &TBase::rcDefault;
-        hWnd = ::CreateWindowEx(dwExStyle, 
reinterpret_cast<LPCWSTR>(MAKEINTATOM(atom)), szWindowName, dwStyle, 
rect.m_lpRect->left,
+        hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, 
dwStyle, rect.m_lpRect->left,
                     rect.m_lpRect->top, rect.m_lpRect->right - 
rect.m_lpRect->left, rect.m_lpRect->bottom - rect.m_lpRect->top,
                     hWndParent, MenuOrID.m_hMenu, 
_AtlBaseModule.GetModuleInstance(), lpCreateParam);
 
@@ -1681,7 +1702,7 @@ public:
         m_pCurrentMsg = NULL;
     }
 
-    CContainedWindowT(LPTSTR lpszClassName, CMessageMap *pObject, DWORD 
dwMsgMapID = 0)
+    CContainedWindowT(LPCTSTR lpszClassName, CMessageMap *pObject, DWORD 
dwMsgMapID = 0)
     {
         m_lpszClassName = lpszClassName;
         m_pfnSuperWindowProc = ::DefWindowProc;
@@ -1697,28 +1718,48 @@ public:
 
     BOOL SubclassWindow(HWND hWnd)
     {
-        CContainedWindowT<TBase> *pThis;
-        WNDPROC newWindowProc;
-        WNDPROC oldWindowProc;
-        BOOL result;
-
         ATLASSERT(m_hWnd == NULL);
         ATLASSERT(::IsWindow(hWnd));
 
+        CContainedWindowT<TBase> *pThis;
         pThis = reinterpret_cast<CContainedWindowT<TBase> *>(this);
 
-        result = m_thunk.Init(WindowProc, pThis);
+        BOOL result = m_thunk.Init(WindowProc, pThis);
         if (result == FALSE)
             return FALSE;
-        newWindowProc = m_thunk.GetWNDPROC();
-        oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, 
GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
+
+        WNDPROC newWindowProc = m_thunk.GetWNDPROC();
+        WNDPROC oldWindowProc = reinterpret_cast<WNDPROC>(
+            ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, 
reinterpret_cast<LONG_PTR>(newWindowProc)));
         if (oldWindowProc == NULL)
             return FALSE;
-        m_pfnSuperWindowProc = oldWindowProc;
+
+        pThis->m_pfnSuperWindowProc = oldWindowProc;
         pThis->m_hWnd = hWnd;
         return TRUE;
     }
 
+    HWND UnsubclassWindow(BOOL bForce = FALSE)
+    {
+        ATLASSERT(m_hWnd != NULL);
+        ATLASSERT(::IsWindow(m_hWnd));
+
+        CContainedWindowT<TBase>* pThis;
+        pThis = reinterpret_cast<CContainedWindowT<TBase>*>(this);
+        HWND hwndOld = pThis->m_hWnd;
+
+        WNDPROC subclassedProc = reinterpret_cast<WNDPROC>(
+            ::GetWindowLongPtr(hwndOld, GWLP_WNDPROC));
+        if (!bForce && m_thunk.GetWNDPROC() != subclassedProc)
+            return NULL;
+
+        ::SetWindowLongPtr(hwndOld, GWLP_WNDPROC,
+                           (LONG_PTR)pThis->m_pfnSuperWindowProc);
+        pThis->m_pfnSuperWindowProc = ::DefWindowProc;
+        pThis->m_hWnd = NULL;
+        return hwndOld;
+    }
+
     static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM 
wParam, LPARAM lParam)
     {
         CContainedWindowT<TBase> *pThis;
@@ -1897,13 +1938,13 @@ static ATL::CWndClassInfo& GetWndClassInfo()
 
 struct _ATL_WNDCLASSINFOW
 {
-    WNDCLASSEXW m_wc;
-    LPCWSTR m_lpszOrigName;
+    WNDCLASSEX m_wc;
+    LPCTSTR m_lpszOrigName;
     WNDPROC pWndProc;
-    LPCWSTR m_lpszCursorID;
+    LPCTSTR m_lpszCursorID;
     BOOL m_bSystemCursor;
     ATOM m_atom;
-    WCHAR m_szAutoName[sizeof("ATL:") + sizeof(void *) * 2]; // == 4 
characters + NULL + number of hexadecimal digits describing a pointer.
+    TCHAR m_szAutoName[sizeof("ATL:") + sizeof(void *) * 2]; // == 4 
characters + NULL + number of hexadecimal digits describing a pointer.
 
     ATOM Register(WNDPROC *p)
     {

Reply via email to