Added CSIDL_MYVIDEO|MYPICTURES|MYMUSIC to _SHRegisterUserShellFolders.
[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  * Copyright 2003 Dmitry Timoshkov
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 /* To get ICON_SMALL2 with the MSVC headers */
24 #define _WIN32_WINNT 0x0501
25
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33
34 #include "windef.h"
35 #include "winbase.h"
36 #include "wingdi.h"
37 #include "winuser.h"
38
39 #include "wine/test.h"
40
41 #ifndef SPI_GETDESKWALLPAPER
42 #define SPI_GETDESKWALLPAPER 0x0073
43 #endif
44
45 #define LONG_PTR INT_PTR
46 #define ULONG_PTR UINT_PTR
47
48 void dump_region(HRGN hrgn);
49
50 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
51 static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*);
52
53 static BOOL test_lbuttondown_flag;
54 static HWND hwndMessage;
55 static HWND hwndMain, hwndMain2;
56 static HHOOK hhook;
57
58 static const char* szAWRClass = "Winsize";
59 static HMENU hmenu;
60
61 #define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0]))
62
63 /* check the values returned by the various parent/owner functions on a given window */
64 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
65                            HWND gw_owner, HWND ga_root, HWND ga_root_owner )
66 {
67     HWND res;
68
69     if (pGetAncestor)
70     {
71         res = pGetAncestor( hwnd, GA_PARENT );
72         ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent );
73     }
74     res = (HWND)GetWindowLongPtrA( hwnd, GWLP_HWNDPARENT );
75     ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p\n", res, gwl_parent );
76     res = GetParent( hwnd );
77     ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent );
78     res = GetWindow( hwnd, GW_OWNER );
79     ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p\n", res, gw_owner );
80     if (pGetAncestor)
81     {
82         res = pGetAncestor( hwnd, GA_ROOT );
83         ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p\n", res, ga_root );
84         res = pGetAncestor( hwnd, GA_ROOTOWNER );
85         ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p\n", res, ga_root_owner );
86     }
87 }
88
89 BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam) 
90 {
91     (*(LPINT)lParam)++;
92     trace("EnumChildProc on %p\n", hwndChild);
93     if (*(LPINT)lParam > 1) return FALSE;
94     return TRUE;
95 }
96
97 static HWND create_tool_window( LONG style, HWND parent )
98 {
99     HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
100                                0, 0, 100, 100, parent, 0, 0, NULL );
101     ok( ret != 0, "Creation failed\n" );
102     return ret;
103 }
104
105 /* test parent and owner values for various combinations */
106 static void test_parent_owner(void)
107 {
108     LONG style;
109     HWND test, owner, ret;
110     HWND desktop = GetDesktopWindow();
111     HWND child = create_tool_window( WS_CHILD, hwndMain );
112     INT  numChildren;
113
114     trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
115
116     /* child without parent, should fail */
117     test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
118                            WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
119     ok( !test, "WS_CHILD without parent created\n" );
120
121     /* desktop window */
122     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
123     style = GetWindowLongA( desktop, GWL_STYLE );
124     ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" );
125     ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" );
126     ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" );
127
128     /* normal child window */
129     test = create_tool_window( WS_CHILD, hwndMain );
130     trace( "created child %p\n", test );
131     check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
132     SetWindowLongA( test, GWL_STYLE, 0 );
133     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
134     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
135     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
136     SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
137     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
138     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
139     DestroyWindow( test );
140
141     /* normal child window with WS_MAXIMIZE */
142     test = create_tool_window( WS_CHILD | WS_MAXIMIZE, hwndMain );
143     DestroyWindow( test );
144
145     /* normal child window with WS_THICKFRAME */
146     test = create_tool_window( WS_CHILD | WS_THICKFRAME, hwndMain );
147     DestroyWindow( test );
148
149     /* popup window with WS_THICKFRAME */
150     test = create_tool_window( WS_POPUP | WS_THICKFRAME, hwndMain );
151     DestroyWindow( test );
152
153     /* child of desktop */
154     test = create_tool_window( WS_CHILD, desktop );
155     trace( "created child of desktop %p\n", test );
156     check_parents( test, desktop, 0, desktop, 0, test, desktop );
157     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
158     check_parents( test, desktop, 0, 0, 0, test, test );
159     SetWindowLongA( test, GWL_STYLE, 0 );
160     check_parents( test, desktop, 0, 0, 0, test, test );
161     DestroyWindow( test );
162
163     /* child of desktop with WS_MAXIMIZE */
164     test = create_tool_window( WS_CHILD | WS_MAXIMIZE, desktop );
165     DestroyWindow( test );
166
167     /* child of desktop with WS_MINIMIZE */
168     test = create_tool_window( WS_CHILD | WS_MINIMIZE, desktop );
169     DestroyWindow( test );
170
171     /* child of child */
172     test = create_tool_window( WS_CHILD, child );
173     trace( "created child of child %p\n", test );
174     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
175     SetWindowLongA( test, GWL_STYLE, 0 );
176     check_parents( test, child, child, 0, 0, hwndMain, test );
177     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
178     check_parents( test, child, child, 0, 0, hwndMain, test );
179     DestroyWindow( test );
180
181     /* child of child with WS_MAXIMIZE */
182     test = create_tool_window( WS_CHILD | WS_MAXIMIZE, child );
183     DestroyWindow( test );
184
185     /* child of child with WS_MINIMIZE */
186     test = create_tool_window( WS_CHILD | WS_MINIMIZE, child );
187     DestroyWindow( test );
188
189     /* not owned top-level window */
190     test = create_tool_window( 0, 0 );
191     trace( "created top-level %p\n", test );
192     check_parents( test, desktop, 0, 0, 0, test, test );
193     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
194     check_parents( test, desktop, 0, 0, 0, test, test );
195     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
196     check_parents( test, desktop, 0, desktop, 0, test, desktop );
197     DestroyWindow( test );
198
199     /* not owned top-level window with WS_MAXIMIZE */
200     test = create_tool_window( WS_MAXIMIZE, 0 );
201     DestroyWindow( test );
202
203     /* owned top-level window */
204     test = create_tool_window( 0, hwndMain );
205     trace( "created owned top-level %p\n", test );
206     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
207     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
208     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
209     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
210     check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
211     DestroyWindow( test );
212
213     /* owned top-level window with WS_MAXIMIZE */
214     test = create_tool_window( WS_MAXIMIZE, hwndMain );
215     DestroyWindow( test );
216
217     /* not owned popup */
218     test = create_tool_window( WS_POPUP, 0 );
219     trace( "created popup %p\n", test );
220     check_parents( test, desktop, 0, 0, 0, test, test );
221     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
222     check_parents( test, desktop, 0, desktop, 0, test, desktop );
223     SetWindowLongA( test, GWL_STYLE, 0 );
224     check_parents( test, desktop, 0, 0, 0, test, test );
225     DestroyWindow( test );
226
227     /* not owned popup with WS_MAXIMIZE */
228     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, 0 );
229     DestroyWindow( test );
230
231     /* owned popup */
232     test = create_tool_window( WS_POPUP, hwndMain );
233     trace( "created owned popup %p\n", test );
234     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
235     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
236     check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
237     SetWindowLongA( test, GWL_STYLE, 0 );
238     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
239     DestroyWindow( test );
240
241     /* owned popup with WS_MAXIMIZE */
242     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, hwndMain );
243     DestroyWindow( test );
244
245     /* top-level window owned by child (same as owned by top-level) */
246     test = create_tool_window( 0, child );
247     trace( "created top-level owned by child %p\n", test );
248     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
249     DestroyWindow( test );
250
251     /* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */
252     test = create_tool_window( WS_MAXIMIZE, child );
253     DestroyWindow( test );
254
255     /* popup owned by desktop (same as not owned) */
256     test = create_tool_window( WS_POPUP, desktop );
257     trace( "created popup owned by desktop %p\n", test );
258     check_parents( test, desktop, 0, 0, 0, test, test );
259     DestroyWindow( test );
260
261     /* popup owned by desktop (same as not owned) with WS_MAXIMIZE */
262     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, desktop );
263     DestroyWindow( test );
264
265     /* popup owned by child (same as owned by top-level) */
266     test = create_tool_window( WS_POPUP, child );
267     trace( "created popup owned by child %p\n", test );
268     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
269     DestroyWindow( test );
270
271     /* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */
272     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, child );
273     DestroyWindow( test );
274
275     /* not owned popup with WS_CHILD (same as WS_POPUP only) */
276     test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
277     trace( "created WS_CHILD popup %p\n", test );
278     check_parents( test, desktop, 0, 0, 0, test, test );
279     DestroyWindow( test );
280
281     /* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */
282     test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, 0 );
283     DestroyWindow( test );
284
285     /* owned popup with WS_CHILD (same as WS_POPUP only) */
286     test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
287     trace( "created owned WS_CHILD popup %p\n", test );
288     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
289     DestroyWindow( test );
290
291     /* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */
292     test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, hwndMain );
293     DestroyWindow( test );
294
295     /******************** parent changes *************************/
296     trace( "testing parent changes\n" );
297
298     /* desktop window */
299     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
300 #if 0 /* this test succeeds on NT but crashes on win9x systems */
301     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
302     ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" );
303     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
304     ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" );
305     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
306 #endif
307     /* normal child window */
308     test = create_tool_window( WS_CHILD, hwndMain );
309     trace( "created child %p\n", test );
310
311     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
312     ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain );
313     check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
314
315     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
316     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
317     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
318
319     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)desktop );
320     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
321     check_parents( test, desktop, 0, desktop, 0, test, desktop );
322
323     /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */
324     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
325     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
326     check_parents( test, desktop, child, desktop, child, test, desktop );
327
328     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
329     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
330     check_parents( test, desktop, 0, desktop, 0, test, desktop );
331     DestroyWindow( test );
332
333     /* not owned top-level window */
334     test = create_tool_window( 0, 0 );
335     trace( "created top-level %p\n", test );
336
337     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
338     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
339     check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
340
341     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
342     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
343     check_parents( test, desktop, child, 0, child, test, test );
344
345     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
346     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
347     check_parents( test, desktop, 0, 0, 0, test, test );
348     DestroyWindow( test );
349
350     /* not owned popup */
351     test = create_tool_window( WS_POPUP, 0 );
352     trace( "created popup %p\n", test );
353
354     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
355     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
356     check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
357
358     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
359     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
360     check_parents( test, desktop, child, child, child, test, hwndMain );
361
362     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
363     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
364     check_parents( test, desktop, 0, 0, 0, test, test );
365     DestroyWindow( test );
366
367     /* normal child window */
368     test = create_tool_window( WS_CHILD, hwndMain );
369     trace( "created child %p\n", test );
370
371     ret = SetParent( test, desktop );
372     ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain );
373     check_parents( test, desktop, 0, desktop, 0, test, desktop );
374
375     ret = SetParent( test, child );
376     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
377     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
378
379     ret = SetParent( test, hwndMain2 );
380     ok( ret == child, "SetParent return value %p expected %p\n", ret, child );
381     check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
382     DestroyWindow( test );
383
384     /* not owned top-level window */
385     test = create_tool_window( 0, 0 );
386     trace( "created top-level %p\n", test );
387
388     ret = SetParent( test, child );
389     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
390     check_parents( test, child, child, 0, 0, hwndMain, test );
391     DestroyWindow( test );
392
393     /* owned popup */
394     test = create_tool_window( WS_POPUP, hwndMain2 );
395     trace( "created owned popup %p\n", test );
396
397     ret = SetParent( test, child );
398     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
399     check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
400
401     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)hwndMain );
402     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
403     check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
404     DestroyWindow( test );
405
406     /**************** test owner destruction *******************/
407
408     /* owned child popup */
409     owner = create_tool_window( 0, 0 );
410     test = create_tool_window( WS_POPUP, owner );
411     trace( "created owner %p and popup %p\n", owner, test );
412     ret = SetParent( test, child );
413     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
414     check_parents( test, child, child, owner, owner, hwndMain, owner );
415     /* window is now child of 'child' but owned by 'owner' */
416     DestroyWindow( owner );
417     ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
418     /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
419      * while Win95, Win2k, WinXP do.
420      */
421     /*check_parents( test, child, child, owner, owner, hwndMain, owner );*/
422     ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
423     DestroyWindow(test);
424
425     /* owned top-level popup */
426     owner = create_tool_window( 0, 0 );
427     test = create_tool_window( WS_POPUP, owner );
428     trace( "created owner %p and popup %p\n", owner, test );
429     check_parents( test, desktop, owner, owner, owner, test, owner );
430     DestroyWindow( owner );
431     ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test );
432
433     /* top-level popup owned by child */
434     owner = create_tool_window( WS_CHILD, hwndMain2 );
435     test = create_tool_window( WS_POPUP, 0 );
436     trace( "created owner %p and popup %p\n", owner, test );
437     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)owner );
438     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
439     check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
440     DestroyWindow( owner );
441     ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
442     ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
443     /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
444      * while Win95, Win2k, WinXP do.
445      */
446     /*check_parents( test, desktop, owner, owner, owner, test, owner );*/
447     DestroyWindow(test);
448
449     /* final cleanup */
450     DestroyWindow(child);
451
452
453     owner = create_tool_window( WS_OVERLAPPED, 0 );
454     test = create_tool_window( WS_POPUP, NULL );
455     numChildren = 0;
456     ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
457         "EnumChildWindows should have returned FALSE\n" );
458     ok( numChildren == 0, "numChildren should be 0 got %d\n", numChildren );
459
460     SetWindowLongA( test, GWL_STYLE, (GetWindowLongA( test, GWL_STYLE ) & ~WS_POPUP) | WS_CHILD );
461     ret = SetParent( test, owner );
462     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
463
464     numChildren = 0;
465     ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
466         "EnumChildWindows should have returned TRUE\n" );
467     ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
468
469     child = create_tool_window( WS_CHILD, owner );
470     numChildren = 0;
471     ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
472         "EnumChildWindows should have returned FALSE\n" );
473     ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
474
475     DestroyWindow( child );
476     DestroyWindow( test );
477     DestroyWindow( owner );
478 }
479
480
481 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
482 {
483     switch (msg)
484     {
485         case WM_GETMINMAXINFO:
486         {
487             MINMAXINFO* minmax = (MINMAXINFO *)lparam;
488
489             trace("hwnd %p, WM_GETMINMAXINFO, %08x, %08lx\n", hwnd, wparam, lparam);
490             trace("ptReserved (%ld,%ld), ptMaxSize (%ld,%ld), ptMaxPosition (%ld,%ld)\n"
491                   "       ptMinTrackSize (%ld,%ld), ptMaxTrackSize (%ld,%ld)\n",
492                   minmax->ptReserved.x, minmax->ptReserved.y,
493                   minmax->ptMaxSize.x, minmax->ptMaxSize.y,
494                   minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
495                   minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
496                   minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
497             SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
498             break;
499         }
500         case WM_WINDOWPOSCHANGING:
501         {
502             BOOL is_win9x = GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == 0;
503             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
504             trace("main: WM_WINDOWPOSCHANGING\n");
505             trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
506                    winpos->hwnd, winpos->hwndInsertAfter,
507                    winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
508             if (!(winpos->flags & SWP_NOMOVE))
509             {
510                 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
511                 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
512             }
513             /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */
514             if (!(winpos->flags & SWP_NOSIZE) && !is_win9x)
515             {
516                 ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx);
517                 ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy);
518             }
519             break;
520         }
521         case WM_WINDOWPOSCHANGED:
522         {
523             RECT rc1, rc2;
524             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
525             trace("main: WM_WINDOWPOSCHANGED\n");
526             trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
527                    winpos->hwnd, winpos->hwndInsertAfter,
528                    winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
529             ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
530             ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
531
532             ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx);
533             ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy);
534
535             GetWindowRect(hwnd, &rc1);
536             trace("window: (%ld,%ld)-(%ld,%ld)\n", rc1.left, rc1.top, rc1.right, rc1.bottom);
537             SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
538             /* note: winpos coordinates are relative to parent */
539             MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
540             trace("pos: (%ld,%ld)-(%ld,%ld)\n", rc2.left, rc2.top, rc2.right, rc2.bottom);
541 #if 0 /* Uncomment this once the test succeeds in all cases */
542             ok(EqualRect(&rc1, &rc2), "rects do not match\n");
543 #endif
544
545             GetClientRect(hwnd, &rc2);
546             DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
547             MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
548             ok(EqualRect(&rc1, &rc2), "rects do not match (%ld,%ld-%ld,%ld) / (%ld,%ld-%ld,%ld)\n",
549                rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom );
550             break;
551         }
552         case WM_NCCREATE:
553         {
554             BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
555             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
556
557             trace("WM_NCCREATE: hwnd %p, parent %p, style %08lx\n", hwnd, cs->hwndParent, cs->style);
558             if (got_getminmaxinfo)
559                 trace("%p got WM_GETMINMAXINFO\n", hwnd);
560
561             if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
562                 ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
563             else
564                 ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
565             break;
566         }
567         case WM_COMMAND:
568             if (test_lbuttondown_flag)
569                 ShowWindow((HWND)wparam, SW_SHOW);
570             break;
571     }
572
573     return DefWindowProcA(hwnd, msg, wparam, lparam);
574 }
575
576 static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
577 {
578     switch (msg)
579     {
580         case WM_GETMINMAXINFO:
581         {
582             MINMAXINFO* minmax = (MINMAXINFO *)lparam;
583
584             trace("hwnd %p, WM_GETMINMAXINFO, %08x, %08lx\n", hwnd, wparam, lparam);
585             trace("ptReserved (%ld,%ld), ptMaxSize (%ld,%ld), ptMaxPosition (%ld,%ld)\n"
586                   "       ptMinTrackSize (%ld,%ld), ptMaxTrackSize (%ld,%ld)\n",
587                   minmax->ptReserved.x, minmax->ptReserved.y,
588                   minmax->ptMaxSize.x, minmax->ptMaxSize.y,
589                   minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
590                   minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
591                   minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
592             SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
593             break;
594         }
595         case WM_NCCREATE:
596         {
597             BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
598             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
599
600             trace("WM_NCCREATE: hwnd %p, parent %p, style %08lx\n", hwnd, cs->hwndParent, cs->style);
601             if (got_getminmaxinfo)
602                 trace("%p got WM_GETMINMAXINFO\n", hwnd);
603
604             if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
605                 ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
606             else
607                 ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
608             break;
609         }
610     }
611
612     return DefWindowProcA(hwnd, msg, wparam, lparam);
613 }
614
615 static BOOL RegisterWindowClasses(void)
616 {
617     WNDCLASSA cls;
618
619     cls.style = CS_DBLCLKS;
620     cls.lpfnWndProc = main_window_procA;
621     cls.cbClsExtra = 0;
622     cls.cbWndExtra = 0;
623     cls.hInstance = GetModuleHandleA(0);
624     cls.hIcon = 0;
625     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
626     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
627     cls.lpszMenuName = NULL;
628     cls.lpszClassName = "MainWindowClass";
629
630     if(!RegisterClassA(&cls)) return FALSE;
631
632     cls.style = 0;
633     cls.lpfnWndProc = tool_window_procA;
634     cls.cbClsExtra = 0;
635     cls.cbWndExtra = 0;
636     cls.hInstance = GetModuleHandleA(0);
637     cls.hIcon = 0;
638     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
639     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
640     cls.lpszMenuName = NULL;
641     cls.lpszClassName = "ToolWindowClass";
642
643     if(!RegisterClassA(&cls)) return FALSE;
644
645     return TRUE;
646 }
647
648 static void verify_window_info(HWND hwnd, const WINDOWINFO *info, BOOL test_borders)
649 {
650     RECT rcWindow, rcClient;
651     UINT border;
652     DWORD status;
653
654     ok(IsWindow(hwnd), "bad window handle\n");
655
656     GetWindowRect(hwnd, &rcWindow);
657     ok(EqualRect(&rcWindow, &info->rcWindow), "wrong rcWindow\n");
658
659     GetClientRect(hwnd, &rcClient);
660     /* translate to screen coordinates */
661     MapWindowPoints(hwnd, 0, (LPPOINT)&rcClient, 2);
662     ok(EqualRect(&rcClient, &info->rcClient), "wrong rcClient\n");
663
664     ok(info->dwStyle == (DWORD)GetWindowLongA(hwnd, GWL_STYLE),
665        "wrong dwStyle: %08lx != %08lx\n", info->dwStyle, GetWindowLongA(hwnd, GWL_STYLE));
666     ok(info->dwExStyle == (DWORD)GetWindowLongA(hwnd, GWL_EXSTYLE),
667        "wrong dwExStyle: %08lx != %08lx\n", info->dwExStyle, GetWindowLongA(hwnd, GWL_EXSTYLE));
668     status = (GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0;
669     ok(info->dwWindowStatus == status, "wrong dwWindowStatus: %04lx != %04lx\n",
670        info->dwWindowStatus, status);
671
672     if (test_borders && !IsRectEmpty(&rcWindow))
673     {
674         trace("rcWindow: %ld,%ld - %ld,%ld\n", rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom);
675         trace("rcClient: %ld,%ld - %ld,%ld\n", rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
676
677         ok(info->cxWindowBorders == (unsigned)(rcClient.left - rcWindow.left),
678             "wrong cxWindowBorders %d != %ld\n", info->cxWindowBorders, rcClient.left - rcWindow.left);
679         border = min(rcWindow.bottom - rcClient.bottom, rcClient.top - rcWindow.top);
680         ok(info->cyWindowBorders == border,
681            "wrong cyWindowBorders %d != %d\n", info->cyWindowBorders, border);
682     }
683
684     ok(info->atomWindowType == GetClassLongA(hwnd, GCW_ATOM), "wrong atomWindowType\n");
685     ok(info->wCreatorVersion == 0x0400, "wrong wCreatorVersion %04x\n", info->wCreatorVersion);
686 }
687
688 static void FixedAdjustWindowRectEx(RECT* rc, LONG style, BOOL menu, LONG exstyle)
689 {
690     AdjustWindowRectEx(rc, style, menu, exstyle);
691     /* AdjustWindowRectEx does not include scroll bars */
692     if (style & WS_VSCROLL)
693     {
694         if(exstyle & WS_EX_LEFTSCROLLBAR)
695             rc->left  -= GetSystemMetrics(SM_CXVSCROLL);
696         else
697             rc->right += GetSystemMetrics(SM_CXVSCROLL);
698     }
699     if (style & WS_HSCROLL)
700         rc->bottom += GetSystemMetrics(SM_CYHSCROLL);
701 }
702
703 static void test_nonclient_area(HWND hwnd)
704 {
705     DWORD style, exstyle;
706     RECT rc_window, rc_client, rc;
707     BOOL menu;
708     BOOL is_win9x = GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == 0;
709
710     style = GetWindowLongA(hwnd, GWL_STYLE);
711     exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
712     menu = !(style & WS_CHILD) && GetMenu(hwnd) != 0;
713
714     GetWindowRect(hwnd, &rc_window);
715     trace("window: (%ld,%ld)-(%ld,%ld)\n", rc_window.left, rc_window.top, rc_window.right, rc_window.bottom);
716     GetClientRect(hwnd, &rc_client);
717     trace("client: (%ld,%ld)-(%ld,%ld)\n", rc_client.left, rc_client.top, rc_client.right, rc_client.bottom);
718
719     /* avoid some cases when things go wrong */
720     if (IsRectEmpty(&rc_window) || IsRectEmpty(&rc_client) ||
721         rc_window.right > 32768 || rc_window.bottom > 32768) return;
722
723     CopyRect(&rc, &rc_client);
724     MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
725     FixedAdjustWindowRectEx(&rc, style, menu, exstyle);
726
727     trace("calc window: (%ld,%ld)-(%ld,%ld)\n", rc.left, rc.top, rc.right, rc.bottom);
728     ok(EqualRect(&rc, &rc_window), "window rect does not match: style:exstyle=0x%08lx:0x%08lx, menu=%d\n", style, exstyle, menu);
729
730
731     CopyRect(&rc, &rc_window);
732     DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
733     MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
734     trace("calc client: (%ld,%ld)-(%ld,%ld)\n", rc.left, rc.top, rc.right, rc.bottom);
735     ok(EqualRect(&rc, &rc_client), "client rect does not match: style:exstyle=0x%08lx:0x%08lx, menu=%d\n", style, exstyle, menu);
736
737     /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */;
738     if (is_win9x)
739         return;
740
741     /* and now test AdjustWindowRectEx and WM_NCCALCSIZE on synthetic data */
742     SetRect(&rc_client, 0, 0, 250, 150);
743     CopyRect(&rc_window, &rc_client);
744     MapWindowPoints(hwnd, 0, (LPPOINT)&rc_window, 2);
745     FixedAdjustWindowRectEx(&rc_window, style, menu, exstyle);
746     trace("calc window: (%ld,%ld)-(%ld,%ld)\n",
747         rc_window.left, rc_window.top, rc_window.right, rc_window.bottom);
748
749     CopyRect(&rc, &rc_window);
750     DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
751     MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
752     trace("calc client: (%ld,%ld)-(%ld,%ld)\n", rc.left, rc.top, rc.right, rc.bottom);
753     ok(EqualRect(&rc, &rc_client), "synthetic rect does not match: style:exstyle=0x%08lx:0x%08lx, menu=%d\n", style, exstyle, menu);
754 }
755
756 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 
757
758     static const char *CBT_code_name[10] = {
759         "HCBT_MOVESIZE",
760         "HCBT_MINMAX",
761         "HCBT_QS",
762         "HCBT_CREATEWND",
763         "HCBT_DESTROYWND",
764         "HCBT_ACTIVATE",
765         "HCBT_CLICKSKIPPED",
766         "HCBT_KEYSKIPPED",
767         "HCBT_SYSCOMMAND",
768         "HCBT_SETFOCUS" };
769     const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
770
771     trace("CBT: %d (%s), %08x, %08lx\n", nCode, code_name, wParam, lParam);
772
773     /* on HCBT_DESTROYWND window state is undefined */
774     if (nCode != HCBT_DESTROYWND && IsWindow((HWND)wParam))
775     {
776         if (pGetWindowInfo)
777         {
778             WINDOWINFO info;
779
780             /* Win98 actually does check the info.cbSize and doesn't allow
781              * it to be anything except sizeof(WINDOWINFO), while Win95, Win2k,
782              * WinXP do not check it at all.
783              */
784             info.cbSize = sizeof(WINDOWINFO);
785             ok(pGetWindowInfo((HWND)wParam, &info), "GetWindowInfo should not fail\n");
786             /* win2k SP4 returns broken border info if GetWindowInfo
787              * is being called from HCBT_DESTROYWND or HCBT_MINMAX hook proc.
788              */
789             verify_window_info((HWND)wParam, &info, nCode != HCBT_MINMAX);
790         }
791     }
792
793     switch (nCode)
794     {
795         case HCBT_CREATEWND:
796         {
797 #if 0 /* Uncomment this once the test succeeds in all cases */
798             static const RECT rc_null;
799             RECT rc;
800 #endif
801             LONG style;
802             CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
803             trace("HCBT_CREATEWND: hwnd %p, parent %p, style %08lx\n",
804                   (HWND)wParam, createwnd->lpcs->hwndParent, createwnd->lpcs->style);
805             ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
806
807             /* WS_VISIBLE should be turned off yet */
808             style = createwnd->lpcs->style & ~WS_VISIBLE;
809             ok(style == GetWindowLongA((HWND)wParam, GWL_STYLE),
810                 "style of hwnd and style in the CREATESTRUCT do not match: %08lx != %08lx\n",
811                 GetWindowLongA((HWND)wParam, GWL_STYLE), style);
812
813 #if 0 /* Uncomment this once the test succeeds in all cases */
814             if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
815             {
816                 ok(GetParent((HWND)wParam) == hwndMessage,
817                    "wrong result from GetParent %p: message window %p\n",
818                    GetParent((HWND)wParam), hwndMessage);
819             }
820             else
821                 ok(!GetParent((HWND)wParam), "GetParent should return 0 at this point\n");
822
823             ok(!GetWindow((HWND)wParam, GW_OWNER), "GW_OWNER should be set to 0 at this point\n");
824 #endif
825 #if 0       /* while NT assigns GW_HWNDFIRST/LAST some values at this point,
826              * Win9x still has them set to 0.
827              */
828             ok(GetWindow((HWND)wParam, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n");
829             ok(GetWindow((HWND)wParam, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n");
830 #endif
831             ok(!GetWindow((HWND)wParam, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n");
832             ok(!GetWindow((HWND)wParam, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n");
833
834 #if 0 /* Uncomment this once the test succeeds in all cases */
835             if (pGetAncestor)
836             {
837                 ok(pGetAncestor((HWND)wParam, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n");
838                 ok(pGetAncestor((HWND)wParam, GA_ROOT) == (HWND)wParam,
839                    "GA_ROOT is set to %p, expected %p\n", pGetAncestor((HWND)wParam, GA_ROOT), (HWND)wParam);
840
841                 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
842                     ok(pGetAncestor((HWND)wParam, GA_ROOTOWNER) == hwndMessage,
843                        "GA_ROOTOWNER should be set to hwndMessage at this point\n");
844                 else
845                     ok(pGetAncestor((HWND)wParam, GA_ROOTOWNER) == (HWND)wParam,
846                        "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor((HWND)wParam, GA_ROOTOWNER), (HWND)wParam);
847             }
848
849             ok(GetWindowRect((HWND)wParam, &rc), "GetWindowRect failed\n");
850             ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n");
851             ok(GetClientRect((HWND)wParam, &rc), "GetClientRect failed\n");
852             ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n");
853 #endif
854             break;
855         }
856     }
857
858     return CallNextHookEx(hhook, nCode, wParam, lParam);
859 }
860
861 static void test_shell_window(void)
862 {
863     BOOL ret;
864     DWORD error;
865     HMODULE hinst, hUser32;
866     BOOL (WINAPI*SetShellWindow)(HWND);
867     BOOL (WINAPI*SetShellWindowEx)(HWND, HWND);
868     HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5;
869     HWND shellWindow, nextWnd;
870
871     if (!GetWindowLongW(GetDesktopWindow(), GWL_STYLE))
872     {
873         trace("Skipping shell window test on Win9x\n");
874         return;
875     }
876
877     shellWindow = GetShellWindow();
878     hinst = GetModuleHandle(0);
879     hUser32 = GetModuleHandleA("user32");
880
881     SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow");
882     SetShellWindowEx = (void *)GetProcAddress(hUser32, "SetShellWindowEx");
883
884     trace("previous shell window: %p\n", shellWindow);
885
886     if (shellWindow) {
887         DWORD pid;
888         HANDLE hProcess;
889
890         ret = DestroyWindow(shellWindow);
891         error = GetLastError();
892
893         ok(!ret, "DestroyWindow(shellWindow)\n");
894         /* passes on Win XP, but not on Win98 */
895         ok(error==ERROR_ACCESS_DENIED, "ERROR_ACCESS_DENIED after DestroyWindow(shellWindow)\n");
896
897         /* close old shell instance */
898         GetWindowThreadProcessId(shellWindow, &pid);
899         hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
900         ret = TerminateProcess(hProcess, 0);
901         ok(ret, "termination of previous shell process failed: GetLastError()=%ld\n", GetLastError());
902         WaitForSingleObject(hProcess, INFINITE);    /* wait for termination */
903         CloseHandle(hProcess);
904     }
905
906     hwnd1 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST1"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0);
907     trace("created window 1: %p\n", hwnd1);
908
909     ret = SetShellWindow(hwnd1);
910     ok(ret, "first call to SetShellWindow(hwnd1)\n");
911     shellWindow = GetShellWindow();
912     ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow);
913
914     ret = SetShellWindow(hwnd1);
915     ok(!ret, "second call to SetShellWindow(hwnd1)\n");
916
917     ret = SetShellWindow(0);
918     error = GetLastError();
919     /* passes on Win XP, but not on Win98
920     ok(!ret, "reset shell window by SetShellWindow(0)\n");
921     ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */
922
923     ret = SetShellWindow(hwnd1);
924     /* passes on Win XP, but not on Win98
925     ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */
926
927     todo_wine
928     {
929         SetWindowLong(hwnd1, GWL_EXSTYLE, GetWindowLong(hwnd1,GWL_EXSTYLE)|WS_EX_TOPMOST);
930         ret = GetWindowLong(hwnd1,GWL_EXSTYLE)&WS_EX_TOPMOST? TRUE: FALSE;
931         ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n");
932     }
933
934     ret = DestroyWindow(hwnd1);
935     ok(ret, "DestroyWindow(hwnd1)\n");
936
937     hwnd2 = CreateWindowEx(WS_EX_TOPMOST, TEXT("#32770"), TEXT("TEST2"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
938     trace("created window 2: %p\n", hwnd2);
939     ret = SetShellWindow(hwnd2);
940     ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n");
941
942     hwnd3 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST3"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
943     trace("created window 3: %p\n", hwnd3);
944
945     hwnd4 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST4"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0);
946     trace("created window 4: %p\n", hwnd4);
947
948     nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
949     ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd);
950
951     ret = SetShellWindow(hwnd4);
952     ok(ret, "SetShellWindow(hwnd4)\n");
953     shellWindow = GetShellWindow();
954     ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
955
956     nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
957     ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
958
959     ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
960     ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
961
962     ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
963     ok(ret, "SetWindowPos(hwnd4, hwnd3\n");
964
965     ret = SetShellWindow(hwnd3);
966     ok(!ret, "SetShellWindow(hwnd3)\n");
967     shellWindow = GetShellWindow();
968     ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
969
970     hwnd5 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST5"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
971     trace("created window 5: %p\n", hwnd5);
972     ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
973     ok(ret, "SetWindowPos(hwnd4, hwnd5)\n");
974
975     todo_wine
976     {
977         nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
978         ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd);
979     }
980
981     /* destroy test windows */
982     DestroyWindow(hwnd2);
983     DestroyWindow(hwnd3);
984     DestroyWindow(hwnd4);
985     DestroyWindow(hwnd5);
986 }
987
988 /************** MDI test ****************/
989
990 static const char mdi_lParam_test_message[] = "just a test string";
991
992 static void test_MDI_create(HWND parent, HWND mdi_client, INT first_id)
993 {
994     MDICREATESTRUCTA mdi_cs;
995     HWND mdi_child;
996     static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
997     static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
998     BOOL isWin9x = FALSE;
999
1000     mdi_cs.szClass = "MDI_child_Class_1";
1001     mdi_cs.szTitle = "MDI child";
1002     mdi_cs.hOwner = GetModuleHandle(0);
1003     mdi_cs.x = CW_USEDEFAULT;
1004     mdi_cs.y = CW_USEDEFAULT;
1005     mdi_cs.cx = CW_USEDEFAULT;
1006     mdi_cs.cy = CW_USEDEFAULT;
1007     mdi_cs.style = 0;
1008     mdi_cs.lParam = (LPARAM)mdi_lParam_test_message;
1009     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1010     ok(mdi_child != 0, "MDI child creation failed\n");
1011     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1012     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1013     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1014
1015     mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
1016     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1017     ok(mdi_child != 0, "MDI child creation failed\n");
1018     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1019     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1020     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1021
1022     mdi_cs.style = 0xffffffff; /* with WS_POPUP */
1023     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1024     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1025     {
1026         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1027     }
1028     else
1029     {
1030         ok(mdi_child != 0, "MDI child creation failed\n");
1031         ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1032         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1033         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1034     }
1035
1036     /* test MDICREATESTRUCT A<->W mapping */
1037     /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
1038     mdi_cs.style = 0;
1039     mdi_cs.szClass = (LPCSTR)classW;
1040     mdi_cs.szTitle = (LPCSTR)titleW;
1041     SetLastError(0xdeadbeef);
1042     mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1043     if (!mdi_child)
1044     {
1045         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1046             isWin9x = TRUE;
1047         else
1048             ok(mdi_child != 0, "MDI child creation failed\n");
1049     }
1050     else
1051     {
1052         ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1053         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1054         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1055     }
1056
1057     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1058                                  0,
1059                                  CW_USEDEFAULT, CW_USEDEFAULT,
1060                                  CW_USEDEFAULT, CW_USEDEFAULT,
1061                                  mdi_client, GetModuleHandle(0),
1062                                  (LPARAM)mdi_lParam_test_message);
1063     ok(mdi_child != 0, "MDI child creation failed\n");
1064     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1065     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1066     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1067
1068     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1069                                  0x7fffffff, /* without WS_POPUP */
1070                                  CW_USEDEFAULT, CW_USEDEFAULT,
1071                                  CW_USEDEFAULT, CW_USEDEFAULT,
1072                                  mdi_client, GetModuleHandle(0),
1073                                  (LPARAM)mdi_lParam_test_message);
1074     ok(mdi_child != 0, "MDI child creation failed\n");
1075     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1076     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1077     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1078
1079     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1080                                  0xffffffff, /* with WS_POPUP */
1081                                  CW_USEDEFAULT, CW_USEDEFAULT,
1082                                  CW_USEDEFAULT, CW_USEDEFAULT,
1083                                  mdi_client, GetModuleHandle(0),
1084                                  (LPARAM)mdi_lParam_test_message);
1085     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1086     {
1087         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1088     }
1089     else
1090     {
1091         ok(mdi_child != 0, "MDI child creation failed\n");
1092         ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1093         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1094         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1095     }
1096
1097     /* test MDICREATESTRUCT A<->W mapping */
1098     SetLastError(0xdeadbeef);
1099     mdi_child = CreateMDIWindowW(classW, titleW,
1100                                  0,
1101                                  CW_USEDEFAULT, CW_USEDEFAULT,
1102                                  CW_USEDEFAULT, CW_USEDEFAULT,
1103                                  mdi_client, GetModuleHandle(0),
1104                                  (LPARAM)mdi_lParam_test_message);
1105     if (!mdi_child)
1106     {
1107         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1108             isWin9x = TRUE;
1109         else
1110             ok(mdi_child != 0, "MDI child creation failed\n");
1111     }
1112     else
1113     {
1114         ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1115         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1116         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1117     }
1118
1119     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1120                                 0,
1121                                 CW_USEDEFAULT, CW_USEDEFAULT,
1122                                 CW_USEDEFAULT, CW_USEDEFAULT,
1123                                 mdi_client, 0, GetModuleHandle(0),
1124                                 (LPVOID)mdi_lParam_test_message);
1125     ok(mdi_child != 0, "MDI child creation failed\n");
1126     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1127     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1128     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1129
1130     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1131                                 0x7fffffff, /* without WS_POPUP */
1132                                 CW_USEDEFAULT, CW_USEDEFAULT,
1133                                 CW_USEDEFAULT, CW_USEDEFAULT,
1134                                 mdi_client, 0, GetModuleHandle(0),
1135                                 (LPVOID)mdi_lParam_test_message);
1136     ok(mdi_child != 0, "MDI child creation failed\n");
1137     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1138     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1139     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1140
1141     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1142                                 0xffffffff, /* with WS_POPUP */
1143                                 CW_USEDEFAULT, CW_USEDEFAULT,
1144                                 CW_USEDEFAULT, CW_USEDEFAULT,
1145                                 mdi_client, 0, GetModuleHandle(0),
1146                                 (LPVOID)mdi_lParam_test_message);
1147     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1148     {
1149         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1150     }
1151     else
1152     {
1153         ok(mdi_child != 0, "MDI child creation failed\n");
1154         ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1155         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1156         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1157     }
1158
1159     /* test MDICREATESTRUCT A<->W mapping */
1160     SetLastError(0xdeadbeef);
1161     mdi_child = CreateWindowExW(WS_EX_MDICHILD, classW, titleW,
1162                                 0,
1163                                 CW_USEDEFAULT, CW_USEDEFAULT,
1164                                 CW_USEDEFAULT, CW_USEDEFAULT,
1165                                 mdi_client, 0, GetModuleHandle(0),
1166                                 (LPVOID)mdi_lParam_test_message);
1167     if (!mdi_child)
1168     {
1169         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1170             isWin9x = TRUE;
1171         else
1172             ok(mdi_child != 0, "MDI child creation failed\n");
1173     }
1174     else
1175     {
1176         ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1177         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1178         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1179     }
1180
1181     /* This test fails on Win9x */
1182     if (!isWin9x)
1183     {
1184         mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
1185                                 WS_CHILD,
1186                                 CW_USEDEFAULT, CW_USEDEFAULT,
1187                                 CW_USEDEFAULT, CW_USEDEFAULT,
1188                                 parent, 0, GetModuleHandle(0),
1189                                 (LPVOID)mdi_lParam_test_message);
1190         ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
1191     }
1192
1193     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1194                                 WS_CHILD, /* without WS_POPUP */
1195                                 CW_USEDEFAULT, CW_USEDEFAULT,
1196                                 CW_USEDEFAULT, CW_USEDEFAULT,
1197                                 mdi_client, 0, GetModuleHandle(0),
1198                                 (LPVOID)mdi_lParam_test_message);
1199     ok(mdi_child != 0, "MDI child creation failed\n");
1200     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1201     DestroyWindow(mdi_child);
1202
1203     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1204                                 WS_CHILD | WS_POPUP, /* with WS_POPUP */
1205                                 CW_USEDEFAULT, CW_USEDEFAULT,
1206                                 CW_USEDEFAULT, CW_USEDEFAULT,
1207                                 mdi_client, 0, GetModuleHandle(0),
1208                                 (LPVOID)mdi_lParam_test_message);
1209     ok(mdi_child != 0, "MDI child creation failed\n");
1210     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1211     DestroyWindow(mdi_child);
1212
1213     /* maximized child */
1214     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1215                                 WS_CHILD | WS_MAXIMIZE,
1216                                 CW_USEDEFAULT, CW_USEDEFAULT,
1217                                 CW_USEDEFAULT, CW_USEDEFAULT,
1218                                 mdi_client, 0, GetModuleHandle(0),
1219                                 (LPVOID)mdi_lParam_test_message);
1220     ok(mdi_child != 0, "MDI child creation failed\n");
1221     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1222     DestroyWindow(mdi_child);
1223
1224     trace("Creating maximized child with a caption\n");
1225     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1226                                 WS_CHILD | WS_MAXIMIZE | WS_CAPTION,
1227                                 CW_USEDEFAULT, CW_USEDEFAULT,
1228                                 CW_USEDEFAULT, CW_USEDEFAULT,
1229                                 mdi_client, 0, GetModuleHandle(0),
1230                                 (LPVOID)mdi_lParam_test_message);
1231     ok(mdi_child != 0, "MDI child creation failed\n");
1232     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1233     DestroyWindow(mdi_child);
1234
1235     trace("Creating maximized child with a caption and a thick frame\n");
1236     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1237                                 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME,
1238                                 CW_USEDEFAULT, CW_USEDEFAULT,
1239                                 CW_USEDEFAULT, CW_USEDEFAULT,
1240                                 mdi_client, 0, GetModuleHandle(0),
1241                                 (LPVOID)mdi_lParam_test_message);
1242     ok(mdi_child != 0, "MDI child creation failed\n");
1243     ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
1244     DestroyWindow(mdi_child);
1245 }
1246
1247 /**********************************************************************
1248  * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c)
1249  *
1250  * Note: The rule here is that client rect of the maximized MDI child
1251  *       is equal to the client rect of the MDI client window.
1252  */
1253 static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax )
1254 {
1255     RECT rect;
1256
1257     GetClientRect( client, &rect );
1258     AdjustWindowRectEx( &rect, GetWindowLongA( hwnd, GWL_STYLE ),
1259                         0, GetWindowLongA( hwnd, GWL_EXSTYLE ));
1260
1261     rect.right -= rect.left;
1262     rect.bottom -= rect.top;
1263     lpMinMax->ptMaxSize.x = rect.right;
1264     lpMinMax->ptMaxSize.y = rect.bottom;
1265
1266     lpMinMax->ptMaxPosition.x = rect.left;
1267     lpMinMax->ptMaxPosition.y = rect.top;
1268
1269     trace("max rect (%ld,%ld - %ld, %ld)\n",
1270            rect.left, rect.top, rect.right, rect.bottom);
1271 }
1272
1273 static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1274 {
1275     switch (msg)
1276     {
1277         case WM_NCCREATE:
1278         case WM_CREATE:
1279         {
1280             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1281             MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs->lpCreateParams;
1282
1283             ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
1284             ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
1285
1286             ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
1287             ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
1288             ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1289             ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
1290             ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
1291
1292             /* MDICREATESTRUCT should have original values */
1293             ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff,
1294                 "mdi_cs->style does not match (%08lx)\n", mdi_cs->style);
1295             ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
1296             ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
1297             ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
1298             ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
1299
1300             /* CREATESTRUCT should have fixed values */
1301             ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
1302             ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1303
1304             /* cx/cy == CW_USEDEFAULT are translated to NOT zero values */
1305             ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx);
1306             ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy);
1307
1308             ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
1309
1310             if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1311             {
1312                 LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS;
1313                 ok(cs->style == style,
1314                    "cs->style does not match (%08lx)\n", cs->style);
1315             }
1316             else
1317             {
1318                 LONG style = mdi_cs->style;
1319                 style &= ~WS_POPUP;
1320                 style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1321                     WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1322                 ok(cs->style == style,
1323                    "cs->style does not match (%08lx)\n", cs->style);
1324             }
1325             break;
1326         }
1327
1328         case WM_GETMINMAXINFO:
1329         {
1330             HWND client = GetParent(hwnd);
1331             RECT rc;
1332             MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1333             MINMAXINFO my_minmax;
1334             LONG style, exstyle;
1335
1336             style = GetWindowLongA(hwnd, GWL_STYLE);
1337             exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1338
1339             GetWindowRect(client, &rc);
1340             trace("MDI client %p window size = (%ld x %ld)\n", client, rc.right-rc.left, rc.bottom-rc.top);
1341             GetClientRect(client, &rc);
1342             trace("MDI client %p client size = (%ld x %ld)\n", client, rc.right, rc.bottom);
1343             trace("screen size: %d x %d\n", GetSystemMetrics(SM_CXSCREEN),
1344                                             GetSystemMetrics(SM_CYSCREEN));
1345
1346             GetClientRect(client, &rc);
1347             if ((style & WS_CAPTION) == WS_CAPTION)
1348                 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1349             AdjustWindowRectEx(&rc, style, 0, exstyle);
1350             trace("MDI child: calculated max window size = (%ld x %ld)\n", rc.right-rc.left, rc.bottom-rc.top);
1351
1352             trace("ptReserved = (%ld,%ld)\n"
1353                   "ptMaxSize = (%ld,%ld)\n"
1354                   "ptMaxPosition = (%ld,%ld)\n"
1355                   "ptMinTrackSize = (%ld,%ld)\n"
1356                   "ptMaxTrackSize = (%ld,%ld)\n",
1357                   minmax->ptReserved.x, minmax->ptReserved.y,
1358                   minmax->ptMaxSize.x, minmax->ptMaxSize.y,
1359                   minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
1360                   minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
1361                   minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
1362
1363             ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %ld != %ld\n",
1364                minmax->ptMaxSize.x, rc.right - rc.left);
1365             ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %ld != %ld\n",
1366                minmax->ptMaxSize.y, rc.bottom - rc.top);
1367
1368             DefMDIChildProcA(hwnd, msg, wparam, lparam);
1369
1370             trace("DefMDIChildProc returned:\n"
1371                   "ptReserved = (%ld,%ld)\n"
1372                   "ptMaxSize = (%ld,%ld)\n"
1373                   "ptMaxPosition = (%ld,%ld)\n"
1374                   "ptMinTrackSize = (%ld,%ld)\n"
1375                   "ptMaxTrackSize = (%ld,%ld)\n",
1376                   minmax->ptReserved.x, minmax->ptReserved.y,
1377                   minmax->ptMaxSize.x, minmax->ptMaxSize.y,
1378                   minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
1379                   minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
1380                   minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
1381
1382             MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax);
1383             ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %ld != %ld\n",
1384                minmax->ptMaxSize.x, my_minmax.ptMaxSize.x);
1385             ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %ld != %ld\n",
1386                minmax->ptMaxSize.y, my_minmax.ptMaxSize.y);
1387
1388             return 1;
1389         }
1390
1391         case WM_MDIACTIVATE:
1392         {
1393             HWND active, client = GetParent(hwnd);
1394             /*trace("%p WM_MDIACTIVATE %08x %08lx\n", hwnd, wparam, lparam);*/
1395             active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1396             if (hwnd == (HWND)lparam) /* if we are being activated */
1397                 ok (active == (HWND)lparam, "new active %p != active %p\n", (HWND)lparam, active);
1398             else
1399                 ok (active == (HWND)wparam, "old active %p != active %p\n", (HWND)wparam, active);
1400             break;
1401         }
1402     }
1403     return DefMDIChildProcA(hwnd, msg, wparam, lparam);
1404 }
1405
1406 static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1407 {
1408     switch (msg)
1409     {
1410         case WM_NCCREATE:
1411         case WM_CREATE:
1412         {
1413             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1414
1415             trace("%s\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE");
1416             trace("x %d, y %d, cx %d, cy %d\n", cs->x, cs->y, cs->cx, cs->cy);
1417
1418             ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
1419             ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
1420
1421             ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
1422             ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1423
1424             /* CREATESTRUCT should have fixed values */
1425             /* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT,
1426                while NT does. */
1427             /*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/
1428             ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1429
1430             /* cx/cy == CW_USEDEFAULT are translated to 0 */
1431             /* For some reason Win98 doesn't translate cs->cx from CW_USEDEFAULT,
1432                while Win95, Win2k, WinXP do. */
1433             /*ok(cs->cx == 0, "%d != 0\n", cs->cx);*/
1434             ok(cs->cy == 0, "%d != 0\n", cs->cy);
1435             break;
1436         }
1437
1438         case WM_GETMINMAXINFO:
1439         {
1440             HWND parent = GetParent(hwnd);
1441             RECT rc;
1442             MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1443             LONG style, exstyle;
1444
1445             trace("WM_GETMINMAXINFO\n");
1446
1447             style = GetWindowLongA(hwnd, GWL_STYLE);
1448             exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1449
1450             GetClientRect(parent, &rc);
1451             trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
1452
1453             GetClientRect(parent, &rc);
1454             if ((style & WS_CAPTION) == WS_CAPTION)
1455                 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1456             AdjustWindowRectEx(&rc, style, 0, exstyle);
1457             trace("calculated max child window size = (%ld x %ld)\n", rc.right-rc.left, rc.bottom-rc.top);
1458
1459             trace("ptReserved = (%ld,%ld)\n"
1460                   "ptMaxSize = (%ld,%ld)\n"
1461                   "ptMaxPosition = (%ld,%ld)\n"
1462                   "ptMinTrackSize = (%ld,%ld)\n"
1463                   "ptMaxTrackSize = (%ld,%ld)\n",
1464                   minmax->ptReserved.x, minmax->ptReserved.y,
1465                   minmax->ptMaxSize.x, minmax->ptMaxSize.y,
1466                   minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
1467                   minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
1468                   minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
1469
1470             ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %ld != %ld\n",
1471                minmax->ptMaxSize.x, rc.right - rc.left);
1472             ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %ld != %ld\n",
1473                minmax->ptMaxSize.y, rc.bottom - rc.top);
1474             break;
1475         }
1476
1477         case WM_WINDOWPOSCHANGED:
1478         {
1479             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1480             RECT rc1, rc2;
1481
1482             GetWindowRect(hwnd, &rc1);
1483             trace("window: (%ld,%ld)-(%ld,%ld)\n", rc1.left, rc1.top, rc1.right, rc1.bottom);
1484             SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1485             /* note: winpos coordinates are relative to parent */
1486             MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
1487             trace("pos: (%ld,%ld)-(%ld,%ld)\n", rc2.left, rc2.top, rc2.right, rc2.bottom);
1488             ok(EqualRect(&rc1, &rc2), "rects do not match\n");
1489
1490             GetWindowRect(hwnd, &rc1);
1491             GetClientRect(hwnd, &rc2);
1492             DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
1493             MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1494             ok(EqualRect(&rc1, &rc2), "rects do not match\n");
1495         }
1496         /* fall through */
1497         case WM_WINDOWPOSCHANGING:
1498         {
1499             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1500             WINDOWPOS my_winpos = *winpos;
1501
1502             trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1503             trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1504                   winpos->hwnd, winpos->hwndInsertAfter,
1505                   winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1506
1507             DefWindowProcA(hwnd, msg, wparam, lparam);
1508
1509             trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1510                   winpos->hwnd, winpos->hwndInsertAfter,
1511                   winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1512
1513             ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
1514                "DefWindowProc should not change WINDOWPOS values\n");
1515
1516             return 1;
1517         }
1518     }
1519     return DefWindowProcA(hwnd, msg, wparam, lparam);
1520 }
1521
1522 static LRESULT WINAPI mdi_main_wnd_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1523 {
1524     static HWND mdi_client;
1525
1526     switch (msg)
1527     {
1528         case WM_CREATE:
1529         {
1530             CLIENTCREATESTRUCT client_cs;
1531             RECT rc;
1532
1533             GetClientRect(hwnd, &rc);
1534
1535             client_cs.hWindowMenu = 0;
1536             client_cs.idFirstChild = 1;
1537
1538             /* MDIClient without MDIS_ALLCHILDSTYLES */
1539             mdi_client = CreateWindowExA(0, "mdiclient",
1540                                          NULL,
1541                                          WS_CHILD /*| WS_VISIBLE*/,
1542                                           /* tests depend on a not zero MDIClient size */
1543                                          0, 0, rc.right, rc.bottom,
1544                                          hwnd, 0, GetModuleHandle(0),
1545                                          (LPVOID)&client_cs);
1546             assert(mdi_client);
1547             test_MDI_create(hwnd, mdi_client, client_cs.idFirstChild);
1548             DestroyWindow(mdi_client);
1549
1550             /* MDIClient with MDIS_ALLCHILDSTYLES */
1551             mdi_client = CreateWindowExA(0, "mdiclient",
1552                                          NULL,
1553                                          WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
1554                                           /* tests depend on a not zero MDIClient size */
1555                                          0, 0, rc.right, rc.bottom,
1556                                          hwnd, 0, GetModuleHandle(0),
1557                                          (LPVOID)&client_cs);
1558             assert(mdi_client);
1559             test_MDI_create(hwnd, mdi_client, client_cs.idFirstChild);
1560             DestroyWindow(mdi_client);
1561             break;
1562         }
1563
1564         case WM_WINDOWPOSCHANGED:
1565         {
1566             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1567             RECT rc1, rc2;
1568
1569             GetWindowRect(hwnd, &rc1);
1570             trace("window: (%ld,%ld)-(%ld,%ld)\n", rc1.left, rc1.top, rc1.right, rc1.bottom);
1571             SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1572             /* note: winpos coordinates are relative to parent */
1573             MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
1574             trace("pos: (%ld,%ld)-(%ld,%ld)\n", rc2.left, rc2.top, rc2.right, rc2.bottom);
1575             ok(EqualRect(&rc1, &rc2), "rects do not match\n");
1576
1577             GetWindowRect(hwnd, &rc1);
1578             GetClientRect(hwnd, &rc2);
1579             DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
1580             MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1581             ok(EqualRect(&rc1, &rc2), "rects do not match\n");
1582         }
1583         /* fall through */
1584         case WM_WINDOWPOSCHANGING:
1585         {
1586             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1587             WINDOWPOS my_winpos = *winpos;
1588
1589             trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1590             trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1591                   winpos->hwnd, winpos->hwndInsertAfter,
1592                   winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1593
1594             DefWindowProcA(hwnd, msg, wparam, lparam);
1595
1596             trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1597                   winpos->hwnd, winpos->hwndInsertAfter,
1598                   winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1599
1600             ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
1601                "DefWindowProc should not change WINDOWPOS values\n");
1602
1603             return 1;
1604         }
1605
1606         case WM_CLOSE:
1607             PostQuitMessage(0);
1608             break;
1609     }
1610     return DefFrameProcA(hwnd, mdi_client, msg, wparam, lparam);
1611 }
1612
1613 static BOOL mdi_RegisterWindowClasses(void)
1614 {
1615     WNDCLASSA cls;
1616
1617     cls.style = 0;
1618     cls.lpfnWndProc = mdi_main_wnd_procA;
1619     cls.cbClsExtra = 0;
1620     cls.cbWndExtra = 0;
1621     cls.hInstance = GetModuleHandleA(0);
1622     cls.hIcon = 0;
1623     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1624     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1625     cls.lpszMenuName = NULL;
1626     cls.lpszClassName = "MDI_parent_Class";
1627     if(!RegisterClassA(&cls)) return FALSE;
1628
1629     cls.lpfnWndProc = mdi_child_wnd_proc_1;
1630     cls.lpszClassName = "MDI_child_Class_1";
1631     if(!RegisterClassA(&cls)) return FALSE;
1632
1633     cls.lpfnWndProc = mdi_child_wnd_proc_2;
1634     cls.lpszClassName = "MDI_child_Class_2";
1635     if(!RegisterClassA(&cls)) return FALSE;
1636
1637     return TRUE;
1638 }
1639
1640 static void test_mdi(void)
1641 {
1642     HWND mdi_hwndMain;
1643     /*MSG msg;*/
1644
1645     if (!mdi_RegisterWindowClasses()) assert(0);
1646
1647     mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window",
1648                                    WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1649                                    WS_MAXIMIZEBOX /*| WS_VISIBLE*/,
1650                                    100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1651                                    GetDesktopWindow(), 0,
1652                                    GetModuleHandle(0), NULL);
1653     assert(mdi_hwndMain);
1654 /*
1655     while(GetMessage(&msg, 0, 0, 0))
1656     {
1657         TranslateMessage(&msg);
1658         DispatchMessage(&msg);
1659     }
1660 */
1661 }
1662
1663 static void test_icons(void)
1664 {
1665     WNDCLASSEXA cls;
1666     HWND hwnd;
1667     HICON icon = LoadIconA(0, (LPSTR)IDI_APPLICATION);
1668     HICON icon2 = LoadIconA(0, (LPSTR)IDI_QUESTION);
1669     HICON small_icon = LoadImageA(0, (LPSTR)IDI_APPLICATION, IMAGE_ICON,
1670                                   GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
1671     HICON res;
1672
1673     cls.cbSize = sizeof(cls);
1674     cls.style = 0;
1675     cls.lpfnWndProc = DefWindowProcA;
1676     cls.cbClsExtra = 0;
1677     cls.cbWndExtra = 0;
1678     cls.hInstance = 0;
1679     cls.hIcon = LoadIconA(0, (LPSTR)IDI_HAND);
1680     cls.hIconSm = small_icon;
1681     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1682     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1683     cls.lpszMenuName = NULL;
1684     cls.lpszClassName = "IconWindowClass";
1685
1686     RegisterClassExA(&cls);
1687
1688     hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
1689                            100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
1690     assert( hwnd );
1691
1692     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1693     ok( res == 0, "wrong big icon %p/0\n", res );
1694     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
1695     ok( res == 0, "wrong previous big icon %p/0\n", res );
1696     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1697     ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
1698     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
1699     ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
1700     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1701     ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
1702
1703     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
1704     ok( res == 0, "wrong small icon %p/0\n", res );
1705     /* this test is XP specific */
1706     /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
1707     ok( res != 0, "wrong small icon %p\n", res );*/
1708     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
1709     ok( res == 0, "wrong previous small icon %p/0\n", res );
1710     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
1711     ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
1712     /* this test is XP specific */
1713     /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
1714     ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );*/
1715     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
1716     ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
1717     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
1718     ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
1719     /* this test is XP specific */
1720     /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
1721     ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );*/
1722
1723     /* make sure the big icon hasn't changed */
1724     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1725     ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
1726 }
1727
1728 static LRESULT WINAPI nccalcsize_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1729 {
1730     if (msg == WM_NCCALCSIZE)
1731     {
1732         RECT *rect = (RECT *)lparam;
1733         /* first time around increase the rectangle, next time decrease it */
1734         if (rect->left == 100) InflateRect( rect, 10, 10 );
1735         else InflateRect( rect, -10, -10 );
1736         return 0;
1737     }
1738     return DefWindowProc( hwnd, msg, wparam, lparam );
1739 }
1740
1741 static void test_SetWindowPos(HWND hwnd)
1742 {
1743     RECT orig_win_rc, rect;
1744     LONG_PTR old_proc;
1745     BOOL is_win9x = GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == 0;
1746
1747     SetRect(&rect, 111, 222, 333, 444);
1748     ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n");
1749     ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
1750        "wrong window rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
1751
1752     SetRect(&rect, 111, 222, 333, 444);
1753     ok(!GetClientRect(0, &rect), "GetClientRect succeeded\n");
1754     ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
1755        "wrong window rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
1756
1757     GetWindowRect(hwnd, &orig_win_rc);
1758
1759     old_proc = SetWindowLongPtr( hwnd, GWLP_WNDPROC, (ULONG_PTR)nccalcsize_proc );
1760     SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
1761     GetWindowRect( hwnd, &rect );
1762     ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100,
1763         "invalid window rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
1764     GetClientRect( hwnd, &rect );
1765     MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
1766     ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110,
1767         "invalid client rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
1768
1769     SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
1770     GetWindowRect( hwnd, &rect );
1771     ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200,
1772         "invalid window rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
1773     GetClientRect( hwnd, &rect );
1774     MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
1775     ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190,
1776         "invalid client rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
1777
1778     SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
1779                  orig_win_rc.right, orig_win_rc.bottom, 0);
1780     SetWindowLongPtr( hwnd, GWLP_WNDPROC, old_proc );
1781
1782     /* Win9x truncates coordinates to 16-bit irrespectively */
1783     if (!is_win9x)
1784     {
1785         SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
1786         SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
1787
1788         SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
1789         SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
1790     }
1791
1792     SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
1793                  orig_win_rc.right, orig_win_rc.bottom, 0);
1794 }
1795
1796 static void test_SetMenu(HWND parent)
1797 {
1798     HWND child;
1799     HMENU hMenu, ret;
1800     BOOL is_win9x = GetWindowLongPtrW(parent, GWLP_WNDPROC) == 0;
1801     BOOL retok;
1802     DWORD style;
1803
1804     hMenu = CreateMenu();
1805     assert(hMenu);
1806
1807     ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
1808 #if 0
1809     /* fails on (at least) Wine, NT4, XP SP2 */
1810     test_nonclient_area(parent); 
1811 #endif
1812     ret = GetMenu(parent);
1813     ok(ret == hMenu, "unexpected menu id %p\n", ret);
1814     /* test whether we can destroy a menu assigned to a window */
1815     retok = DestroyMenu(hMenu);
1816     ok( retok, "DestroyMenu error %ld\n", GetLastError());
1817     ok(!IsMenu(hMenu), "menu handle should be not valid after DestroyMenu\n");
1818     ret = GetMenu(parent);
1819     /* This test fails on Win9x */
1820     if (!is_win9x)
1821         ok(ret == hMenu, "unexpected menu id %p\n", ret);
1822     ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
1823     test_nonclient_area(parent);
1824
1825     hMenu = CreateMenu();
1826     assert(hMenu);
1827
1828     /* parent */
1829     ret = GetMenu(parent);
1830     ok(ret == 0, "unexpected menu id %p\n", ret);
1831
1832     ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
1833     test_nonclient_area(parent);
1834     ret = GetMenu(parent);
1835     ok(ret == 0, "unexpected menu id %p\n", ret);
1836
1837     ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
1838 #if 0
1839     /* fails on (at least) Wine, NT4, XP SP2 */
1840     test_nonclient_area(parent);
1841 #endif
1842     ret = GetMenu(parent);
1843     ok(ret == hMenu, "unexpected menu id %p\n", ret);
1844
1845     ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
1846     test_nonclient_area(parent);
1847     ret = GetMenu(parent);
1848     ok(ret == 0, "unexpected menu id %p\n", ret);
1849  
1850     /* child */
1851     child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL);
1852     assert(child);
1853
1854     ret = GetMenu(child);
1855     ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
1856
1857     ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
1858     test_nonclient_area(child);
1859     ret = GetMenu(child);
1860     ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
1861
1862     ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n");
1863     test_nonclient_area(child);
1864     ret = GetMenu(child);
1865     ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
1866
1867     ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n");
1868     test_nonclient_area(child);
1869     ret = GetMenu(child);
1870     ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
1871
1872     style = GetWindowLong(child, GWL_STYLE);
1873     SetWindowLong(child, GWL_STYLE, style | WS_POPUP);
1874     ok(SetMenu(child, hMenu), "SetMenu on a popup child window should not fail\n");
1875     ok(SetMenu(child, 0), "SetMenu on a popup child window should not fail\n");
1876     SetWindowLong(child, GWL_STYLE, style);
1877
1878     SetWindowLong(child, GWL_STYLE, style | WS_OVERLAPPED);
1879     ok(!SetMenu(child, hMenu), "SetMenu on a overlapped child window should fail\n");
1880     SetWindowLong(child, GWL_STYLE, style);
1881
1882     DestroyWindow(child);
1883     DestroyMenu(hMenu);
1884 }
1885
1886 static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total)
1887 {
1888     HWND child[5], hwnd;
1889     int i;
1890
1891     assert(total <= 5);
1892
1893     hwnd = GetWindow(parent, GW_CHILD);
1894     ok(!hwnd, "have to start without children to perform the test\n");
1895
1896     for (i = 0; i < total; i++)
1897     {
1898         if (style[i] & DS_CONTROL)
1899         {
1900             child[i] = CreateWindowExA(0, MAKEINTATOMA(32770), "", style[i] & ~WS_VISIBLE,
1901                                        0,0,0,0, parent, (HMENU)i, 0, NULL);
1902             if (style[i] & WS_VISIBLE)
1903                 ShowWindow(child[i], SW_SHOW);
1904
1905             SetWindowPos(child[i], HWND_BOTTOM, 0,0,10,10, SWP_NOACTIVATE);
1906         }
1907         else
1908             child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
1909                                        parent, (HMENU)i, 0, NULL);
1910         trace("child[%d] = %p\n", i, child[i]);
1911         ok(child[i] != 0, "CreateWindowEx failed to create child window\n");
1912     }
1913
1914     hwnd = GetWindow(parent, GW_CHILD);
1915     ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n");
1916     ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n");
1917     ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n");
1918
1919     for (i = 0; i < total; i++)
1920     {
1921         trace("hwnd[%d] = %p\n", i, hwnd);
1922         ok(child[order[i]] == hwnd, "Z order of child #%d is wrong\n", i);
1923
1924         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
1925     }
1926
1927     for (i = 0; i < total; i++)
1928         ok(DestroyWindow(child[i]), "DestroyWindow failed\n");
1929 }
1930
1931 static void test_children_zorder(HWND parent)
1932 {
1933     const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD,
1934                                     WS_CHILD };
1935     const int simple_order[5] = { 0, 1, 2, 3, 4 };
1936
1937     const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE,
1938                              WS_CHILD | WS_VISIBLE, WS_CHILD,
1939                              WS_CHILD | WS_MAXIMIZE | WS_VISIBLE };
1940     const int complex_order_1[1] = { 0 };
1941     const int complex_order_2[2] = { 1, 0 };
1942     const int complex_order_3[3] = { 1, 0, 2 };
1943     const int complex_order_4[4] = { 1, 0, 2, 3 };
1944     const int complex_order_5[5] = { 4, 1, 0, 2, 3 };
1945     const DWORD complex_style_6[3] = { WS_CHILD | WS_VISIBLE,
1946                                        WS_CHILD | WS_CLIPSIBLINGS | DS_CONTROL | WS_VISIBLE,
1947                                        WS_CHILD | WS_VISIBLE };
1948     const int complex_order_6[3] = { 0, 1, 2 };
1949
1950     /* simple WS_CHILD */
1951     test_window_tree(parent, simple_style, simple_order, 5);
1952
1953     /* complex children styles */
1954     test_window_tree(parent, complex_style, complex_order_1, 1);
1955     test_window_tree(parent, complex_style, complex_order_2, 2);
1956     test_window_tree(parent, complex_style, complex_order_3, 3);
1957     test_window_tree(parent, complex_style, complex_order_4, 4);
1958     test_window_tree(parent, complex_style, complex_order_5, 5);
1959
1960     /* another set of complex children styles */
1961     test_window_tree(parent, complex_style_6, complex_order_6, 3);
1962 }
1963
1964 static void test_vis_rgn( HWND hwnd )
1965 {
1966     RECT win_rect, rgn_rect;
1967     HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
1968     HDC hdc;
1969
1970     ShowWindow(hwnd,SW_SHOW);
1971     hdc = GetDC( hwnd );
1972     ok( GetRandomRgn( hdc, hrgn, SYSRGN ) != 0, "GetRandomRgn failed\n" );
1973     GetWindowRect( hwnd, &win_rect );
1974     GetRgnBox( hrgn, &rgn_rect );
1975     if (GetVersion() & 0x80000000)
1976     {
1977         trace("win9x, mapping to screen coords\n");
1978         MapWindowPoints( hwnd, 0, (POINT *)&rgn_rect, 2 );
1979     }
1980     trace("win: %ld,%ld-%ld,%ld\n", win_rect.left, win_rect.top, win_rect.right, win_rect.bottom );
1981     trace("rgn: %ld,%ld-%ld,%ld\n", rgn_rect.left, rgn_rect.top, rgn_rect.right, rgn_rect.bottom );
1982     ok( win_rect.left <= rgn_rect.left, "rgn left %ld not inside win rect %ld\n",
1983         rgn_rect.left, win_rect.left );
1984     ok( win_rect.top <= rgn_rect.top, "rgn top %ld not inside win rect %ld\n",
1985         rgn_rect.top, win_rect.top );
1986     ok( win_rect.right >= rgn_rect.right, "rgn right %ld not inside win rect %ld\n",
1987         rgn_rect.right, win_rect.right );
1988     ok( win_rect.bottom >= rgn_rect.bottom, "rgn bottom %ld not inside win rect %ld\n",
1989         rgn_rect.bottom, win_rect.bottom );
1990     ReleaseDC( hwnd, hdc );
1991 }
1992
1993 static void test_SetFocus(HWND hwnd)
1994 {
1995     HWND child;
1996
1997     /* check if we can set focus to non-visible windows */
1998
1999     ShowWindow(hwnd, SW_SHOW);
2000     SetFocus(0);
2001     SetFocus(hwnd);
2002     ok( GetFocus() == hwnd, "Failed to set focus to visible window %p\n", hwnd );
2003     ok( GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE, "Window %p not visible\n", hwnd );
2004     ShowWindow(hwnd, SW_HIDE);
2005     SetFocus(0);
2006     SetFocus(hwnd);
2007     ok( GetFocus() == hwnd, "Failed to set focus to invisible window %p\n", hwnd );
2008     ok( !(GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p still visible\n", hwnd );
2009     child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2010     assert(child);
2011     SetFocus(child);
2012     ok( GetFocus() == child, "Failed to set focus to invisible child %p\n", child );
2013     ok( !(GetWindowLong(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2014     ShowWindow(child, SW_SHOW);
2015     ok( GetWindowLong(child,GWL_STYLE) & WS_VISIBLE, "Child %p is not visible\n", child );
2016     ok( GetFocus() == child, "Focus no longer on child %p\n", child );
2017     ShowWindow(child, SW_HIDE);
2018     ok( !(GetWindowLong(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2019     ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
2020     ShowWindow(child, SW_SHOW);
2021     SetFocus(child);
2022     ok( GetFocus() == child, "Focus should be on child %p\n", child );
2023     SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW);
2024     ok( GetFocus() == child, "Focus should still be on child %p\n", child );
2025
2026     ShowWindow(child, SW_HIDE);
2027     SetFocus(hwnd);
2028     ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
2029     SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
2030     ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
2031     ShowWindow(child, SW_HIDE);
2032     ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
2033
2034     ShowWindow(hwnd, SW_SHOW);
2035     ShowWindow(child, SW_SHOW);
2036     SetFocus(child);
2037     ok( GetFocus() == child, "Focus should be on child %p\n", child );
2038     EnableWindow(hwnd, FALSE);
2039     ok( GetFocus() == child, "Focus should still be on child %p\n", child );
2040     EnableWindow(hwnd, TRUE);
2041
2042     DestroyWindow( child );
2043 }
2044
2045 static void test_SetActiveWindow(HWND hwnd)
2046 {
2047     HWND hwnd2;
2048
2049     ShowWindow(hwnd, SW_SHOW);
2050     SetActiveWindow(0);
2051     SetActiveWindow(hwnd);
2052     ok( GetActiveWindow() == hwnd, "Failed to set focus to visible window %p\n", hwnd );
2053     SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
2054     ok( GetActiveWindow() == hwnd, "Window %p no longer active\n", hwnd );
2055     SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
2056     ShowWindow(hwnd, SW_HIDE);
2057     ok( GetActiveWindow() != hwnd, "Window %p is still active\n", hwnd );
2058
2059     /* trace("**testing an invisible window now\n"); */
2060     SetActiveWindow(hwnd);
2061     ok( GetActiveWindow() == hwnd, "Window %p not active\n", hwnd );
2062     ok( !(GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p is visible\n", hwnd );
2063     
2064     ShowWindow(hwnd, SW_SHOW);
2065
2066     hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2067     ok( GetActiveWindow() == hwnd2, "Window %p is not active\n", hwnd2 );
2068     DestroyWindow(hwnd2);
2069     ok( GetActiveWindow() != hwnd2, "Window %p is still active\n", hwnd2 );
2070
2071     hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2072     ok( GetActiveWindow() == hwnd2, "Window %p is not active\n", hwnd2 );
2073     SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
2074     ok( GetActiveWindow() == hwnd2, "Window %p no longer active (%p)\n", hwnd2, GetActiveWindow() );
2075     DestroyWindow(hwnd2);
2076     ok( GetActiveWindow() != hwnd2, "Window %p is still active\n", hwnd2 );
2077 }
2078
2079 static void check_wnd_state(HWND active, HWND foreground, HWND focus, HWND capture)
2080 {
2081     ok(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
2082     if (foreground)
2083         ok(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
2084     ok(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
2085     ok(capture == GetCapture(), "GetCapture() = %p\n", GetCapture());
2086 }
2087
2088 static WNDPROC old_button_proc;
2089
2090 static LRESULT WINAPI button_hook_proc(HWND button, UINT msg, WPARAM wparam, LPARAM lparam)
2091 {
2092     LRESULT ret;
2093     USHORT key_state;
2094
2095     key_state = GetKeyState(VK_LBUTTON);
2096     ok(!(key_state & 0x8000), "VK_LBUTTON should not be pressed, state %04x\n", key_state);
2097
2098     ret = CallWindowProcA(old_button_proc, button, msg, wparam, lparam);
2099
2100     if (msg == WM_LBUTTONDOWN)
2101     {
2102         HWND hwnd, capture;
2103
2104         check_wnd_state(button, button, button, button);
2105
2106         hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
2107         assert(hwnd);
2108         trace("hwnd %p\n", hwnd);
2109
2110         check_wnd_state(button, button, button, button);
2111
2112         ShowWindow(hwnd, SW_SHOWNOACTIVATE);
2113
2114         check_wnd_state(button, button, button, button);
2115
2116         DestroyWindow(hwnd);
2117
2118         hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
2119         assert(hwnd);
2120         trace("hwnd %p\n", hwnd);
2121
2122         check_wnd_state(button, button, button, button);
2123
2124         /* button wnd proc should release capture on WM_KILLFOCUS if it does
2125          * match internal button state.
2126          */
2127         SendMessage(button, WM_KILLFOCUS, 0, 0);
2128         check_wnd_state(button, button, button, 0);
2129
2130         ShowWindow(hwnd, SW_SHOW);
2131         check_wnd_state(hwnd, hwnd, hwnd, 0);
2132
2133         capture = SetCapture(hwnd);
2134         ok(capture == 0, "SetCapture() = %p\n", capture);
2135
2136         check_wnd_state(hwnd, hwnd, hwnd, hwnd);
2137
2138         DestroyWindow(hwnd);
2139
2140         check_wnd_state(button, 0, button, 0);
2141     }
2142
2143     return ret;
2144 }
2145
2146 static void test_capture_1(void)
2147 {
2148     HWND button, capture;
2149
2150     capture = GetCapture();
2151     ok(capture == 0, "GetCapture() = %p\n", capture);
2152
2153     button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL);
2154     assert(button);
2155     trace("button %p\n", button);
2156
2157     old_button_proc = (WNDPROC)SetWindowLongPtrA(button, GWLP_WNDPROC, (LONG_PTR)button_hook_proc);
2158
2159     SendMessageA(button, WM_LBUTTONDOWN, 0, 0);
2160
2161     capture = SetCapture(button);
2162     ok(capture == 0, "SetCapture() = %p\n", capture);
2163     check_wnd_state(button, 0, button, button);
2164
2165     DestroyWindow(button);
2166     check_wnd_state(0, 0, 0, 0);
2167 }
2168
2169 static void test_capture_2(void)
2170 {
2171     HWND button, hwnd, capture;
2172
2173     check_wnd_state(0, 0, 0, 0);
2174
2175     button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL);
2176     assert(button);
2177     trace("button %p\n", button);
2178
2179     check_wnd_state(button, button, button, 0);
2180
2181     capture = SetCapture(button);
2182     ok(capture == 0, "SetCapture() = %p\n", capture);
2183
2184     check_wnd_state(button, button, button, button);
2185
2186     /* button wnd proc should ignore WM_KILLFOCUS if it doesn't match
2187      * internal button state.
2188      */
2189     SendMessage(button, WM_KILLFOCUS, 0, 0);
2190     check_wnd_state(button, button, button, button);
2191
2192     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
2193     assert(hwnd);
2194     trace("hwnd %p\n", hwnd);
2195
2196     check_wnd_state(button, button, button, button);
2197
2198     ShowWindow(hwnd, SW_SHOWNOACTIVATE);
2199
2200     check_wnd_state(button, button, button, button);
2201
2202     DestroyWindow(hwnd);
2203
2204     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
2205     assert(hwnd);
2206     trace("hwnd %p\n", hwnd);
2207
2208     check_wnd_state(button, button, button, button);
2209
2210     ShowWindow(hwnd, SW_SHOW);
2211
2212     check_wnd_state(hwnd, hwnd, hwnd, button);
2213
2214     capture = SetCapture(hwnd);
2215     ok(capture == button, "SetCapture() = %p\n", capture);
2216
2217     check_wnd_state(hwnd, hwnd, hwnd, hwnd);
2218
2219     DestroyWindow(hwnd);
2220     check_wnd_state(button, button, button, 0);
2221
2222     DestroyWindow(button);
2223     check_wnd_state(0, 0, 0, 0);
2224 }
2225
2226 static void test_capture_3(HWND hwnd1, HWND hwnd2)
2227 {
2228     BOOL ret;
2229
2230     ShowWindow(hwnd1, SW_HIDE);
2231     ShowWindow(hwnd2, SW_HIDE);
2232
2233     ok(!IsWindowVisible(hwnd1), "%p should be invisible\n", hwnd1);
2234     ok(!IsWindowVisible(hwnd2), "%p should be invisible\n", hwnd2);
2235
2236     SetCapture(hwnd1);
2237     check_wnd_state(0, 0, 0, hwnd1);
2238
2239     SetCapture(hwnd2);
2240     check_wnd_state(0, 0, 0, hwnd2);
2241
2242     ShowWindow(hwnd1, SW_SHOW);
2243     check_wnd_state(hwnd1, hwnd1, hwnd1, hwnd2);
2244
2245     ret = ReleaseCapture();
2246     ok (ret, "releasecapture did not return TRUE.\n");
2247     ret = ReleaseCapture();
2248     ok (ret, "releasecapture did not return TRUE after second try.\n");
2249 }
2250
2251 static void test_keyboard_input(HWND hwnd)
2252 {
2253     MSG msg;
2254     BOOL ret;
2255
2256     ShowWindow(hwnd, SW_SHOW);
2257     UpdateWindow(hwnd);
2258
2259     ok(GetActiveWindow() == hwnd, "wrong active window %p\n", GetActiveWindow());
2260
2261     SetFocus(hwnd);
2262     ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
2263
2264     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2265
2266     PostMessageA(hwnd, WM_KEYDOWN, 0, 0);
2267     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2268     ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2269     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
2270     ok( !ret, "message %04x available\n", msg.message);
2271
2272     ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
2273
2274     PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0);
2275     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2276     ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2277     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
2278     ok( !ret, "message %04x available\n", msg.message);
2279
2280     ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
2281
2282     keybd_event(VK_SPACE, 0, 0, 0);
2283     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2284     ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2285     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
2286     ok( !ret, "message %04x available\n", msg.message);
2287
2288     SetFocus(0);
2289     ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2290
2291     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2292
2293     PostMessageA(hwnd, WM_KEYDOWN, 0, 0);
2294     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2295     ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2296     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
2297     ok( !ret, "message %04x available\n", msg.message);
2298
2299     ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2300
2301     PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0);
2302     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2303     ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2304     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
2305     ok( !ret, "message %04x available\n", msg.message);
2306
2307     ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2308
2309     keybd_event(VK_SPACE, 0, 0, 0);
2310     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2311     ok(msg.hwnd == hwnd && msg.message == WM_SYSKEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2312     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
2313     ok( !ret, "message %04x available\n", msg.message);
2314 }
2315
2316 static void test_mouse_input(HWND hwnd)
2317 {
2318     RECT rc;
2319     POINT pt;
2320     int x, y;
2321     HWND popup;
2322     MSG msg;
2323     BOOL ret;
2324     LRESULT res;
2325
2326     ShowWindow(hwnd, SW_SHOW);
2327     UpdateWindow(hwnd);
2328
2329     GetWindowRect(hwnd, &rc);
2330     trace("main window %p: (%ld,%ld)-(%ld,%ld)\n", hwnd, rc.left, rc.top, rc.right, rc.bottom);
2331
2332     popup = CreateWindowExA(0, "MainWindowClass", NULL, WS_POPUP,
2333                             rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
2334                             hwnd, 0, 0, NULL);
2335     assert(popup != 0);
2336     ShowWindow(popup, SW_SHOW);
2337     UpdateWindow(popup);
2338
2339     GetWindowRect(popup, &rc);
2340     trace("popup window %p: (%ld,%ld)-(%ld,%ld)\n", popup, rc.left, rc.top, rc.right, rc.bottom);
2341
2342     x = rc.left + (rc.right - rc.left) / 2;
2343     y = rc.top + (rc.bottom - rc.top) / 2;
2344     trace("setting cursor to (%d,%d)\n", x, y);
2345
2346     SetCursorPos(x, y);
2347     GetCursorPos(&pt);
2348     ok(x == pt.x && y == pt.y, "wrong cursor pos (%ld,%ld), expected (%d,%d)\n", pt.x, pt.y, x, y);
2349
2350     /* force the system to update its internal queue mouse position,
2351      * otherwise it won't generate relative mouse movements below.
2352      */
2353     mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
2354     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2355
2356     msg.message = 0;
2357     mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
2358     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2359     ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2360     /* FIXME: SetCursorPos in Wine generates additional WM_MOUSEMOVE message */
2361     if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2362         ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2363     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
2364     ok( !ret, "message %04x available\n", msg.message);
2365
2366     mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
2367     ShowWindow(popup, SW_HIDE);
2368     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2369     ok(msg.hwnd == hwnd && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2370     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2371
2372     mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
2373     ShowWindow(hwnd, SW_HIDE);
2374     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
2375     ok( !ret, "message %04x available\n", msg.message);
2376
2377     /* test mouse clicks */
2378
2379     ShowWindow(hwnd, SW_SHOW);
2380     ShowWindow(popup, SW_SHOW);
2381
2382     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2383
2384     mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
2385     mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
2386     mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
2387     mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
2388
2389     ok(PeekMessageA(&msg, 0, 0, 0, 0), "no message available\n");
2390     ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2391     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2392     ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2393
2394     ok(PeekMessageA(&msg, 0, 0, 0, 0), "no message available\n");
2395     ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2396     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2397     ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2398
2399     ok(PeekMessageA(&msg, 0, 0, 0, 0), "no message available\n");
2400     ok(msg.hwnd == popup && msg.message == WM_LBUTTONDBLCLK, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2401     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2402     ok(msg.hwnd == popup && msg.message == WM_LBUTTONDBLCLK, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2403
2404     ok(PeekMessageA(&msg, 0, 0, 0, 0), "no message available\n");
2405     ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2406     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2407     ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2408
2409     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
2410     ok(!ret, "message %04x available\n", msg.message);
2411
2412     ShowWindow(popup, SW_HIDE);
2413     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2414
2415     mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
2416     mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
2417     mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
2418     mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
2419
2420     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2421     ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2422     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2423     ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONUP, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2424
2425     test_lbuttondown_flag = TRUE;
2426     SendMessageA(hwnd, WM_COMMAND, (WPARAM)popup, 0);
2427     test_lbuttondown_flag = FALSE;
2428
2429     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2430     ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2431     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2432     ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p message %04x\n", msg.hwnd, msg.message);
2433     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
2434
2435     /* Test WM_MOUSEACTIVATE */
2436 #define TEST_MOUSEACTIVATE(A,B)                                                          \
2437        res = SendMessageA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,0));   \
2438        ok(res == B, "WM_MOUSEACTIVATE for %s returned %ld\n", #A, res);
2439        
2440     TEST_MOUSEACTIVATE(HTERROR,MA_ACTIVATE);
2441     TEST_MOUSEACTIVATE(HTTRANSPARENT,MA_ACTIVATE);
2442     TEST_MOUSEACTIVATE(HTNOWHERE,MA_ACTIVATE);
2443     TEST_MOUSEACTIVATE(HTCLIENT,MA_ACTIVATE);
2444     TEST_MOUSEACTIVATE(HTCAPTION,MA_ACTIVATE);
2445     TEST_MOUSEACTIVATE(HTSYSMENU,MA_ACTIVATE);
2446     TEST_MOUSEACTIVATE(HTSIZE,MA_ACTIVATE);
2447     TEST_MOUSEACTIVATE(HTMENU,MA_ACTIVATE);
2448     TEST_MOUSEACTIVATE(HTHSCROLL,MA_ACTIVATE);
2449     TEST_MOUSEACTIVATE(HTVSCROLL,MA_ACTIVATE);
2450     TEST_MOUSEACTIVATE(HTMINBUTTON,MA_ACTIVATE);
2451     TEST_MOUSEACTIVATE(HTMAXBUTTON,MA_ACTIVATE);
2452     TEST_MOUSEACTIVATE(HTLEFT,MA_ACTIVATE);
2453     TEST_MOUSEACTIVATE(HTRIGHT,MA_ACTIVATE);
2454     TEST_MOUSEACTIVATE(HTTOP,MA_ACTIVATE);
2455     TEST_MOUSEACTIVATE(HTTOPLEFT,MA_ACTIVATE);
2456     TEST_MOUSEACTIVATE(HTTOPRIGHT,MA_ACTIVATE);
2457     TEST_MOUSEACTIVATE(HTBOTTOM,MA_ACTIVATE);
2458     TEST_MOUSEACTIVATE(HTBOTTOMLEFT,MA_ACTIVATE);
2459     TEST_MOUSEACTIVATE(HTBOTTOMRIGHT,MA_ACTIVATE);
2460     TEST_MOUSEACTIVATE(HTBORDER,MA_ACTIVATE);
2461     TEST_MOUSEACTIVATE(HTOBJECT,MA_ACTIVATE);
2462     TEST_MOUSEACTIVATE(HTCLOSE,MA_ACTIVATE);
2463     TEST_MOUSEACTIVATE(HTHELP,MA_ACTIVATE);
2464
2465     /* Clear any messages left behind by WM_MOUSEACTIVATE tests */
2466     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2467
2468     DestroyWindow(popup);
2469 }
2470
2471 static void test_validatergn(HWND hwnd)
2472 {
2473     HWND child;
2474     RECT rc, rc2;
2475     HRGN rgn;
2476     int ret;
2477     child = CreateWindowExA(0, "static", NULL, WS_CHILD| WS_VISIBLE, 10, 10, 10, 10, hwnd, 0, 0, NULL);
2478     ShowWindow(hwnd, SW_SHOW);
2479     UpdateWindow( hwnd);
2480     /* test that ValidateRect validates children*/
2481     InvalidateRect( child, NULL, 1);
2482     GetWindowRect( child, &rc);
2483     MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2);
2484     ret = GetUpdateRect( child, &rc2, 0);
2485     ok( rc2.right > rc2.left && rc2.bottom > rc2.top,
2486             "Update rectangle is empty!\n");
2487     ValidateRect( hwnd, &rc);
2488     ret = GetUpdateRect( child, &rc2, 0);
2489     ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0,
2490             "Update rectangle %ld,%ld-%ld,%ld is not empty!\n", rc2.left, rc2.top,
2491             rc2.right, rc2.bottom);
2492
2493     /* now test ValidateRgn */
2494     InvalidateRect( child, NULL, 1);
2495     GetWindowRect( child, &rc);
2496     MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2);
2497     rgn = CreateRectRgnIndirect( &rc);
2498     ValidateRgn( hwnd, rgn);
2499     ret = GetUpdateRect( child, &rc2, 0);
2500     ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0,
2501             "Update rectangle %ld,%ld-%ld,%ld is not empty!\n", rc2.left, rc2.top,
2502             rc2.right, rc2.bottom);
2503
2504     DeleteObject( rgn);
2505     DestroyWindow( child );
2506 }
2507
2508 static void nccalchelper(HWND hwnd, INT x, INT y, RECT *prc)
2509 {
2510     MoveWindow( hwnd, 0, 0, x, y, 0);
2511     GetWindowRect( hwnd, prc);
2512     trace("window rect is %ld,%ld - %ld,%ld\n", 
2513             prc->left,prc->top,prc->right,prc->bottom);
2514     DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)prc);
2515     trace("nccalc rect is %ld,%ld - %ld,%ld\n",
2516             prc->left,prc->top,prc->right,prc->bottom);
2517 }
2518
2519 static void test_nccalcscroll(HWND parent)
2520 {
2521     RECT rc1;
2522     INT sbheight = GetSystemMetrics( SM_CYHSCROLL);
2523     INT sbwidth = GetSystemMetrics( SM_CXVSCROLL);
2524     HWND hwnd = CreateWindowExA(0, "static", NULL, 
2525             WS_CHILD| WS_VISIBLE | WS_VSCROLL | WS_HSCROLL , 
2526             10, 10, 200, 200, parent, 0, 0, NULL); 
2527     ShowWindow( parent, SW_SHOW);
2528     UpdateWindow( parent);
2529
2530     /* test window too low for a horizontal scroll bar */
2531     nccalchelper( hwnd, 100, sbheight, &rc1);
2532     ok( rc1.bottom - rc1.top == sbheight, "Height should be %d size is %ld,%ld - %ld,%ld\n", 
2533             sbheight, rc1.left, rc1.top, rc1.right, rc1.bottom);
2534
2535     /* test window just high enough for a horizontal scroll bar */
2536     nccalchelper( hwnd, 100, sbheight + 1, &rc1);
2537     ok( rc1.bottom - rc1.top == 1, "Height should be %d size is %ld,%ld - %ld,%ld\n", 
2538             1, rc1.left, rc1.top, rc1.right, rc1.bottom);
2539
2540     /* test window too narrow for a vertical scroll bar */
2541     nccalchelper( hwnd, sbwidth - 1, 100, &rc1);
2542     ok( rc1.right - rc1.left == sbwidth - 1 , "Width should be %d size is %ld,%ld - %ld,%ld\n", 
2543             sbwidth - 1, rc1.left, rc1.top, rc1.right, rc1.bottom);
2544
2545     /* test window just wide enough for a vertical scroll bar */
2546     nccalchelper( hwnd, sbwidth, 100, &rc1);
2547     ok( rc1.right - rc1.left == 0, "Width should be %d size is %ld,%ld - %ld,%ld\n", 
2548             0, rc1.left, rc1.top, rc1.right, rc1.bottom);
2549
2550     /* same test, but with client edge: not enough width */
2551     SetWindowLong( hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE | GetWindowLong( hwnd, GWL_EXSTYLE));
2552     nccalchelper( hwnd, sbwidth, 100, &rc1);
2553     ok( rc1.right - rc1.left == sbwidth - 2 * GetSystemMetrics(SM_CXEDGE),
2554             "Width should be %d size is %ld,%ld - %ld,%ld\n", 
2555             sbwidth - 2 * GetSystemMetrics(SM_CXEDGE), rc1.left, rc1.top, rc1.right, rc1.bottom);
2556
2557     DestroyWindow( hwnd);
2558 }
2559
2560 static void test_SetParent(void)
2561 {
2562     BOOL ret;
2563     HWND desktop = GetDesktopWindow();
2564     HMENU hMenu;
2565     BOOL is_win9x = GetWindowLongPtrW(desktop, GWLP_WNDPROC) == 0;
2566     HWND parent, child1, child2, child3, child4, sibling;
2567
2568     parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
2569                              100, 100, 200, 200, 0, 0, 0, NULL);
2570     assert(parent != 0);
2571     child1 = CreateWindowExA(0, "static", NULL, WS_CHILD,
2572                              0, 0, 50, 50, parent, 0, 0, NULL);
2573     assert(child1 != 0);
2574     child2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
2575                              0, 0, 50, 50, child1, 0, 0, NULL);
2576     assert(child2 != 0);
2577     child3 = CreateWindowExA(0, "static", NULL, WS_CHILD,
2578                              0, 0, 50, 50, child2, 0, 0, NULL);
2579     assert(child3 != 0);
2580     child4 = CreateWindowExA(0, "static", NULL, WS_POPUP,
2581                              0, 0, 50, 50, child3, 0, 0, NULL);
2582     assert(child4 != 0);
2583
2584     trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
2585            parent, child1, child2, child3, child4);
2586
2587     check_parents(parent, desktop, 0, 0, 0, parent, parent);
2588     check_parents(child1, parent, parent, parent, 0, parent, parent);
2589     check_parents(child2, desktop, parent, parent, parent, child2, parent);
2590     check_parents(child3, child2, child2, child2, 0, child2, parent);
2591     check_parents(child4, desktop, child2, child2, child2, child4, parent);
2592
2593 todo_wine {
2594     ok(!IsChild(desktop, parent), "wrong parent/child %p/%p\n", desktop, parent);
2595     ok(!IsChild(desktop, child1), "wrong parent/child %p/%p\n", desktop, child1);
2596     ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2);
2597     ok(!IsChild(desktop, child3), "wrong parent/child %p/%p\n", desktop, child3);
2598     ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4);
2599 }
2600
2601     ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1);
2602 todo_wine {
2603     ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2);
2604 }
2605     ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
2606     ok(!IsChild(child1, child2), "wrong parent/child %p/%p\n", child1, child2);
2607     ok(!IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3);
2608     ok(IsChild(child2, child3), "wrong parent/child %p/%p\n", child2, child3);
2609     ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
2610     ok(!IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4);
2611 todo_wine {
2612     ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4);
2613 }
2614
2615     if (!is_win9x) /* Win9x doesn't survive this test */
2616     {
2617         ok(!SetParent(parent, child1), "SetParent should fail\n");
2618         ok(!SetParent(child2, child3), "SetParent should fail\n");
2619         ok(SetParent(child1, parent) != 0, "SetParent should not fail\n");
2620         ok(SetParent(parent, child2) != 0, "SetParent should not fail\n");
2621         ok(SetParent(parent, child3) != 0, "SetParent should not fail\n");
2622         ok(!SetParent(child2, parent), "SetParent should fail\n");
2623         ok(SetParent(parent, child4) != 0, "SetParent should not fail\n");
2624
2625         check_parents(parent, child4, child4, 0, 0, child4, parent);
2626         check_parents(child1, parent, parent, parent, 0, child4, parent);
2627         check_parents(child2, desktop, parent, parent, parent, child2, parent);
2628         check_parents(child3, child2, child2, child2, 0, child2, parent);
2629         check_parents(child4, desktop, child2, child2, child2, child4, parent);
2630     }
2631
2632     hMenu = CreateMenu();
2633     sibling = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
2634                              100, 100, 200, 200, 0, hMenu, 0, NULL);
2635     assert(sibling != 0);
2636
2637     ok(SetParent(sibling, parent) != 0, "SetParent should not fail\n");
2638     ok(GetMenu(sibling) == hMenu, "SetParent should not remove menu\n");
2639
2640     ret = DestroyWindow(parent);
2641     ok( ret, "DestroyWindow() error %ld\n", GetLastError());
2642
2643     ok(!IsWindow(parent), "parent still exists\n");
2644     ok(!IsWindow(sibling), "sibling still exists\n");
2645     ok(!IsWindow(child1), "child1 still exists\n");
2646     ok(!IsWindow(child2), "child2 still exists\n");
2647     ok(!IsWindow(child3), "child3 still exists\n");
2648     ok(!IsWindow(child4), "child4 still exists\n");
2649 }
2650
2651 static LRESULT WINAPI StyleCheckProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
2652 {
2653     LPCREATESTRUCT lpcs;
2654     LPSTYLESTRUCT lpss;
2655
2656     switch (msg)
2657     {
2658     case WM_NCCREATE:
2659     case WM_CREATE:
2660         lpcs = (LPCREATESTRUCT)lparam;
2661         lpss = (LPSTYLESTRUCT)lpcs->lpCreateParams;
2662         if (lpss)
2663         {
2664             if ((lpcs->dwExStyle & WS_EX_DLGMODALFRAME) ||
2665                 ((!(lpcs->dwExStyle & WS_EX_STATICEDGE)) &&
2666                     (lpcs->style & (WS_DLGFRAME | WS_THICKFRAME))))
2667                 ok(lpcs->dwExStyle & WS_EX_WINDOWEDGE, "Window should have WS_EX_WINDOWEDGE style\n");
2668             else
2669                 ok(!(lpcs->dwExStyle & WS_EX_WINDOWEDGE), "Window shouldn't have WS_EX_WINDOWEDGE style\n");
2670
2671             ok((lpss->styleOld & ~WS_EX_WINDOWEDGE) == (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE),
2672                 "Ex style (0x%08lx) should match what the caller passed to CreateWindowEx (0x%08lx)\n",
2673                 (lpss->styleOld & ~WS_EX_WINDOWEDGE), (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE));
2674
2675             ok(lpss->styleNew == lpcs->style,
2676                 "Style (0x%08lx) should match what the caller passed to CreateWindowEx (0x%08lx)\n",
2677                 lpss->styleNew, lpcs->style);
2678         }
2679         break;
2680     }
2681     return DefWindowProc(hwnd, msg, wparam, lparam);
2682 }
2683
2684 static ATOM atomStyleCheckClass;
2685
2686 static void register_style_check_class(void)
2687 {
2688     WNDCLASS wc =
2689     {
2690         0,
2691         StyleCheckProc,
2692         0,
2693         0,
2694         GetModuleHandle(NULL),
2695         NULL,
2696         LoadCursor(NULL, IDC_ARROW),
2697         (HBRUSH)(COLOR_BTNFACE+1),
2698         NULL,
2699         TEXT("WineStyleCheck"),
2700     };
2701     
2702     atomStyleCheckClass = RegisterClass(&wc);
2703 }
2704
2705 static void check_window_style(DWORD dwStyleIn, DWORD dwExStyleIn, DWORD dwStyleOut, DWORD dwExStyleOut)
2706 {
2707     DWORD dwActualStyle;
2708     DWORD dwActualExStyle;
2709     STYLESTRUCT ss;
2710     HWND hwnd;
2711     HWND hwndParent = NULL;
2712     MSG msg;
2713
2714     ss.styleNew = dwStyleIn;
2715     ss.styleOld = dwExStyleIn;
2716
2717     if (dwStyleIn & WS_CHILD)
2718     {
2719         hwndParent = CreateWindowEx(0, MAKEINTATOM(atomStyleCheckClass), NULL,
2720             WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
2721     }
2722
2723     hwnd = CreateWindowEx(dwExStyleIn, MAKEINTATOM(atomStyleCheckClass), NULL,
2724                     dwStyleIn, 0, 0, 0, 0, hwndParent, NULL, NULL, &ss);
2725     assert(hwnd);
2726
2727     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2728     {
2729         TranslateMessage(&msg);
2730         DispatchMessage(&msg);
2731     }
2732
2733     dwActualStyle = GetWindowLong(hwnd, GWL_STYLE);
2734     dwActualExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
2735     ok((dwActualStyle == dwStyleOut) && (dwActualExStyle == dwExStyleOut),
2736         "Style (0x%08lx) should really be 0x%08lx and/or Ex style (0x%08lx) should really be 0x%08lx\n",
2737         dwActualStyle, dwStyleOut, dwActualExStyle, dwExStyleOut);
2738
2739     DestroyWindow(hwnd);
2740     if (hwndParent) DestroyWindow(hwndParent);
2741 }
2742
2743 /* tests what window styles the window manager automatically adds */
2744 static void test_window_styles(void)
2745 {
2746     register_style_check_class();
2747
2748     check_window_style(0, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE);
2749     check_window_style(WS_OVERLAPPEDWINDOW, 0, WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE);
2750     check_window_style(WS_CHILD, 0, WS_CHILD, 0);
2751     check_window_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
2752     check_window_style(0, WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW);
2753     check_window_style(WS_POPUP, 0, WS_POPUP|WS_CLIPSIBLINGS, 0);
2754     check_window_style(WS_POPUP, WS_EX_WINDOWEDGE, WS_POPUP|WS_CLIPSIBLINGS, 0);
2755     check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME, WS_CHILD, WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
2756     check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME|WS_EX_STATICEDGE, WS_CHILD, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
2757     check_window_style(WS_CAPTION, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE);
2758     check_window_style(0, WS_EX_APPWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_APPWINDOW|WS_EX_WINDOWEDGE);
2759 }
2760
2761 static void test_scrollvalidate( HWND parent)
2762 {
2763     HDC hdc;
2764     HRGN hrgn=CreateRectRgn(0,0,0,0);
2765     HRGN exprgn, tmprgn, clipping;
2766     RECT rc, rcu, cliprc;
2767     /* create two overlapping child windows. The visual region
2768      * of hwnd1 is clipped by the overlapping part of
2769      * hwnd2 because of the WS_CLIPSIBLING style */
2770     HWND hwnd1, hwnd2;
2771
2772     hwnd2 = CreateWindowExA(0, "static", NULL,
2773             WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
2774             75, 30, 100, 100, parent, 0, 0, NULL);
2775     hwnd1 = CreateWindowExA(0, "static", NULL,
2776             WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
2777             25, 50, 100, 100, parent, 0, 0, NULL);
2778     ShowWindow( parent, SW_SHOW);
2779     UpdateWindow( parent);
2780     GetClientRect( hwnd1, &rc);
2781     cliprc=rc; 
2782     clipping = CreateRectRgn( 10, 10, 90, 90);
2783     hdc = GetDC( hwnd1);
2784     /* for a visual touch */
2785     TextOut( hdc, 0,10, "0123456789", 10);
2786     ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
2787     if (winetest_debug > 0) dump_region(hrgn);
2788     /* create a region with what is expected */
2789     exprgn = CreateRectRgn( 39,0,49,74);
2790     tmprgn = CreateRectRgn( 88,79,98,93);
2791     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
2792     tmprgn = CreateRectRgn( 0,93,98,98);
2793     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
2794     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
2795     trace("update rect is %ld,%ld - %ld,%ld\n",
2796             rcu.left,rcu.top,rcu.right,rcu.bottom);
2797     /* now with clipping region */
2798     SelectClipRgn( hdc, clipping);
2799     ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
2800     if (winetest_debug > 0) dump_region(hrgn);
2801     /* create a region with what is expected */
2802     exprgn = CreateRectRgn( 39,10,49,74);
2803     tmprgn = CreateRectRgn( 80,79,90,85);
2804     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
2805     tmprgn = CreateRectRgn( 10,85,90,90);
2806     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
2807     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
2808     trace("update rect is %ld,%ld - %ld,%ld\n",
2809             rcu.left,rcu.top,rcu.right,rcu.bottom);
2810     ReleaseDC( hwnd1, hdc);
2811
2812     /* test scrolling a window with an update region */
2813     DestroyWindow( hwnd2);
2814     ValidateRect( hwnd1, NULL);
2815     SetRect( &rc, 40,40, 50,50);
2816     InvalidateRect( hwnd1, &rc, 1);
2817     GetClientRect( hwnd1, &rc);
2818     cliprc=rc;
2819     ScrollWindowEx( hwnd1, -10, 0, &rc, &cliprc, hrgn, &rcu,
2820       SW_SCROLLCHILDREN | SW_INVALIDATE);
2821     if (winetest_debug > 0) dump_region(hrgn);
2822     exprgn = CreateRectRgn( 88,0,98,98);
2823     tmprgn = CreateRectRgn( 30, 40, 50, 50);
2824     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
2825     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
2826
2827     /* now test ScrollWindowEx with a combination of
2828      * WS_CLIPCHILDREN style and SW_SCROLLCHILDREN flag */
2829     /* make hwnd2 the child of hwnd1 */
2830     hwnd2 = CreateWindowExA(0, "static", NULL,
2831             WS_CHILD| WS_VISIBLE | WS_BORDER ,
2832             50, 50, 100, 100, hwnd1, 0, 0, NULL);
2833     SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) & ~WS_CLIPSIBLINGS);
2834     GetClientRect( hwnd1, &rc);
2835     cliprc=rc;
2836
2837     /* WS_CLIPCHILDREN and SW_SCROLLCHILDREN */
2838     SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
2839     ValidateRect( hwnd1, NULL);
2840     ValidateRect( hwnd2, NULL);
2841     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu,
2842       SW_SCROLLCHILDREN | SW_INVALIDATE);
2843     if (winetest_debug > 0) dump_region(hrgn);
2844     exprgn = CreateRectRgn( 88,0,98,88);
2845     tmprgn = CreateRectRgn( 0,88,98,98);
2846     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
2847     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
2848
2849     /* SW_SCROLLCHILDREN */
2850     SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
2851     ValidateRect( hwnd1, NULL);
2852     ValidateRect( hwnd2, NULL);
2853     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_SCROLLCHILDREN | SW_INVALIDATE);
2854     if (winetest_debug > 0) dump_region(hrgn);
2855     /* expected region is the same as in previous test */
2856     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
2857
2858     /* no SW_SCROLLCHILDREN */
2859     SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
2860     ValidateRect( hwnd1, NULL);
2861     ValidateRect( hwnd2, NULL);
2862     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
2863     if (winetest_debug > 0) dump_region(hrgn);
2864     /* expected region is the same as in previous test */
2865     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
2866
2867     /* WS_CLIPCHILDREN and no SW_SCROLLCHILDREN */
2868     SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
2869     ValidateRect( hwnd1, NULL);
2870     ValidateRect( hwnd2, NULL);
2871     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
2872     if (winetest_debug > 0) dump_region(hrgn);
2873     exprgn = CreateRectRgn( 88,0,98,20);
2874     tmprgn = CreateRectRgn( 20,20,98,30);
2875     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
2876     tmprgn = CreateRectRgn( 20,30,30,88);
2877     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
2878     tmprgn = CreateRectRgn( 0,88,30,98);
2879     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
2880     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
2881
2882     /* clean up */
2883     DeleteObject( hrgn);
2884     DeleteObject( exprgn);
2885     DeleteObject( tmprgn);
2886     DestroyWindow( hwnd1);
2887     DestroyWindow( hwnd2);
2888 }
2889
2890 /* couple of tests of return values of scrollbar functions
2891  * called on a scrollbarless window */ 
2892 static void test_scroll(void)
2893 {
2894     BOOL ret;
2895     INT min, max;
2896     SCROLLINFO si;
2897     HWND hwnd = CreateWindowExA(0, "Static", "Wine test window",
2898         WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP,
2899         100, 100, 200, 200, 0, 0, 0, NULL);
2900     /* horizontal */
2901     ret = GetScrollRange( hwnd, SB_HORZ, &min, &max);
2902     ok( ret, "GetScrollRange returns FALSE\n");
2903     ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min);
2904     ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min);
2905     si.cbSize = sizeof( si);
2906     si.fMask = SIF_PAGE;
2907     si.nPage = 0xdeadbeef;
2908     ret = GetScrollInfo( hwnd, SB_HORZ, &si);
2909     ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret);
2910     ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage);
2911     /* vertical */
2912     ret = GetScrollRange( hwnd, SB_VERT, &min, &max);
2913     ok( ret, "GetScrollRange returns FALSE\n");
2914     ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min);
2915     ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min);
2916     si.cbSize = sizeof( si);
2917     si.fMask = SIF_PAGE;
2918     si.nPage = 0xdeadbeef;
2919     ret = GetScrollInfo( hwnd, SB_VERT, &si);
2920     ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret);
2921     ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage);
2922     /* clean up */
2923     DestroyWindow( hwnd);
2924 }
2925
2926 static void test_params(void)
2927 {
2928     HWND hwnd;
2929     INT rc;
2930
2931     /* Just a param check */
2932     SetLastError(0xdeadbeef);
2933     rc = GetWindowText(hwndMain2, NULL, 1024);
2934     ok( rc==0, "GetWindowText: rc=%d err=%ld\n",rc,GetLastError());
2935
2936     SetLastError(0xdeadbeef);
2937     hwnd=CreateWindow("LISTBOX", "TestList",
2938                       (LBS_STANDARD & ~LBS_SORT),
2939                       0, 0, 100, 100,
2940                       NULL, (HMENU)1, NULL, 0);
2941
2942     ok(!hwnd, "CreateWindow with invalid menu handle should fail\n");
2943     ok(GetLastError() == ERROR_INVALID_MENU_HANDLE || /* NT */
2944        GetLastError() == 0xdeadbeef, /* Win9x */
2945        "wrong last error value %ld\n", GetLastError());
2946 }
2947
2948 static void test_AWRwindow(LPCSTR class, LONG style, LONG exStyle, BOOL menu)
2949 {
2950     HWND hwnd = 0;
2951
2952     hwnd = CreateWindowEx(exStyle, class, class, style,
2953                           110, 100,
2954                           225, 200,
2955                           0,
2956                           menu ? hmenu : 0,
2957                           0, 0);
2958     if (!hwnd) {
2959         trace("Failed to create window class=%s, style=0x%08lx, exStyle=0x%08lx\n", class, style, exStyle);
2960         return;
2961     }
2962     ShowWindow(hwnd, SW_SHOW);
2963
2964     test_nonclient_area(hwnd);
2965
2966     SetMenu(hwnd, 0);
2967     DestroyWindow(hwnd);
2968 }
2969
2970 static BOOL AWR_init(void)
2971 {
2972     WNDCLASS class;
2973
2974     class.style         = CS_HREDRAW | CS_VREDRAW;
2975     class.lpfnWndProc     = DefWindowProcA;
2976     class.cbClsExtra    = 0;
2977     class.cbWndExtra    = 0;
2978     class.hInstance     = 0;
2979     class.hIcon         = LoadIcon (0, IDI_APPLICATION);
2980     class.hCursor       = LoadCursor (0, IDC_ARROW);
2981     class.hbrBackground = 0;
2982     class.lpszMenuName  = 0;
2983     class.lpszClassName = szAWRClass;
2984     
2985     if (!RegisterClass (&class)) {
2986         ok(FALSE, "RegisterClass failed\n");
2987         return FALSE;
2988     }
2989
2990     hmenu = CreateMenu();
2991     if (!hmenu)
2992         return FALSE;
2993     ok(hmenu != 0, "Failed to create menu\n");
2994     ok(AppendMenu(hmenu, MF_STRING, 1, "Test!"), "Failed to create menu item\n");
2995     
2996     return TRUE;
2997 }
2998
2999
3000 static void test_AWR_window_size(BOOL menu)
3001 {
3002     LONG styles[] = {
3003         WS_POPUP,
3004         WS_MAXIMIZE, WS_BORDER, WS_DLGFRAME, 
3005         WS_SYSMENU, 
3006         WS_THICKFRAME,
3007         WS_MINIMIZEBOX, WS_MAXIMIZEBOX,
3008         WS_HSCROLL, WS_VSCROLL
3009     };
3010     LONG exStyles[] = {
3011         WS_EX_CLIENTEDGE,
3012         WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE,
3013         WS_EX_APPWINDOW,
3014 #if 0
3015         /* These styles have problems on (at least) WinXP (SP2) and Wine */
3016         WS_EX_DLGMODALFRAME, 
3017         WS_EX_STATICEDGE, 
3018 #endif
3019     };
3020
3021     int i;    
3022
3023     /* A exhaustive check of all the styles takes too long
3024      * so just do a (hopefully representative) sample
3025      */
3026     for (i = 0; i < COUNTOF(styles); ++i)
3027         test_AWRwindow(szAWRClass, styles[i], 0, menu);
3028     for (i = 0; i < COUNTOF(exStyles); ++i) {
3029         test_AWRwindow(szAWRClass, WS_POPUP, exStyles[i], menu);
3030         test_AWRwindow(szAWRClass, WS_THICKFRAME, exStyles[i], menu);
3031     }
3032 }
3033 #undef COUNTOF
3034
3035 #define SHOWSYSMETRIC(SM) trace(#SM "=%d\n", GetSystemMetrics(SM))
3036
3037 static void test_AdjustWindowRect(void)
3038 {
3039     if (!AWR_init())
3040         return;
3041     
3042     SHOWSYSMETRIC(SM_CYCAPTION);
3043     SHOWSYSMETRIC(SM_CYSMCAPTION);
3044     SHOWSYSMETRIC(SM_CYMENU);
3045     SHOWSYSMETRIC(SM_CXEDGE);
3046     SHOWSYSMETRIC(SM_CYEDGE);
3047     SHOWSYSMETRIC(SM_CXVSCROLL);
3048     SHOWSYSMETRIC(SM_CYHSCROLL);
3049     SHOWSYSMETRIC(SM_CXFRAME);
3050     SHOWSYSMETRIC(SM_CYFRAME);
3051     SHOWSYSMETRIC(SM_CXDLGFRAME);
3052     SHOWSYSMETRIC(SM_CYDLGFRAME);
3053     SHOWSYSMETRIC(SM_CXBORDER);
3054     SHOWSYSMETRIC(SM_CYBORDER);  
3055
3056     test_AWR_window_size(FALSE);
3057     test_AWR_window_size(TRUE);
3058
3059     DestroyMenu(hmenu);
3060 }
3061 #undef SHOWSYSMETRIC
3062
3063
3064 /* Global variables to trigger exit from loop */
3065 static int redrawComplete, WMPAINT_count;
3066
3067 static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
3068 {
3069     switch (msg)
3070     {
3071     case WM_PAINT:
3072         trace("doing WM_PAINT %d\n", WMPAINT_count);
3073         WMPAINT_count++;
3074         if (WMPAINT_count > 10 && redrawComplete == 0) {
3075             PAINTSTRUCT ps;
3076             BeginPaint(hwnd, &ps);
3077             EndPaint(hwnd, &ps);
3078             return 1;
3079         }
3080         return 0;
3081         break;
3082     }
3083     return DefWindowProc(hwnd, msg, wparam, lparam);
3084 }
3085
3086 /* Ensure we exit from RedrawNow regardless of invalidated area */
3087 static void test_redrawnow(void)
3088 {
3089    WNDCLASSA cls;
3090    HWND hwndMain;
3091
3092    cls.style = CS_DBLCLKS;
3093    cls.lpfnWndProc = redraw_window_procA;
3094    cls.cbClsExtra = 0;
3095    cls.cbWndExtra = 0;
3096    cls.hInstance = GetModuleHandleA(0);
3097    cls.hIcon = 0;
3098    cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
3099    cls.hbrBackground = GetStockObject(WHITE_BRUSH);
3100    cls.lpszMenuName = NULL;
3101    cls.lpszClassName = "RedrawWindowClass";
3102
3103    if(!RegisterClassA(&cls)) {
3104        trace("Register failed %ld\n", GetLastError());
3105        return;
3106    }
3107
3108    hwndMain = CreateWindowA("RedrawWindowClass", "Main Window", WS_OVERLAPPEDWINDOW,
3109                             CW_USEDEFAULT, 0, 100, 100, NULL, NULL, 0, NULL);
3110
3111    ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
3112    ShowWindow(hwndMain, SW_SHOW);
3113    ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
3114    RedrawWindow(hwndMain, NULL,NULL,RDW_UPDATENOW | RDW_ALLCHILDREN);
3115    ok( WMPAINT_count == 1, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
3116    redrawComplete = TRUE;
3117    ok( WMPAINT_count < 10, "RedrawWindow (RDW_UPDATENOW) never completed (%d)\n", WMPAINT_count);
3118
3119    /* clean up */
3120    DestroyWindow( hwndMain);
3121 }
3122
3123 struct parentdc_stat {
3124     RECT client;
3125     RECT clip;
3126     RECT paint;
3127 };
3128
3129 struct parentdc_test {
3130    struct parentdc_stat main, main_todo;
3131    struct parentdc_stat child1, child1_todo;
3132    struct parentdc_stat child2, child2_todo;
3133 };
3134
3135 static LRESULT WINAPI parentdc_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
3136 {
3137     RECT rc;
3138     PAINTSTRUCT ps;
3139
3140     struct parentdc_stat *t = (struct parentdc_stat *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
3141
3142     switch (msg)
3143     {
3144     case WM_PAINT:
3145         trace("doing WM_PAINT on %p\n", hwnd);
3146         GetClientRect(hwnd, &rc);
3147         CopyRect(&t->client, &rc);
3148         trace("client rect (%ld, %ld)-(%ld, %ld)\n", rc.left, rc.top, rc.right, rc.bottom);
3149         GetWindowRect(hwnd, &rc);
3150         trace("window rect (%ld, %ld)-(%ld, %ld)\n", rc.left, rc.top, rc.right, rc.bottom);
3151         BeginPaint(hwnd, &ps);
3152         CopyRect(&t->paint, &ps.rcPaint);
3153         GetClipBox(ps.hdc, &rc);
3154         CopyRect(&t->clip, &rc);
3155         trace("clip rect (%ld, %ld)-(%ld, %ld)\n", rc.left, rc.top, rc.right, rc.bottom);
3156         trace("paint rect (%ld, %ld)-(%ld, %ld)\n", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
3157         EndPaint(hwnd, &ps);
3158         return 0;
3159     }
3160     return DefWindowProc(hwnd, msg, wparam, lparam);
3161 }
3162
3163 static void zero_parentdc_stat(struct parentdc_stat *t)
3164 {
3165     SetRectEmpty(&t->client);
3166     SetRectEmpty(&t->clip);
3167     SetRectEmpty(&t->paint);
3168 }
3169
3170 static void zero_parentdc_test(struct parentdc_test *t)
3171 {
3172     zero_parentdc_stat(&t->main);
3173     zero_parentdc_stat(&t->child1);
3174     zero_parentdc_stat(&t->child2);
3175 }
3176
3177 #define parentdc_field_ok(t, w, r, f, got) \
3178   ok (t.w.r.f==got.w.r.f, "window " #w ", rect " #r ", field " #f \
3179       ": expected %ld, got %ld\n", \
3180       t.w.r.f, got.w.r.f)
3181
3182 #define parentdc_todo_field_ok(t, w, r, f, got) \
3183   if (t.w##_todo.r.f) todo_wine { parentdc_field_ok(t, w, r, f, got); } \
3184   else parentdc_field_ok(t, w, r, f, got)
3185
3186 #define parentdc_rect_ok(t, w, r, got) \
3187   parentdc_todo_field_ok(t, w, r, left, got); \
3188   parentdc_todo_field_ok(t, w, r, top, got); \
3189   parentdc_todo_field_ok(t, w, r, right, got); \
3190   parentdc_todo_field_ok(t, w, r, bottom, got);
3191
3192 #define parentdc_win_ok(t, w, got) \
3193   parentdc_rect_ok(t, w, client, got); \
3194   parentdc_rect_ok(t, w, clip, got); \
3195   parentdc_rect_ok(t, w, paint, got);
3196
3197 #define parentdc_ok(t, got) \
3198   parentdc_win_ok(t, main, got); \
3199   parentdc_win_ok(t, child1, got); \
3200   parentdc_win_ok(t, child2, got);
3201
3202 static void test_csparentdc(void)
3203 {
3204    WNDCLASSA clsMain, cls;
3205    HWND hwndMain, hwnd1, hwnd2;
3206    MSG msg;
3207    RECT rc;
3208
3209    struct parentdc_test test_answer;
3210
3211 #define nothing_todo {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
3212    const struct parentdc_test test1 = 
3213    {
3214         {{0, 0, 150, 150}, {0, 0, 150, 150}, {0, 0, 150, 150}}, nothing_todo,
3215         {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
3216         {{0, 0, 40, 40}, {-40, -40, 110, 110}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
3217    };
3218
3219    const struct parentdc_test test2 = 
3220    {
3221         {{0, 0, 150, 150}, {0, 0, 50, 50}, {0, 0, 50, 50}}, nothing_todo,
3222         {{0, 0, 40, 40}, {-20, -20, 30, 30}, {0, 0, 30, 30}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
3223         {{0, 0, 40, 40}, {-40, -40, 10, 10}, {0, 0, 10, 10}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
3224    };
3225
3226    const struct parentdc_test test3 = 
3227    {
3228         {{0, 0, 150, 150}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
3229         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
3230         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
3231    };
3232
3233    const struct parentdc_test test4 = 
3234    {
3235         {{0, 0, 150, 150}, {40, 40, 50, 50}, {40, 40, 50, 50}}, nothing_todo,
3236         {{0, 0, 40, 40}, {20, 20, 30, 30}, {20, 20, 30, 30}}, nothing_todo,
3237         {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
3238    };
3239
3240    const struct parentdc_test test5 = 
3241    {
3242         {{0, 0, 150, 150}, {20, 20, 60, 60}, {20, 20, 60, 60}}, nothing_todo,
3243         {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
3244         {{0, 0, 40, 40}, {-20, -20, 20, 20}, {0, 0, 20, 20}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
3245    };
3246
3247    const struct parentdc_test test6 = 
3248    {
3249         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
3250         {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
3251         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
3252    };
3253
3254    const struct parentdc_test test7 = 
3255    {
3256         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
3257         {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
3258         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
3259    };
3260 #undef nothing_todo
3261
3262    clsMain.style = CS_DBLCLKS;
3263    clsMain.lpfnWndProc = parentdc_window_procA;
3264    clsMain.cbClsExtra = 0;
3265    clsMain.cbWndExtra = 0;
3266    clsMain.hInstance = GetModuleHandleA(0);
3267    clsMain.hIcon = 0;
3268    clsMain.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
3269    clsMain.hbrBackground = GetStockObject(WHITE_BRUSH);
3270    clsMain.lpszMenuName = NULL;
3271    clsMain.lpszClassName = "ParentDcMainWindowClass";
3272
3273    if(!RegisterClassA(&clsMain)) {
3274        trace("Register failed %ld\n", GetLastError());
3275        return;
3276    }
3277
3278    cls.style = CS_DBLCLKS | CS_PARENTDC;
3279    cls.lpfnWndProc = parentdc_window_procA;
3280    cls.cbClsExtra = 0;
3281    cls.cbWndExtra = 0;
3282    cls.hInstance = GetModuleHandleA(0);
3283    cls.hIcon = 0;
3284    cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
3285    cls.hbrBackground = GetStockObject(WHITE_BRUSH);
3286    cls.lpszMenuName = NULL;
3287    cls.lpszClassName = "ParentDcWindowClass";
3288
3289    if(!RegisterClassA(&cls)) {
3290        trace("Register failed %ld\n", GetLastError());
3291        return;
3292    }
3293
3294    SetRect(&rc, 0, 0, 150, 150);
3295    AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0);
3296    hwndMain = CreateWindowA("ParentDcMainWindowClass", "Main Window", WS_OVERLAPPEDWINDOW,
3297                             CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, 0, NULL);
3298    SetWindowLongPtrA(hwndMain, GWLP_USERDATA, (DWORD_PTR)&test_answer.main);
3299    hwnd1 = CreateWindowA("ParentDcWindowClass", "Child Window 1", WS_CHILD,
3300                             20, 20, 40, 40, hwndMain, NULL, 0, NULL);
3301    SetWindowLongPtrA(hwnd1, GWLP_USERDATA, (DWORD_PTR)&test_answer.child1);
3302    hwnd2 = CreateWindowA("ParentDcWindowClass", "Child Window 2", WS_CHILD,
3303                             40, 40, 40, 40, hwndMain, NULL, 0, NULL);
3304    SetWindowLongPtrA(hwnd2, GWLP_USERDATA, (DWORD_PTR)&test_answer.child2);
3305    ShowWindow(hwndMain, SW_SHOW);
3306    ShowWindow(hwnd1, SW_SHOW);
3307    ShowWindow(hwnd2, SW_SHOW);
3308
3309    zero_parentdc_test(&test_answer);
3310    InvalidateRect(hwndMain, NULL, TRUE);
3311    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3312    parentdc_ok(test1, test_answer);
3313
3314    zero_parentdc_test(&test_answer);
3315    SetRect(&rc, 0, 0, 50, 50);
3316    InvalidateRect(hwndMain, &rc, TRUE);
3317    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3318    parentdc_ok(test2, test_answer);
3319
3320    zero_parentdc_test(&test_answer);
3321    SetRect(&rc, 0, 0, 10, 10);
3322    InvalidateRect(hwndMain, &rc, TRUE);
3323    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3324    parentdc_ok(test3, test_answer);
3325
3326    zero_parentdc_test(&test_answer);
3327    SetRect(&rc, 40, 40, 50, 50);
3328    InvalidateRect(hwndMain, &rc, TRUE);
3329    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3330    parentdc_ok(test4, test_answer);
3331
3332    zero_parentdc_test(&test_answer);
3333    SetRect(&rc, 20, 20, 60, 60);
3334    InvalidateRect(hwndMain, &rc, TRUE);
3335    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3336    parentdc_ok(test5, test_answer);
3337
3338    zero_parentdc_test(&test_answer);
3339    SetRect(&rc, 0, 0, 10, 10);
3340    InvalidateRect(hwnd1, &rc, TRUE);
3341    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3342    parentdc_ok(test6, test_answer);
3343
3344    zero_parentdc_test(&test_answer);
3345    SetRect(&rc, -5, -5, 65, 65);
3346    InvalidateRect(hwnd1, &rc, TRUE);
3347    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3348    parentdc_ok(test7, test_answer);
3349
3350    DestroyWindow(hwndMain);
3351    DestroyWindow(hwnd1);
3352    DestroyWindow(hwnd2);
3353 }
3354
3355 static void test_IsWindowUnicode(void)
3356 {
3357     static const char ansi_class_nameA[] = "ansi class name";
3358     static const WCHAR ansi_class_nameW[] = {'a','n','s','i',' ','c','l','a','s','s',' ','n','a','m','e',0};
3359     static const char unicode_class_nameA[] = "unicode class name";
3360     static const WCHAR unicode_class_nameW[] = {'u','n','i','c','o','d','e',' ','c','l','a','s','s',' ','n','a','m','e',0};
3361     WNDCLASSA classA;
3362     WNDCLASSW classW;
3363     HWND hwnd;
3364
3365     memset(&classW, 0, sizeof(classW));
3366     classW.hInstance = GetModuleHandleA(0);
3367     classW.lpfnWndProc = DefWindowProcW;
3368     classW.lpszClassName = unicode_class_nameW;
3369     if (!RegisterClassW(&classW)) return;
3370
3371     memset(&classA, 0, sizeof(classA));
3372     classA.hInstance = GetModuleHandleA(0);
3373     classA.lpfnWndProc = DefWindowProcA;
3374     classA.lpszClassName = ansi_class_nameA;
3375     assert(RegisterClassA(&classA));
3376
3377     /* unicode class: window proc */
3378     hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP,
3379                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
3380     assert(hwnd);
3381
3382     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3383     SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)DefWindowProcA);
3384     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3385     SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)DefWindowProcW);
3386     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3387
3388     DestroyWindow(hwnd);
3389
3390     hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP,
3391                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
3392     assert(hwnd);
3393
3394     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3395     SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)DefWindowProcA);
3396     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3397     SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)DefWindowProcW);
3398     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3399
3400     DestroyWindow(hwnd);
3401
3402     /* ansi class: window proc */
3403     hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP,
3404                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
3405     assert(hwnd);
3406
3407     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3408     SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)DefWindowProcW);
3409     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3410     SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)DefWindowProcA);
3411     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3412
3413     DestroyWindow(hwnd);
3414
3415     hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP,
3416                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
3417     assert(hwnd);
3418
3419     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3420     SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)DefWindowProcW);
3421     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3422     SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)DefWindowProcA);
3423     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3424
3425     DestroyWindow(hwnd);
3426
3427     /* unicode class: class proc */
3428     hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP,
3429                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
3430     assert(hwnd);
3431
3432     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3433     SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)DefWindowProcA);
3434     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3435     /* do not restore class window proc back to unicode */
3436
3437     DestroyWindow(hwnd);
3438
3439     hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP,
3440                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
3441     assert(hwnd);
3442
3443     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3444     SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)DefWindowProcW);
3445     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3446
3447     DestroyWindow(hwnd);
3448
3449     /* ansi class: class proc */
3450     hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP,
3451                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
3452     assert(hwnd);
3453
3454     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3455     SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)DefWindowProcW);
3456     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
3457     /* do not restore class window proc back to ansi */
3458
3459     DestroyWindow(hwnd);
3460
3461     hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP,
3462                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
3463     assert(hwnd);
3464
3465     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3466     SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)DefWindowProcA);
3467     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
3468
3469     DestroyWindow(hwnd);
3470 }
3471
3472 START_TEST(win)
3473 {
3474     pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
3475     pGetWindowInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetWindowInfo" );
3476
3477     hwndMain = CreateWindowExA(0, "static", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, NULL);
3478     if (hwndMain)
3479     {
3480         ok(!GetParent(hwndMain), "GetParent should return 0 for message only windows\n");
3481         if (pGetAncestor)
3482         {
3483             hwndMessage = pGetAncestor(hwndMain, GA_PARENT);
3484             ok(hwndMessage != 0, "GetAncestor(GA_PARENT) should not return 0 for message only windows\n");
3485             trace("hwndMessage %p\n", hwndMessage);
3486         }
3487         DestroyWindow(hwndMain);
3488     }
3489     else
3490         trace("CreateWindowExA with parent HWND_MESSAGE failed\n");
3491
3492     if (!RegisterWindowClasses()) assert(0);
3493
3494     hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
3495     assert(hhook);
3496
3497     hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
3498                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
3499                                WS_MAXIMIZEBOX | WS_POPUP,
3500                                100, 100, 200, 200,
3501                                0, 0, 0, NULL);
3502     test_nonclient_area(hwndMain);
3503
3504     hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
3505                                 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
3506                                 WS_MAXIMIZEBOX | WS_POPUP,
3507                                 100, 100, 200, 200,
3508                                 0, 0, 0, NULL);
3509     assert( hwndMain );
3510     assert( hwndMain2 );
3511
3512     /* Add the tests below this line */
3513     test_params();
3514
3515     test_capture_1();
3516     test_capture_2();
3517     test_capture_3(hwndMain, hwndMain2);
3518
3519     test_parent_owner();
3520     test_SetParent();
3521     test_shell_window();
3522
3523     test_mdi();
3524     test_icons();
3525     test_SetWindowPos(hwndMain);
3526     test_SetMenu(hwndMain);
3527     test_SetFocus(hwndMain);
3528     test_SetActiveWindow(hwndMain);
3529
3530     test_children_zorder(hwndMain);
3531     test_keyboard_input(hwndMain);
3532     test_mouse_input(hwndMain);
3533     test_validatergn(hwndMain);
3534     test_nccalcscroll( hwndMain);
3535     test_scrollvalidate( hwndMain);
3536     test_scroll();
3537     test_IsWindowUnicode();
3538     test_vis_rgn(hwndMain);
3539
3540     test_AdjustWindowRect();
3541     test_window_styles();
3542     test_redrawnow();
3543     test_csparentdc();
3544
3545     /* add the tests above this line */
3546     UnhookWindowsHookEx(hhook);
3547 }