- define additional shell paths for CSIDL_... constants
[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 #include <assert.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35
36 #include "wine/test.h"
37
38 #ifndef SPI_GETDESKWALLPAPER
39 #define SPI_GETDESKWALLPAPER 0x0073
40 #endif
41
42 #define LONG_PTR INT_PTR
43 #define ULONG_PTR UINT_PTR
44
45 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
46
47 static HWND hwndMain, hwndMain2;
48 static HHOOK hhook;
49
50 /* check the values returned by the various parent/owner functions on a given window */
51 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
52                            HWND gw_owner, HWND ga_root, HWND ga_root_owner )
53 {
54     HWND res;
55
56     if (pGetAncestor)
57     {
58         res = pGetAncestor( hwnd, GA_PARENT );
59         ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent );
60     }
61     res = (HWND)GetWindowLongA( hwnd, GWL_HWNDPARENT );
62     ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p\n", res, gwl_parent );
63     res = GetParent( hwnd );
64     ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent );
65     res = GetWindow( hwnd, GW_OWNER );
66     ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p\n", res, gw_owner );
67     if (pGetAncestor)
68     {
69         res = pGetAncestor( hwnd, GA_ROOT );
70         ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p\n", res, ga_root );
71         res = pGetAncestor( hwnd, GA_ROOTOWNER );
72         ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p\n", res, ga_root_owner );
73     }
74 }
75
76
77 static HWND create_tool_window( LONG style, HWND parent )
78 {
79     HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
80                                0, 0, 100, 100, parent, 0, 0, NULL );
81     ok( ret != 0, "Creation failed\n" );
82     return ret;
83 }
84
85 /* test parent and owner values for various combinations */
86 static void test_parent_owner(void)
87 {
88     LONG style;
89     HWND test, owner, ret;
90     HWND desktop = GetDesktopWindow();
91     HWND child = create_tool_window( WS_CHILD, hwndMain );
92
93     trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
94
95     /* child without parent, should fail */
96     test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
97                            WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
98     ok( !test, "WS_CHILD without parent created\n" );
99
100     /* desktop window */
101     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
102     style = GetWindowLongA( desktop, GWL_STYLE );
103     ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" );
104     ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" );
105     ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" );
106
107     /* normal child window */
108     test = create_tool_window( WS_CHILD, hwndMain );
109     trace( "created child %p\n", test );
110     check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
111     SetWindowLongA( test, GWL_STYLE, 0 );
112     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
113     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
114     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
115     SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
116     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
117     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
118     DestroyWindow( test );
119
120     /* normal child window with WS_MAXIMIZE */
121     test = create_tool_window( WS_CHILD | WS_MAXIMIZE, hwndMain );
122     DestroyWindow( test );
123
124     /* normal child window with WS_THICKFRAME */
125     test = create_tool_window( WS_CHILD | WS_THICKFRAME, hwndMain );
126     DestroyWindow( test );
127
128     /* popup window with WS_THICKFRAME */
129     test = create_tool_window( WS_POPUP | WS_THICKFRAME, hwndMain );
130     DestroyWindow( test );
131
132     /* child of desktop */
133     test = create_tool_window( WS_CHILD, desktop );
134     trace( "created child of desktop %p\n", test );
135     check_parents( test, desktop, 0, desktop, 0, test, desktop );
136     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
137     check_parents( test, desktop, 0, 0, 0, test, test );
138     SetWindowLongA( test, GWL_STYLE, 0 );
139     check_parents( test, desktop, 0, 0, 0, test, test );
140     DestroyWindow( test );
141
142     /* child of desktop with WS_MAXIMIZE */
143     test = create_tool_window( WS_CHILD | WS_MAXIMIZE, desktop );
144     DestroyWindow( test );
145
146     /* child of desktop with WS_MINIMIZE */
147     test = create_tool_window( WS_CHILD | WS_MINIMIZE, desktop );
148     DestroyWindow( test );
149
150     /* child of child */
151     test = create_tool_window( WS_CHILD, child );
152     trace( "created child of child %p\n", test );
153     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
154     SetWindowLongA( test, GWL_STYLE, 0 );
155     check_parents( test, child, child, 0, 0, hwndMain, test );
156     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
157     check_parents( test, child, child, 0, 0, hwndMain, test );
158     DestroyWindow( test );
159
160     /* child of child with WS_MAXIMIZE */
161     test = create_tool_window( WS_CHILD | WS_MAXIMIZE, child );
162     DestroyWindow( test );
163
164     /* child of child with WS_MINIMIZE */
165     test = create_tool_window( WS_CHILD | WS_MINIMIZE, child );
166     DestroyWindow( test );
167
168     /* not owned top-level window */
169     test = create_tool_window( 0, 0 );
170     trace( "created top-level %p\n", test );
171     check_parents( test, desktop, 0, 0, 0, test, test );
172     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
173     check_parents( test, desktop, 0, 0, 0, test, test );
174     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
175     check_parents( test, desktop, 0, desktop, 0, test, desktop );
176     DestroyWindow( test );
177
178     /* not owned top-level window with WS_MAXIMIZE */
179     test = create_tool_window( WS_MAXIMIZE, 0 );
180     DestroyWindow( test );
181
182     /* owned top-level window */
183     test = create_tool_window( 0, hwndMain );
184     trace( "created owned top-level %p\n", test );
185     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
186     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
187     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
188     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
189     check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
190     DestroyWindow( test );
191
192     /* owned top-level window with WS_MAXIMIZE */
193     test = create_tool_window( WS_MAXIMIZE, hwndMain );
194     DestroyWindow( test );
195
196     /* not owned popup */
197     test = create_tool_window( WS_POPUP, 0 );
198     trace( "created popup %p\n", test );
199     check_parents( test, desktop, 0, 0, 0, test, test );
200     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
201     check_parents( test, desktop, 0, desktop, 0, test, desktop );
202     SetWindowLongA( test, GWL_STYLE, 0 );
203     check_parents( test, desktop, 0, 0, 0, test, test );
204     DestroyWindow( test );
205
206     /* not owned popup with WS_MAXIMIZE */
207     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, 0 );
208     DestroyWindow( test );
209
210     /* owned popup */
211     test = create_tool_window( WS_POPUP, hwndMain );
212     trace( "created owned popup %p\n", test );
213     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
214     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
215     check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
216     SetWindowLongA( test, GWL_STYLE, 0 );
217     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
218     DestroyWindow( test );
219
220     /* owned popup with WS_MAXIMIZE */
221     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, hwndMain );
222     DestroyWindow( test );
223
224     /* top-level window owned by child (same as owned by top-level) */
225     test = create_tool_window( 0, child );
226     trace( "created top-level owned by child %p\n", test );
227     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
228     DestroyWindow( test );
229
230     /* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */
231     test = create_tool_window( WS_MAXIMIZE, child );
232     DestroyWindow( test );
233
234     /* popup owned by desktop (same as not owned) */
235     test = create_tool_window( WS_POPUP, desktop );
236     trace( "created popup owned by desktop %p\n", test );
237     check_parents( test, desktop, 0, 0, 0, test, test );
238     DestroyWindow( test );
239
240     /* popup owned by desktop (same as not owned) with WS_MAXIMIZE */
241     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, desktop );
242     DestroyWindow( test );
243
244     /* popup owned by child (same as owned by top-level) */
245     test = create_tool_window( WS_POPUP, child );
246     trace( "created popup owned by child %p\n", test );
247     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
248     DestroyWindow( test );
249
250     /* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */
251     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, child );
252     DestroyWindow( test );
253
254     /* not owned popup with WS_CHILD (same as WS_POPUP only) */
255     test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
256     trace( "created WS_CHILD popup %p\n", test );
257     check_parents( test, desktop, 0, 0, 0, test, test );
258     DestroyWindow( test );
259
260     /* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */
261     test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, 0 );
262     DestroyWindow( test );
263
264     /* owned popup with WS_CHILD (same as WS_POPUP only) */
265     test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
266     trace( "created owned WS_CHILD popup %p\n", test );
267     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
268     DestroyWindow( test );
269
270     /* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */
271     test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, hwndMain );
272     DestroyWindow( test );
273
274     /******************** parent changes *************************/
275     trace( "testing parent changes\n" );
276
277     /* desktop window */
278     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
279 #if 0 /* this test succeeds on NT but crashes on win9x systems */
280     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
281     ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" );
282     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
283     ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" );
284     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
285 #endif
286     /* normal child window */
287     test = create_tool_window( WS_CHILD, hwndMain );
288     trace( "created child %p\n", test );
289
290     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
291     ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain );
292     check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
293
294     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
295     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
296     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
297
298     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)desktop );
299     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
300     check_parents( test, desktop, 0, desktop, 0, test, desktop );
301
302     /* window is now child of desktop so GWL_HWNDPARENT changes owner from now on */
303     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
304     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
305     check_parents( test, desktop, child, desktop, child, test, desktop );
306
307     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
308     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
309     check_parents( test, desktop, 0, desktop, 0, test, desktop );
310     DestroyWindow( test );
311
312     /* not owned top-level window */
313     test = create_tool_window( 0, 0 );
314     trace( "created top-level %p\n", test );
315
316     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
317     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
318     check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
319
320     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
321     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
322     check_parents( test, desktop, child, 0, child, test, test );
323
324     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
325     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
326     check_parents( test, desktop, 0, 0, 0, test, test );
327     DestroyWindow( test );
328
329     /* not owned popup */
330     test = create_tool_window( WS_POPUP, 0 );
331     trace( "created popup %p\n", test );
332
333     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
334     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
335     check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
336
337     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
338     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
339     check_parents( test, desktop, child, child, child, test, hwndMain );
340
341     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
342     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
343     check_parents( test, desktop, 0, 0, 0, test, test );
344     DestroyWindow( test );
345
346     /* normal child window */
347     test = create_tool_window( WS_CHILD, hwndMain );
348     trace( "created child %p\n", test );
349
350     ret = SetParent( test, desktop );
351     ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain );
352     check_parents( test, desktop, 0, desktop, 0, test, desktop );
353
354     ret = SetParent( test, child );
355     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
356     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
357
358     ret = SetParent( test, hwndMain2 );
359     ok( ret == child, "SetParent return value %p expected %p\n", ret, child );
360     check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
361     DestroyWindow( test );
362
363     /* not owned top-level window */
364     test = create_tool_window( 0, 0 );
365     trace( "created top-level %p\n", test );
366
367     ret = SetParent( test, child );
368     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
369     check_parents( test, child, child, 0, 0, hwndMain, test );
370     DestroyWindow( test );
371
372     /* owned popup */
373     test = create_tool_window( WS_POPUP, hwndMain2 );
374     trace( "created owned popup %p\n", test );
375
376     ret = SetParent( test, child );
377     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
378     check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
379
380     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)hwndMain );
381     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
382     check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
383     DestroyWindow( test );
384
385     /**************** test owner destruction *******************/
386
387     /* owned child popup */
388     owner = create_tool_window( 0, 0 );
389     test = create_tool_window( WS_POPUP, owner );
390     trace( "created owner %p and popup %p\n", owner, test );
391     ret = SetParent( test, child );
392     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
393     check_parents( test, child, child, owner, owner, hwndMain, owner );
394     /* window is now child of 'child' but owned by 'owner' */
395     DestroyWindow( owner );
396     ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
397     check_parents( test, child, child, owner, owner, hwndMain, owner );
398     ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
399     DestroyWindow(test);
400
401     /* owned top-level popup */
402     owner = create_tool_window( 0, 0 );
403     test = create_tool_window( WS_POPUP, owner );
404     trace( "created owner %p and popup %p\n", owner, test );
405     check_parents( test, desktop, owner, owner, owner, test, owner );
406     DestroyWindow( owner );
407     ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test );
408
409     /* top-level popup owned by child */
410     owner = create_tool_window( WS_CHILD, hwndMain2 );
411     test = create_tool_window( WS_POPUP, 0 );
412     trace( "created owner %p and popup %p\n", owner, test );
413     ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)owner );
414     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
415     check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
416     DestroyWindow( owner );
417     ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
418     ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
419     check_parents( test, desktop, owner, owner, owner, test, owner );
420     DestroyWindow(test);
421
422     /* final cleanup */
423     DestroyWindow(child);
424 }
425
426
427 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
428 {
429     switch (msg)
430     {
431         case WM_GETMINMAXINFO:
432         {
433             MINMAXINFO* minmax = (MINMAXINFO *)lparam;
434
435             trace("hwnd %p, WM_GETMINMAXINFO, %08x, %08lx\n", hwnd, wparam, lparam);
436             trace("ptReserved (%ld,%ld), ptMaxSize (%ld,%ld), ptMaxPosition (%ld,%ld)\n"
437                   "       ptMinTrackSize (%ld,%ld), ptMaxTrackSize (%ld,%ld)\n",
438                   minmax->ptReserved.x, minmax->ptReserved.y,
439                   minmax->ptMaxSize.x, minmax->ptMaxSize.y,
440                   minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
441                   minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
442                   minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
443             SetWindowLongA(hwnd, GWL_USERDATA, 0x20031021);
444             break;
445         }
446         case WM_NCCREATE:
447         {
448             BOOL got_getminmaxinfo = GetWindowLongA(hwnd, GWL_USERDATA) == 0x20031021;
449             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
450
451             trace("WM_NCCREATE: hwnd %p, parent %p, style %08lx\n", hwnd, cs->hwndParent, cs->style);
452             if (got_getminmaxinfo)
453                 trace("%p got WM_GETMINMAXINFO\n", hwnd);
454
455             if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
456                 ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
457             else
458                 ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
459             break;
460         }
461     }
462
463     return DefWindowProcA(hwnd, msg, wparam, lparam);
464 }
465
466 static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
467 {
468     switch (msg)
469     {
470         case WM_GETMINMAXINFO:
471         {
472             MINMAXINFO* minmax = (MINMAXINFO *)lparam;
473
474             trace("hwnd %p, WM_GETMINMAXINFO, %08x, %08lx\n", hwnd, wparam, lparam);
475             trace("ptReserved (%ld,%ld), ptMaxSize (%ld,%ld), ptMaxPosition (%ld,%ld)\n"
476                   "       ptMinTrackSize (%ld,%ld), ptMaxTrackSize (%ld,%ld)\n",
477                   minmax->ptReserved.x, minmax->ptReserved.y,
478                   minmax->ptMaxSize.x, minmax->ptMaxSize.y,
479                   minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
480                   minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
481                   minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
482             SetWindowLongA(hwnd, GWL_USERDATA, 0x20031021);
483             break;
484         }
485         case WM_NCCREATE:
486         {
487             BOOL got_getminmaxinfo = GetWindowLongA(hwnd, GWL_USERDATA) == 0x20031021;
488             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
489
490             trace("WM_NCCREATE: hwnd %p, parent %p, style %08lx\n", hwnd, cs->hwndParent, cs->style);
491             if (got_getminmaxinfo)
492                 trace("%p got WM_GETMINMAXINFO\n", hwnd);
493
494             if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
495                 ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
496             else
497                 ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
498             break;
499         }
500     }
501
502     return DefWindowProcA(hwnd, msg, wparam, lparam);
503 }
504
505 static BOOL RegisterWindowClasses(void)
506 {
507     WNDCLASSA cls;
508
509     cls.style = 0;
510     cls.lpfnWndProc = main_window_procA;
511     cls.cbClsExtra = 0;
512     cls.cbWndExtra = 0;
513     cls.hInstance = GetModuleHandleA(0);
514     cls.hIcon = 0;
515     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
516     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
517     cls.lpszMenuName = NULL;
518     cls.lpszClassName = "MainWindowClass";
519
520     if(!RegisterClassA(&cls)) return FALSE;
521
522     cls.style = 0;
523     cls.lpfnWndProc = tool_window_procA;
524     cls.cbClsExtra = 0;
525     cls.cbWndExtra = 0;
526     cls.hInstance = GetModuleHandleA(0);
527     cls.hIcon = 0;
528     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
529     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
530     cls.lpszMenuName = NULL;
531     cls.lpszClassName = "ToolWindowClass";
532
533     if(!RegisterClassA(&cls)) return FALSE;
534
535     return TRUE;
536 }
537
538 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 
539
540     static const char *CBT_code_name[10] = {
541         "HCBT_MOVESIZE",
542         "HCBT_MINMAX",
543         "HCBT_QS",
544         "HCBT_CREATEWND",
545         "HCBT_DESTROYWND",
546         "HCBT_ACTIVATE",
547         "HCBT_CLICKSKIPPED",
548         "HCBT_KEYSKIPPED",
549         "HCBT_SYSCOMMAND",
550         "HCBT_SETFOCUS" };
551     const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
552
553     trace("CBT: %d (%s), %08x, %08lx\n", nCode, code_name, wParam, lParam);
554
555     switch (nCode)
556     {
557         case HCBT_CREATEWND:
558         {
559             CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
560             trace("HCBT_CREATEWND: hwnd %p, parent %p, style %08lx\n",
561                   (HWND)wParam, createwnd->lpcs->hwndParent, createwnd->lpcs->style);
562             ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
563             break;
564         }
565     }
566
567     return CallNextHookEx(hhook, nCode, wParam, lParam);
568 }
569
570 static void test_shell_window()
571 {
572     BOOL ret;
573     DWORD error;
574     HMODULE hinst, hUser32;
575     BOOL (WINAPI*SetShellWindow)(HWND);
576     BOOL (WINAPI*SetShellWindowEx)(HWND, HWND);
577     HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5;
578     HWND shellWindow, nextWnd;
579
580     shellWindow = GetShellWindow();
581     hinst = GetModuleHandle(0);
582     hUser32 = GetModuleHandleA("user32");
583
584     SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow");
585     SetShellWindowEx = (void *)GetProcAddress(hUser32, "SetShellWindowEx");
586
587     trace("previous shell window: %p\n", shellWindow);
588
589     if (shellWindow) {
590         DWORD pid;
591         HANDLE hProcess;
592
593         ret = DestroyWindow(shellWindow);
594         error = GetLastError();
595
596         ok(!ret, "DestroyWindow(shellWindow)\n");
597         /* passes on Win XP, but not on Win98
598         ok(error==ERROR_ACCESS_DENIED, "ERROR_ACCESS_DENIED after DestroyWindow(shellWindow)\n"); */
599
600         /* close old shell instance */
601         GetWindowThreadProcessId(shellWindow, &pid);
602         hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
603         ret = TerminateProcess(hProcess, 0);
604         ok(ret, "termination of previous shell process failed: GetLastError()=%ld\n", GetLastError());
605         WaitForSingleObject(hProcess, INFINITE);    /* wait for termination */
606         CloseHandle(hProcess);
607     }
608
609     hwnd1 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST1"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0);
610     trace("created window 1: %p\n", hwnd1);
611
612     ret = SetShellWindow(hwnd1);
613     ok(ret, "first call to SetShellWindow(hwnd1)\n");
614     shellWindow = GetShellWindow();
615     ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow);
616
617     ret = SetShellWindow(hwnd1);
618     ok(!ret, "second call to SetShellWindow(hwnd1)\n");
619
620     ret = SetShellWindow(0);
621     error = GetLastError();
622     /* passes on Win XP, but not on Win98
623     ok(!ret, "reset shell window by SetShellWindow(0)\n");
624     ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */
625
626     ret = SetShellWindow(hwnd1);
627     /* passes on Win XP, but not on Win98
628     ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */
629
630     todo_wine
631     {
632         SetWindowLong(hwnd1, GWL_EXSTYLE, GetWindowLong(hwnd1,GWL_EXSTYLE)|WS_EX_TOPMOST);
633         ret = GetWindowLong(hwnd1,GWL_EXSTYLE)&WS_EX_TOPMOST? TRUE: FALSE;
634         ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n");
635     }
636
637     ret = DestroyWindow(hwnd1);
638     ok(ret, "DestroyWindow(hwnd1)\n");
639
640     hwnd2 = CreateWindowEx(WS_EX_TOPMOST, TEXT("#32770"), TEXT("TEST2"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
641     trace("created window 2: %p\n", hwnd2);
642     ret = SetShellWindow(hwnd2);
643     ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n");
644
645     hwnd3 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST3"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
646     trace("created window 3: %p\n", hwnd3);
647
648     hwnd4 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST4"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0);
649     trace("created window 4: %p\n", hwnd4);
650
651     nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
652     ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd);
653
654     ret = SetShellWindow(hwnd4);
655     ok(ret, "SetShellWindow(hwnd4)\n");
656     shellWindow = GetShellWindow();
657     ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
658
659     nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
660     ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
661
662     ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
663     ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
664
665     ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
666     ok(ret, "SetWindowPos(hwnd4, hwnd3\n");
667
668     ret = SetShellWindow(hwnd3);
669     ok(!ret, "SetShellWindow(hwnd3)\n");
670     shellWindow = GetShellWindow();
671     ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
672
673     hwnd5 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST5"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
674     trace("created window 5: %p\n", hwnd5);
675     ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
676     ok(ret, "SetWindowPos(hwnd4, hwnd5)\n");
677
678     todo_wine
679     {
680         nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
681         ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd);
682     }
683
684     /* destroy test windows */
685     DestroyWindow(hwnd2);
686     DestroyWindow(hwnd3);
687     DestroyWindow(hwnd4);
688     DestroyWindow(hwnd5);
689 }
690
691 /************** MDI test ****************/
692
693 static const char mdi_lParam_test_message[] = "just a test string";
694
695 static void test_MDI_create(HWND parent, HWND mdi_client)
696 {
697     MDICREATESTRUCTA mdi_cs;
698     HWND mdi_child;
699     static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
700     static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
701     BOOL isWin9x = FALSE;
702
703     mdi_cs.szClass = "MDI_child_Class_1";
704     mdi_cs.szTitle = "MDI child";
705     mdi_cs.hOwner = GetModuleHandle(0);
706     mdi_cs.x = CW_USEDEFAULT;
707     mdi_cs.y = CW_USEDEFAULT;
708     mdi_cs.cx = CW_USEDEFAULT;
709     mdi_cs.cy = CW_USEDEFAULT;
710     mdi_cs.style = 0;
711     mdi_cs.lParam = (LPARAM)mdi_lParam_test_message;
712     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
713     ok(mdi_child != 0, "MDI child creation failed\n");
714     DestroyWindow(mdi_child);
715
716     mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
717     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
718     ok(mdi_child != 0, "MDI child creation failed\n");
719     DestroyWindow(mdi_child);
720
721     mdi_cs.style = 0xffffffff; /* with WS_POPUP */
722     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
723     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
724     {
725         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
726         DestroyWindow(mdi_child);
727     }
728     else
729         ok(mdi_child != 0, "MDI child creation failed\n");
730
731     /* test MDICREATESTRUCT A<->W mapping */
732     /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
733     mdi_cs.style = 0;
734     mdi_cs.szClass = (LPCSTR)classW;
735     mdi_cs.szTitle = (LPCSTR)titleW;
736     SetLastError(0xdeadbeef);
737     mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
738     if (!mdi_child)
739     {
740         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
741             isWin9x = TRUE;
742         else
743             ok(mdi_child != 0, "MDI child creation failed\n");
744     }
745     DestroyWindow(mdi_child);
746
747     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
748                                  0,
749                                  CW_USEDEFAULT, CW_USEDEFAULT,
750                                  CW_USEDEFAULT, CW_USEDEFAULT,
751                                  mdi_client, GetModuleHandle(0),
752                                  (LPARAM)mdi_lParam_test_message);
753     ok(mdi_child != 0, "MDI child creation failed\n");
754     DestroyWindow(mdi_child);
755
756     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
757                                  0x7fffffff, /* without WS_POPUP */
758                                  CW_USEDEFAULT, CW_USEDEFAULT,
759                                  CW_USEDEFAULT, CW_USEDEFAULT,
760                                  mdi_client, GetModuleHandle(0),
761                                  (LPARAM)mdi_lParam_test_message);
762     ok(mdi_child != 0, "MDI child creation failed\n");
763     DestroyWindow(mdi_child);
764
765     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
766                                  0xffffffff, /* with WS_POPUP */
767                                  CW_USEDEFAULT, CW_USEDEFAULT,
768                                  CW_USEDEFAULT, CW_USEDEFAULT,
769                                  mdi_client, GetModuleHandle(0),
770                                  (LPARAM)mdi_lParam_test_message);
771     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
772     {
773         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
774         DestroyWindow(mdi_child);
775     }
776     else
777         ok(mdi_child != 0, "MDI child creation failed\n");
778
779     /* test MDICREATESTRUCT A<->W mapping */
780     SetLastError(0xdeadbeef);
781     mdi_child = CreateMDIWindowW(classW, titleW,
782                                  0,
783                                  CW_USEDEFAULT, CW_USEDEFAULT,
784                                  CW_USEDEFAULT, CW_USEDEFAULT,
785                                  mdi_client, GetModuleHandle(0),
786                                  (LPARAM)mdi_lParam_test_message);
787     if (!mdi_child)
788     {
789         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
790             isWin9x = TRUE;
791         else
792             ok(mdi_child != 0, "MDI child creation failed\n");
793     }
794     DestroyWindow(mdi_child);
795
796     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
797                                 0,
798                                 CW_USEDEFAULT, CW_USEDEFAULT,
799                                 CW_USEDEFAULT, CW_USEDEFAULT,
800                                 mdi_client, 0, GetModuleHandle(0),
801                                 (LPVOID)mdi_lParam_test_message);
802     ok(mdi_child != 0, "MDI child creation failed\n");
803     DestroyWindow(mdi_child);
804
805     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
806                                 0x7fffffff, /* without WS_POPUP */
807                                 CW_USEDEFAULT, CW_USEDEFAULT,
808                                 CW_USEDEFAULT, CW_USEDEFAULT,
809                                 mdi_client, 0, GetModuleHandle(0),
810                                 (LPVOID)mdi_lParam_test_message);
811     ok(mdi_child != 0, "MDI child creation failed\n");
812     DestroyWindow(mdi_child);
813
814     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
815                                 0xffffffff, /* with WS_POPUP */
816                                 CW_USEDEFAULT, CW_USEDEFAULT,
817                                 CW_USEDEFAULT, CW_USEDEFAULT,
818                                 mdi_client, 0, GetModuleHandle(0),
819                                 (LPVOID)mdi_lParam_test_message);
820     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
821     {
822         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
823         DestroyWindow(mdi_child);
824     }
825     else
826         ok(mdi_child != 0, "MDI child creation failed\n");
827
828     /* test MDICREATESTRUCT A<->W mapping */
829     SetLastError(0xdeadbeef);
830     mdi_child = CreateWindowExW(WS_EX_MDICHILD, classW, titleW,
831                                 0,
832                                 CW_USEDEFAULT, CW_USEDEFAULT,
833                                 CW_USEDEFAULT, CW_USEDEFAULT,
834                                 mdi_client, 0, GetModuleHandle(0),
835                                 (LPVOID)mdi_lParam_test_message);
836     if (!mdi_child)
837     {
838         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
839             isWin9x = TRUE;
840         else
841             ok(mdi_child != 0, "MDI child creation failed\n");
842     }
843     DestroyWindow(mdi_child);
844
845     /* This test fails on Win9x */
846     if (!isWin9x)
847     {
848         mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
849                                 WS_CHILD,
850                                 CW_USEDEFAULT, CW_USEDEFAULT,
851                                 CW_USEDEFAULT, CW_USEDEFAULT,
852                                 parent, 0, GetModuleHandle(0),
853                                 (LPVOID)mdi_lParam_test_message);
854         ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
855     }
856
857     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
858                                 WS_CHILD, /* without WS_POPUP */
859                                 CW_USEDEFAULT, CW_USEDEFAULT,
860                                 CW_USEDEFAULT, CW_USEDEFAULT,
861                                 mdi_client, 0, GetModuleHandle(0),
862                                 (LPVOID)mdi_lParam_test_message);
863     ok(mdi_child != 0, "MDI child creation failed\n");
864     DestroyWindow(mdi_child);
865
866     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
867                                 WS_CHILD | WS_POPUP, /* with WS_POPUP */
868                                 CW_USEDEFAULT, CW_USEDEFAULT,
869                                 CW_USEDEFAULT, CW_USEDEFAULT,
870                                 mdi_client, 0, GetModuleHandle(0),
871                                 (LPVOID)mdi_lParam_test_message);
872     ok(mdi_child != 0, "MDI child creation failed\n");
873     DestroyWindow(mdi_child);
874 }
875
876 static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
877 {
878     switch (msg)
879     {
880         case WM_NCCREATE:
881         case WM_CREATE:
882         {
883             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
884             MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs->lpCreateParams;
885
886             ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
887             ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
888
889             ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
890             ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
891             ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
892             ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
893             ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
894
895             /* MDICREATESTRUCT should have original values */
896             ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff,
897                 "mdi_cs->style does not match (%08lx)\n", mdi_cs->style);
898             ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
899             ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
900             ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
901             ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
902
903             /* CREATESTRUCT should have fixed values */
904             ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
905             ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
906
907             /* cx/cy == CW_USEDEFAULT are translated to NOT zero values */
908             ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx);
909             ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy);
910
911             ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
912
913             if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
914             {
915                 ok(cs->style == (mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS),
916                    "cs->style does not match (%08lx)\n", cs->style);
917             }
918             else
919             {
920                 DWORD style = mdi_cs->style;
921                 style &= ~WS_POPUP;
922                 style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
923                     WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
924                 ok(cs->style == style,
925                    "cs->style does not match (%08lx)\n", cs->style);
926             }
927             break;
928         }
929     }
930     return DefMDIChildProcA(hwnd, msg, wparam, lparam);
931 }
932
933 static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
934 {
935     switch (msg)
936     {
937         case WM_NCCREATE:
938         case WM_CREATE:
939         {
940             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
941
942             ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
943             ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
944
945             ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
946             ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
947
948             /* CREATESTRUCT should have fixed values */
949             /* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT,
950                while NT does. */
951             /*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/
952             ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
953
954             /* cx/cy == CW_USEDEFAULT are translated to 0 */
955             ok(cs->cx == 0, "%d != 0\n", cs->cx);
956             ok(cs->cy == 0, "%d != 0\n", cs->cy);
957             break;
958         }
959     }
960     return DefWindowProcA(hwnd, msg, wparam, lparam);
961 }
962
963 static LRESULT WINAPI mdi_main_wnd_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
964 {
965     static HWND mdi_client;
966
967     switch (msg)
968     {
969         case WM_CREATE:
970         {
971             CLIENTCREATESTRUCT client_cs;
972             RECT rc;
973
974             GetClientRect(hwnd, &rc);
975
976             client_cs.hWindowMenu = 0;
977             client_cs.idFirstChild = 1;
978
979             /* MDIClient without MDIS_ALLCHILDSTYLES */
980             mdi_client = CreateWindowExA(0, "mdiclient",
981                                          NULL,
982                                          WS_CHILD /*| WS_VISIBLE*/,
983                                           /* tests depend on a not zero MDIClient size */
984                                          0, 0, rc.right, rc.bottom,
985                                          hwnd, 0, GetModuleHandle(0),
986                                          (LPVOID)&client_cs);
987             assert(mdi_client);
988             test_MDI_create(hwnd, mdi_client);
989             DestroyWindow(mdi_client);
990
991             /* MDIClient with MDIS_ALLCHILDSTYLES */
992             mdi_client = CreateWindowExA(0, "mdiclient",
993                                          NULL,
994                                          WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
995                                           /* tests depend on a not zero MDIClient size */
996                                          0, 0, rc.right, rc.bottom,
997                                          hwnd, 0, GetModuleHandle(0),
998                                          (LPVOID)&client_cs);
999             assert(mdi_client);
1000             test_MDI_create(hwnd, mdi_client);
1001             DestroyWindow(mdi_client);
1002             break;
1003         }
1004
1005         case WM_CLOSE:
1006             PostQuitMessage(0);
1007             break;
1008     }
1009     return DefFrameProcA(hwnd, mdi_client, msg, wparam, lparam);
1010 }
1011
1012 static BOOL mdi_RegisterWindowClasses(void)
1013 {
1014     WNDCLASSA cls;
1015
1016     cls.style = 0;
1017     cls.lpfnWndProc = mdi_main_wnd_procA;
1018     cls.cbClsExtra = 0;
1019     cls.cbWndExtra = 0;
1020     cls.hInstance = GetModuleHandleA(0);
1021     cls.hIcon = 0;
1022     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1023     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1024     cls.lpszMenuName = NULL;
1025     cls.lpszClassName = "MDI_parent_Class";
1026     if(!RegisterClassA(&cls)) return FALSE;
1027
1028     cls.lpfnWndProc = mdi_child_wnd_proc_1;
1029     cls.lpszClassName = "MDI_child_Class_1";
1030     if(!RegisterClassA(&cls)) return FALSE;
1031
1032     cls.lpfnWndProc = mdi_child_wnd_proc_2;
1033     cls.lpszClassName = "MDI_child_Class_2";
1034     if(!RegisterClassA(&cls)) return FALSE;
1035
1036     return TRUE;
1037 }
1038
1039 static void test_mdi(void)
1040 {
1041     HWND mdi_hwndMain;
1042     /*MSG msg;*/
1043
1044     if (!mdi_RegisterWindowClasses()) assert(0);
1045
1046     mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window",
1047                                    WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1048                                    WS_MAXIMIZEBOX /*| WS_VISIBLE*/,
1049                                    100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1050                                    GetDesktopWindow(), 0,
1051                                    GetModuleHandle(0), NULL);
1052     assert(mdi_hwndMain);
1053 /*
1054     while(GetMessage(&msg, 0, 0, 0))
1055     {
1056         TranslateMessage(&msg);
1057         DispatchMessage(&msg);
1058     }
1059 */
1060 }
1061
1062 static void test_icons(void)
1063 {
1064     WNDCLASSEXA cls;
1065     HWND hwnd;
1066     HICON icon = LoadIconA(0, (LPSTR)IDI_APPLICATION);
1067     HICON icon2 = LoadIconA(0, (LPSTR)IDI_QUESTION);
1068     HICON small_icon = LoadImageA(0, (LPSTR)IDI_APPLICATION, IMAGE_ICON,
1069                                   GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
1070     HICON res;
1071
1072     cls.cbSize = sizeof(cls);
1073     cls.style = 0;
1074     cls.lpfnWndProc = DefWindowProcA;
1075     cls.cbClsExtra = 0;
1076     cls.cbWndExtra = 0;
1077     cls.hInstance = 0;
1078     cls.hIcon = LoadIconA(0, (LPSTR)IDI_HAND);
1079     cls.hIconSm = small_icon;
1080     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1081     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1082     cls.lpszMenuName = NULL;
1083     cls.lpszClassName = "IconWindowClass";
1084
1085     RegisterClassExA(&cls);
1086
1087     hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
1088                            100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
1089     assert( hwnd );
1090
1091     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1092     ok( res == 0, "wrong big icon %p/0\n", res );
1093     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
1094     ok( res == 0, "wrong previous big icon %p/0\n", res );
1095     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1096     ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
1097     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
1098     ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
1099     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1100     ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
1101
1102     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
1103     ok( res == 0, "wrong small icon %p/0\n", res );
1104     /* this test is XP specific */
1105     /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
1106     ok( res != 0, "wrong small icon %p\n", res );*/
1107     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
1108     ok( res == 0, "wrong previous small icon %p/0\n", res );
1109     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
1110     ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
1111     /* this test is XP specific */
1112     /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
1113     ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );*/
1114     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
1115     ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
1116     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
1117     ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
1118     /* this test is XP specific */
1119     /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
1120     ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );*/
1121
1122     /* make sure the big icon hasn't changed */
1123     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1124     ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
1125 }
1126
1127 START_TEST(win)
1128 {
1129     pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
1130
1131     if (!RegisterWindowClasses()) assert(0);
1132
1133     hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
1134     assert(hhook);
1135
1136     hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
1137                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1138                                WS_MAXIMIZEBOX | WS_POPUP,
1139                                100, 100, 200, 200,
1140                                0, 0, 0, NULL);
1141     hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
1142                                 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1143                                 WS_MAXIMIZEBOX | WS_POPUP,
1144                                 100, 100, 200, 200,
1145                                 0, 0, 0, NULL);
1146     assert( hwndMain );
1147     assert( hwndMain2 );
1148
1149     test_parent_owner();
1150     test_shell_window();
1151
1152     test_mdi();
1153     test_icons();
1154
1155     UnhookWindowsHookEx(hhook);
1156 }