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