Fixed a race condition on RPC worker thread creation, and a typo.
[wine] / dlls / user / tests / win.c
1 /*
2  * Unit tests for window handling
3  *
4  * Copyright 2002 Bill Medland
5  * Copyright 2002 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30
31 #include "wine/test.h"
32
33 #ifndef IDC_ARROWA
34 # define IDC_ARROWA IDC_ARROW
35 #endif
36
37 #ifndef SPI_GETDESKWALLPAPER
38 #define SPI_GETDESKWALLPAPER 0x0073
39 #endif
40
41 #define LONG_PTR INT_PTR
42 #define ULONG_PTR UINT_PTR
43
44 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
45
46 static HWND hwndMain, hwndMain2;
47
48 /* check the values returned by the various parent/owner functions on a given window */
49 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
50                            HWND gw_owner, HWND ga_root, HWND ga_root_owner )
51 {
52     HWND res;
53
54     if (pGetAncestor)
55     {
56         res = pGetAncestor( hwnd, GA_PARENT );
57         ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p", res, ga_parent );
58     }
59     res = (HWND)GetWindowLongA( hwnd, GWL_HWNDPARENT );
60     ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p", res, gwl_parent );
61     res = GetParent( hwnd );
62     ok( res == get_parent, "Wrong result for GetParent %p expected %p", res, get_parent );
63     res = GetWindow( hwnd, GW_OWNER );
64     ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p", res, gw_owner );
65     if (pGetAncestor)
66     {
67         res = pGetAncestor( hwnd, GA_ROOT );
68         ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p", res, ga_root );
69         res = pGetAncestor( hwnd, GA_ROOTOWNER );
70         ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p", res, ga_root_owner );
71     }
72 }
73
74
75 static HWND create_tool_window( LONG style, HWND parent )
76 {
77     HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
78                                0, 0, 100, 100, parent, 0, 0, NULL );
79     ok( ret != 0, "Creation failed" );
80     return ret;
81 }
82
83 /* test parent and owner values for various combinations */
84 static void test_parent_owner(void)
85 {
86     LONG style;
87     HWND test, owner, ret;
88     HWND desktop = GetDesktopWindow();
89     HWND child = create_tool_window( WS_CHILD, hwndMain );
90
91     trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
92
93     /* child without parent, should fail */
94     test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
95                            WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
96     ok( !test, "WS_CHILD without parent created" );
97
98     /* desktop window */
99     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
100     style = GetWindowLongA( desktop, GWL_STYLE );
101     ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded" );
102     ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded" );
103     ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed" );
104
105     /* normal child window */
106     test = create_tool_window( WS_CHILD, hwndMain );
107     trace( "created child %p\n", test );
108     check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
109     SetWindowLongA( test, GWL_STYLE, 0 );
110     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
111     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
112     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
113     SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
114     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
115     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
116     DestroyWindow( test );
117
118     /* child of desktop */
119     test = create_tool_window( WS_CHILD, desktop );
120     trace( "created child of desktop %p\n", test );
121     check_parents( test, desktop, 0, desktop, 0, test, desktop );
122     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
123     check_parents( test, desktop, 0, 0, 0, test, test );
124     SetWindowLongA( test, GWL_STYLE, 0 );
125     check_parents( test, desktop, 0, 0, 0, test, test );
126     DestroyWindow( test );
127
128     /* child of child */
129     test = create_tool_window( WS_CHILD, child );
130     trace( "created child of child %p\n", test );
131     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
132     SetWindowLongA( test, GWL_STYLE, 0 );
133     check_parents( test, child, child, 0, 0, hwndMain, test );
134     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
135     check_parents( test, child, child, 0, 0, hwndMain, test );
136     DestroyWindow( test );
137
138     /* not owned top-level window */
139     test = create_tool_window( 0, 0 );
140     trace( "created top-level %p\n", test );
141     check_parents( test, desktop, 0, 0, 0, test, test );
142     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
143     check_parents( test, desktop, 0, 0, 0, test, test );
144     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
145     check_parents( test, desktop, 0, desktop, 0, test, desktop );
146     DestroyWindow( test );
147
148     /* owned top-level window */
149     test = create_tool_window( 0, hwndMain );
150     trace( "created owned top-level %p\n", test );
151     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
152     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
153     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
154     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
155     check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
156     DestroyWindow( test );
157
158     /* not owned popup */
159     test = create_tool_window( WS_POPUP, 0 );
160     trace( "created popup %p\n", test );
161     check_parents( test, desktop, 0, 0, 0, test, test );
162     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
163     check_parents( test, desktop, 0, desktop, 0, test, desktop );
164     SetWindowLongA( test, GWL_STYLE, 0 );
165     check_parents( test, desktop, 0, 0, 0, test, test );
166     DestroyWindow( test );
167
168     /* owned popup */
169     test = create_tool_window( WS_POPUP, hwndMain );
170     trace( "created owned popup %p\n", test );
171     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
172     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
173     check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
174     SetWindowLongA( test, GWL_STYLE, 0 );
175     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
176     DestroyWindow( test );
177
178     /* top-level window owned by child (same as owned by top-level) */
179     test = create_tool_window( 0, child );
180     trace( "created top-level owned by child %p\n", test );
181     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
182     DestroyWindow( test );
183
184     /* popup owned by desktop (same as not owned) */
185     test = create_tool_window( WS_POPUP, desktop );
186     trace( "created popup owned by desktop %p\n", test );
187     check_parents( test, desktop, 0, 0, 0, test, test );
188     DestroyWindow( test );
189
190     /* popup owned by child (same as owned by top-level) */
191     test = create_tool_window( WS_POPUP, child );
192     trace( "created popup owned by child %p\n", test );
193     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
194     DestroyWindow( test );
195
196     /* not owned popup with WS_CHILD (same as WS_POPUP only) */
197     test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
198     trace( "created WS_CHILD popup %p\n", test );
199     check_parents( test, desktop, 0, 0, 0, test, test );
200     DestroyWindow( test );
201
202     /* owned popup with WS_CHILD (same as WS_POPUP only) */
203     test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
204     trace( "created owned WS_CHILD popup %p\n", test );
205     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
206     DestroyWindow( test );
207
208     /******************** parent changes *************************/
209     trace( "testing parent changes\n" );
210
211     /* desktop window */
212     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
213     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
214     ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop" );
215     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
216     ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop" );
217     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
218
219     /* normal child window */
220     test = create_tool_window( WS_CHILD, hwndMain );
221     trace( "created child %p\n", test );
222
223     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
224     ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain );
225     check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
226
227     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
228     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
229     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
230
231     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)desktop );
232     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
233     check_parents( test, desktop, 0, desktop, 0, test, desktop );
234
235     /* window is now child of desktop so GWL_HWNDPARENT changes owner from now on */
236     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
237     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
238     check_parents( test, desktop, child, desktop, child, test, desktop );
239
240     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
241     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
242     check_parents( test, desktop, 0, desktop, 0, test, desktop );
243     DestroyWindow( test );
244
245     /* not owned top-level window */
246     test = create_tool_window( 0, 0 );
247     trace( "created top-level %p\n", test );
248
249     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
250     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
251     check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
252
253     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
254     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
255     check_parents( test, desktop, child, 0, child, test, test );
256
257     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
258     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
259     check_parents( test, desktop, 0, 0, 0, test, test );
260     DestroyWindow( test );
261
262     /* not owned popup */
263     test = create_tool_window( WS_POPUP, 0 );
264     trace( "created popup %p\n", test );
265
266     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
267     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
268     check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
269
270     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
271     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
272     check_parents( test, desktop, child, child, child, test, hwndMain );
273
274     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
275     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
276     check_parents( test, desktop, 0, 0, 0, test, test );
277     DestroyWindow( test );
278
279     /* normal child window */
280     test = create_tool_window( WS_CHILD, hwndMain );
281     trace( "created child %p\n", test );
282
283     ret = SetParent( test, desktop );
284     ok( ret == hwndMain, "SetParent return value %p expected %p", ret, hwndMain );
285     check_parents( test, desktop, 0, desktop, 0, test, desktop );
286
287     ret = SetParent( test, child );
288     ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
289     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
290
291     ret = SetParent( test, hwndMain2 );
292     ok( ret == child, "SetParent return value %p expected %p", ret, child );
293     check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
294     DestroyWindow( test );
295
296     /* not owned top-level window */
297     test = create_tool_window( 0, 0 );
298     trace( "created top-level %p\n", test );
299
300     ret = SetParent( test, child );
301     ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
302     check_parents( test, child, child, 0, 0, hwndMain, test );
303     DestroyWindow( test );
304
305     /* owned popup */
306     test = create_tool_window( WS_POPUP, hwndMain2 );
307     trace( "created owned popup %p\n", test );
308
309     ret = SetParent( test, child );
310     ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
311     check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
312
313     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)hwndMain );
314     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
315     check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
316     DestroyWindow( test );
317
318     /**************** test owner destruction *******************/
319
320     /* owned child popup */
321     owner = create_tool_window( 0, 0 );
322     test = create_tool_window( WS_POPUP, owner );
323     trace( "created owner %p and popup %p\n", owner, test );
324     ret = SetParent( test, child );
325     ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
326     check_parents( test, child, child, owner, owner, hwndMain, owner );
327     /* window is now child of 'child' but owned by 'owner' */
328     DestroyWindow( owner );
329     ok( IsWindow(test), "Window %p destroyed by owner destruction", test );
330     check_parents( test, child, child, owner, owner, hwndMain, owner );
331     ok( !IsWindow(owner), "Owner %p not destroyed", owner );
332     DestroyWindow(test);
333
334     /* owned top-level popup */
335     owner = create_tool_window( 0, 0 );
336     test = create_tool_window( WS_POPUP, owner );
337     trace( "created owner %p and popup %p\n", owner, test );
338     check_parents( test, desktop, owner, owner, owner, test, owner );
339     DestroyWindow( owner );
340     ok( !IsWindow(test), "Window %p not destroyed by owner destruction", test );
341
342     /* top-level popup owned by child */
343     owner = create_tool_window( WS_CHILD, hwndMain2 );
344     test = create_tool_window( WS_POPUP, 0 );
345     trace( "created owner %p and popup %p\n", owner, test );
346     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)owner );
347     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
348     check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
349     DestroyWindow( owner );
350     ok( IsWindow(test), "Window %p destroyed by owner destruction", test );
351     ok( !IsWindow(owner), "Owner %p not destroyed", owner );
352     check_parents( test, desktop, owner, owner, owner, test, owner );
353     DestroyWindow(test);
354
355     /* final cleanup */
356     DestroyWindow(child);
357 }
358
359
360 static BOOL RegisterWindowClasses(void)
361 {
362     WNDCLASSA cls;
363
364     cls.style = 0;
365     cls.lpfnWndProc = DefWindowProcA;
366     cls.cbClsExtra = 0;
367     cls.cbWndExtra = 0;
368     cls.hInstance = GetModuleHandleA(0);
369     cls.hIcon = 0;
370     cls.hCursor = LoadCursorA(0, IDC_ARROWA);
371     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
372     cls.lpszMenuName = NULL;
373     cls.lpszClassName = "MainWindowClass";
374
375     if(!RegisterClassA(&cls)) return FALSE;
376
377     cls.style = 0;
378     cls.lpfnWndProc = DefWindowProcA;
379     cls.cbClsExtra = 0;
380     cls.cbWndExtra = 0;
381     cls.hInstance = GetModuleHandleA(0);
382     cls.hIcon = 0;
383     cls.hCursor = LoadCursorA(0, IDC_ARROWA);
384     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
385     cls.lpszMenuName = NULL;
386     cls.lpszClassName = "ToolWindowClass";
387
388     if(!RegisterClassA(&cls)) return FALSE;
389
390     return TRUE;
391 }
392
393
394 START_TEST(win)
395 {
396     pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
397
398     if (!RegisterWindowClasses()) assert(0);
399
400     hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
401                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
402                                WS_MAXIMIZEBOX | WS_POPUP,
403                                100, 100, 200, 200,
404                                0, 0, 0, NULL);
405     hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
406                                 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
407                                 WS_MAXIMIZEBOX | WS_POPUP,
408                                 100, 100, 200, 200,
409                                 0, 0, 0, NULL);
410     assert( hwndMain );
411     assert( hwndMain2 );
412
413     test_parent_owner();
414 }