1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Test for SubclassWindow/UnsubclassWindow
5  * PROGRAMMER:      Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6  */
7 
8 #ifdef HAVE_APITEST
9     #include <apitest.h>
10     #define ATLASSUME(x) /*empty*/
11     #undef ATLASSERT
12     #define ATLASSERT(x) /*empty*/
13 #else
14     #include "atltest.h"
15     #define ATLASSUME(x) do { \
16         trace("ATLASSUME(%s) %s.\n", #x, ((x) ? "success" : "failure")); \
17     } while (0)
18     #define ATLASSERT(x) do { \
19         trace("ATLASSERT(%s) %s.\n", #x, ((x) ? "success" : "failure")); \
20     } while (0)
21 #endif
22 
23 #include <atlbase.h>
24 #include <atlwin.h>
25 
26 #ifdef _WIN64
27     #define INVALID_HWND ((HWND)(ULONG_PTR)0xDEADBEEFDEADBEEFULL)
28 #else
29     #define INVALID_HWND ((HWND)(ULONG_PTR)0xDEADBEEF)
30 #endif
31 
32 static BOOL s_flag = TRUE;
33 
34 class CMyCtrl1 : public CWindowImpl<CMyCtrl1, CWindow>
35 {
36 public:
GetWndClassName()37     static LPCWSTR GetWndClassName()
38     {
39         if (s_flag)
40             return L"EDIT";
41         else
42             return L"STATIC";
43     }
44 
CMyCtrl1()45     CMyCtrl1()
46     {
47     }
~CMyCtrl1()48     virtual ~CMyCtrl1()
49     {
50     }
51 
52     BEGIN_MSG_MAP(CMyCtrl1)
53     END_MSG_MAP()
54 };
55 
56 class CMyCtrl2
57     : public CContainedWindowT<CWindowImpl<CMyCtrl2, CWindow> >
58 {
59 public:
GetWndClassName()60     static LPCWSTR GetWndClassName()
61     {
62         if (s_flag)
63             return L"EDIT";
64         else
65             return L"STATIC";
66     }
67 
CMyCtrl2()68     CMyCtrl2() : CContainedWindowT<CWindowImpl<CMyCtrl2, CWindow> >(this)
69     {
70     }
~CMyCtrl2()71     virtual ~CMyCtrl2()
72     {
73     }
74 
75     BEGIN_MSG_MAP(CMyCtrl2)
76     END_MSG_MAP()
77 };
78 
MyCreateWindow(DWORD style)79 static HWND MyCreateWindow(DWORD style)
80 {
81     return CreateWindowW(L"EDIT", NULL, style,
82                          CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
83                          NULL, NULL, GetModuleHandleW(NULL), NULL);
84 }
85 
86 static LRESULT CALLBACK
MyWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)87 MyWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
88 {
89     return 0;
90 }
91 
START_TEST(SubclassWindow)92 START_TEST(SubclassWindow)
93 {
94     const DWORD style = WS_POPUPWINDOW | ES_MULTILINE;
95     HWND hwnd1, hwnd2;
96     WNDPROC fn1, fn2;
97     BOOL b;
98     trace("DefWindowProcA == %p\n", DefWindowProcA);
99     trace("DefWindowProcW == %p\n", DefWindowProcW);
100     trace("MyWindowProc == %p\n", MyWindowProc);
101 
102     //
103     // Ctrl1
104     //
105     {
106         CMyCtrl1 Ctrl1;
107         s_flag = TRUE; // "EDIT"
108         hwnd1 = MyCreateWindow(style);
109         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
110         fn1 = Ctrl1.m_pfnSuperWindowProc;
111         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
112         b = Ctrl1.SubclassWindow(hwnd1);
113         ok_int(b, TRUE);
114         ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
115         fn1 = Ctrl1.m_pfnSuperWindowProc;
116         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
117         hwnd2 = Ctrl1.UnsubclassWindow();
118         ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
119         fn2 = Ctrl1.m_pfnSuperWindowProc;
120         ok(fn1 != fn2, "fn1 == fn2\n");
121         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
122         DestroyWindow(hwnd2);
123         ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
124     }
125 
126     {
127         CMyCtrl1 Ctrl1;
128         s_flag = TRUE; // "EDIT"
129         hwnd1 = MyCreateWindow(style);
130         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
131         fn1 = Ctrl1.m_pfnSuperWindowProc;
132         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
133         b = Ctrl1.SubclassWindow(hwnd1);
134         ok_int(b, TRUE);
135         ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
136         fn1 = Ctrl1.m_pfnSuperWindowProc;
137         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
138         DestroyWindow(hwnd1); // destroy now
139         hwnd2 = Ctrl1.UnsubclassWindow();
140         ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
141         fn2 = Ctrl1.m_pfnSuperWindowProc;
142         ok(fn2 == fn1, "fn2 was %p\n", fn2);
143         DestroyWindow(hwnd2);
144         ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
145     }
146 
147     {
148         CMyCtrl1 Ctrl1;
149         s_flag = FALSE; // "STATIC"
150         hwnd1 = MyCreateWindow(style);
151         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
152         fn1 = Ctrl1.m_pfnSuperWindowProc;
153         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
154         b = Ctrl1.SubclassWindow(hwnd1);
155         ok_int(b, TRUE);
156         ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
157         fn1 = Ctrl1.m_pfnSuperWindowProc;
158         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
159         hwnd2 = Ctrl1.UnsubclassWindow();
160         ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
161         fn2 = Ctrl1.m_pfnSuperWindowProc;
162         ok(fn1 != fn2, "fn1 == fn2\n");
163         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
164         DestroyWindow(hwnd2);
165         ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
166     }
167 
168     {
169         CMyCtrl1 Ctrl1;
170         s_flag = FALSE; // "STATIC"
171         hwnd1 = MyCreateWindow(style);
172         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
173         fn1 = Ctrl1.m_pfnSuperWindowProc;
174         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
175         b = Ctrl1.SubclassWindow(hwnd1);
176         ok_int(b, TRUE);
177         ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
178         fn1 = Ctrl1.m_pfnSuperWindowProc;
179         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
180         DestroyWindow(hwnd1); // destroy now
181         hwnd2 = Ctrl1.UnsubclassWindow();
182         ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
183         fn2 = Ctrl1.m_pfnSuperWindowProc;
184         ok(fn1 == fn2, "fn1 != fn2\n");
185         DestroyWindow(hwnd2);
186         ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
187     }
188 
189     {
190         CMyCtrl1 Ctrl1;
191         s_flag = TRUE; // "EDIT"
192         hwnd1 = MyCreateWindow(style);
193         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
194         fn1 = Ctrl1.m_pfnSuperWindowProc;
195         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
196         b = Ctrl1.SubclassWindow(hwnd1);
197         ok_int(b, TRUE);
198         ok(Ctrl1.m_hWnd == hwnd1, "Ctrl1.m_hWnd was %p\n", Ctrl1.m_hWnd);
199         Ctrl1.m_pfnSuperWindowProc = MyWindowProc;
200         hwnd2 = Ctrl1.UnsubclassWindow();
201         ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
202         fn2 = Ctrl1.m_pfnSuperWindowProc;
203         ok(fn1 == fn2, "fn2 was %p\n", fn2);
204         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
205         DestroyWindow(hwnd2);
206         ok(Ctrl1.m_hWnd == NULL, "hwnd != NULL\n");
207     }
208 
209     //
210     // Ctrl2 (Not Forced)
211     //
212     {
213         CMyCtrl2 Ctrl2;
214         s_flag = TRUE; // "EDIT"
215         hwnd1 = MyCreateWindow(style);
216         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
217         fn1 = Ctrl2.m_pfnSuperWindowProc;
218         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
219         b = Ctrl2.SubclassWindow(hwnd1);
220         ok_int(b, TRUE);
221         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
222         fn1 = Ctrl2.m_pfnSuperWindowProc;
223         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
224         hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
225         ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
226         fn2 = Ctrl2.m_pfnSuperWindowProc;
227         ok(fn1 != fn2, "fn1 == fn2\n");
228         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
229         DestroyWindow(hwnd2);
230         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
231     }
232 
233     {
234         CMyCtrl2 Ctrl2;
235         s_flag = TRUE; // "EDIT"
236         hwnd1 = MyCreateWindow(style);
237         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
238         fn1 = Ctrl2.m_pfnSuperWindowProc;
239         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
240         b = Ctrl2.SubclassWindow(hwnd1);
241         ok_int(b, TRUE);
242         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
243         fn1 = Ctrl2.m_pfnSuperWindowProc;
244         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
245         DestroyWindow(hwnd1); // destroy now
246         hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
247         ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
248         fn2 = Ctrl2.m_pfnSuperWindowProc;
249         ok(fn1 == fn2, "fn1 == fn2\n");
250         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
251         DestroyWindow(hwnd2);
252         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
253     }
254 
255     {
256         CMyCtrl2 Ctrl2;
257         s_flag = FALSE; // "STATIC"
258         hwnd1 = MyCreateWindow(style);
259         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
260         fn1 = Ctrl2.m_pfnSuperWindowProc;
261         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
262         b = Ctrl2.SubclassWindow(hwnd1);
263         ok_int(b, TRUE);
264         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
265         fn1 = Ctrl2.m_pfnSuperWindowProc;
266         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
267         hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
268         ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
269         fn2 = Ctrl2.m_pfnSuperWindowProc;
270         ok(fn1 != fn2, "fn1 == fn2\n");
271         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
272         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
273         DestroyWindow(hwnd2);
274         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
275     }
276 
277     {
278         CMyCtrl2 Ctrl2;
279         s_flag = FALSE; // "STATIC"
280         hwnd1 = MyCreateWindow(style);
281         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
282         fn1 = Ctrl2.m_pfnSuperWindowProc;
283         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
284         b = Ctrl2.SubclassWindow(hwnd1);
285         ok_int(b, TRUE);
286         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
287         fn1 = Ctrl2.m_pfnSuperWindowProc;
288         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
289         DestroyWindow(hwnd1); // destroy now
290         hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
291         ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
292         fn2 = Ctrl2.m_pfnSuperWindowProc;
293         ok(fn2 != DefWindowProc, "fn2 was %p\n", fn2); // ntdll.dll!NtdllEditWndProc_W
294         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
295         DestroyWindow(hwnd2);
296         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
297     }
298 
299     {
300         CMyCtrl2 Ctrl2;
301         s_flag = TRUE; // "EDIT"
302         hwnd1 = MyCreateWindow(style);
303         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
304         fn1 = Ctrl2.m_pfnSuperWindowProc;
305         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
306         b = Ctrl2.SubclassWindow(hwnd1);
307         ok_int(b, TRUE);
308         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
309         Ctrl2.m_pfnSuperWindowProc = MyWindowProc;
310         hwnd2 = Ctrl2.UnsubclassWindow(FALSE);
311         ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
312         fn2 = Ctrl2.m_pfnSuperWindowProc;
313         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
314         ok(Ctrl2.m_hWnd == NULL, "hwnd != NULL\n");
315         DestroyWindow(hwnd2);
316         ok(Ctrl2.m_hWnd == NULL, "hwnd != NULL\n");
317     }
318 
319     //
320     // Ctrl2 (Forced)
321     //
322     {
323         CMyCtrl2 Ctrl2;
324         s_flag = TRUE; // "EDIT"
325         hwnd1 = MyCreateWindow(style);
326         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
327         fn1 = Ctrl2.m_pfnSuperWindowProc;
328         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
329         b = Ctrl2.SubclassWindow(hwnd1);
330         ok_int(b, TRUE);
331         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
332         fn1 = Ctrl2.m_pfnSuperWindowProc;
333         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
334         hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
335         ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
336         fn2 = Ctrl2.m_pfnSuperWindowProc;
337         ok(fn1 != fn2, "fn1 == fn2\n");
338         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
339         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
340         DestroyWindow(hwnd2);
341         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
342     }
343 
344     {
345         CMyCtrl2 Ctrl2;
346         s_flag = TRUE; // "EDIT"
347         hwnd1 = MyCreateWindow(style);
348         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
349         fn1 = Ctrl2.m_pfnSuperWindowProc;
350         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
351         b = Ctrl2.SubclassWindow(hwnd1);
352         ok_int(b, TRUE);
353         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
354         fn1 = Ctrl2.m_pfnSuperWindowProc;
355         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
356         DestroyWindow(hwnd1); // destroy now
357         hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
358         ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
359         fn2 = Ctrl2.m_pfnSuperWindowProc;
360         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
361         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
362         DestroyWindow(hwnd2);
363         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
364     }
365 
366     {
367         CMyCtrl2 Ctrl2;
368         s_flag = FALSE; // "STATIC"
369         hwnd1 = MyCreateWindow(style);
370         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
371         fn1 = Ctrl2.m_pfnSuperWindowProc;
372         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
373         b = Ctrl2.SubclassWindow(hwnd1);
374         ok_int(b, TRUE);
375         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
376         fn1 = Ctrl2.m_pfnSuperWindowProc;
377         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
378         hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
379         ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
380         fn2 = Ctrl2.m_pfnSuperWindowProc;
381         ok(fn1 != fn2, "fn1 == fn2\n");
382         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
383         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
384         DestroyWindow(hwnd2);
385         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
386     }
387 
388     {
389         CMyCtrl2 Ctrl2;
390         s_flag = FALSE; // "STATIC"
391         hwnd1 = MyCreateWindow(style);
392         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
393         fn1 = Ctrl2.m_pfnSuperWindowProc;
394         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
395         b = Ctrl2.SubclassWindow(hwnd1);
396         ok_int(b, TRUE);
397         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
398         fn1 = Ctrl2.m_pfnSuperWindowProc;
399         ok(fn1 != DefWindowProc, "fn1 was %p\n", fn1);
400         DestroyWindow(hwnd1); // destroy now
401         hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
402         ok(hwnd2 == NULL, "hwnd2 was %p\n", hwnd2);
403         fn2 = Ctrl2.m_pfnSuperWindowProc;
404         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
405         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
406         DestroyWindow(hwnd2);
407         ok(Ctrl2.m_hWnd == NULL, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
408     }
409 
410     {
411         CMyCtrl2 Ctrl2;
412         s_flag = TRUE; // "EDIT"
413         hwnd1 = MyCreateWindow(style);
414         ok(hwnd1 != NULL, "hwnd1 was NULL\n");
415         fn1 = Ctrl2.m_pfnSuperWindowProc;
416         ok(fn1 == DefWindowProc, "fn1 was %p\n", fn1);
417         b = Ctrl2.SubclassWindow(hwnd1);
418         ok_int(b, TRUE);
419         ok(Ctrl2.m_hWnd == hwnd1, "Ctrl2.m_hWnd was %p\n", Ctrl2.m_hWnd);
420         Ctrl2.m_pfnSuperWindowProc = MyWindowProc;
421         hwnd2 = Ctrl2.UnsubclassWindow(TRUE);
422         ok(hwnd1 == hwnd2, "hwnd1 != hwnd2\n");
423         fn2 = Ctrl2.m_pfnSuperWindowProc;
424         ok(fn2 == DefWindowProc, "fn2 was %p\n", fn2);
425         ok(Ctrl2.m_hWnd == NULL, "hwnd != NULL\n");
426         DestroyWindow(hwnd2);
427         ok(Ctrl2.m_hWnd == NULL, "hwnd != NULL\n");
428     }
429 }
430